Enforce cdecl calling convention for callable code, global variables, symbol table for exporting programmes

This commit is contained in:
Simon Robertshaw
2013-02-09 13:44:09 +00:00
parent f3cfa6106b
commit 14991cba5f
19 changed files with 532 additions and 74 deletions

View File

@@ -212,6 +212,8 @@ extern unsigned char ZSIZE;
#define TPT_NO_INLINE inline #define TPT_NO_INLINE inline
#endif #endif
#define TPT_VM_CALLABLE __cdecl
#define SDEUT #define SDEUT
//#define REALHEAT //#define REALHEAT

View File

@@ -1336,7 +1336,7 @@ int LuaScriptInterface::elements_property(lua_State * l)
updateVirtualMachines[id] = (pim::VirtualMachine*)lua_touserdata(l, 3); updateVirtualMachines[id] = (pim::VirtualMachine*)lua_touserdata(l, 3);
if(updateVirtualMachines[id]->IsCompiled()) if(updateVirtualMachines[id]->IsCompiled())
{ {
updateNativeCode[id] = (NativeUpdateFunc)updateVirtualMachines[id]->GetNativeEntryPoint(0); updateNativeCode[id] = (NativeUpdateFunc)updateVirtualMachines[id]->GetNativeEntryPoint("update", "I", "III");
luacon_sim->elements[id].Update = &updateNative; luacon_sim->elements[id].Update = &updateNative;
} }
else else
@@ -1481,7 +1481,7 @@ int LuaScriptInterface::virtualMachine_loadProgram(lua_State * l)
return luaL_error(l, "Unable to load program"); return luaL_error(l, "Unable to load program");
} }
lua_pushlightuserdata(l, newVM);*/ lua_pushlightuserdata(l, newVM);*/
std::string programSource(lua_tostring(l, 1)); std::string programSource(lua_tostring(l, 1), lua_strlen(l, 1));
std::stringstream input(programSource); std::stringstream input(programSource);

View File

@@ -2,6 +2,7 @@
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <cstdio>
#include "Token.h" #include "Token.h"
namespace pim namespace pim
@@ -36,5 +37,34 @@ namespace pim
} }
~TypeException() throw() {}; ~TypeException() throw() {};
}; };
class ScannerCharacterException: public std::exception
{
char * error;
public:
ScannerCharacterException(char character, int lineNumber, int characterNumber) {
error = new char[256];
sprintf(error, "Unexpected character '%c' at line %d, char %d", character, lineNumber, characterNumber);
}
const char * what() const throw()
{
return error;
}
~ScannerCharacterException() throw() { delete[] error; };
};
} }
class FunctionNotFoundException: public std::exception
{
char * error;
public:
FunctionNotFoundException(std::string functionName, std::string returnType, std::string arguments)
{
error = new char[functionName.length() + returnType.length() + arguments.length()];
sprintf(error, "Could not find function \"%s\" of type %s(%s)", functionName.c_str(), returnType.c_str(), arguments.c_str());
}
const char * what() const throw()
{
return error;
}
~FunctionNotFoundException() throw() { delete[] error; };
};
} }

View File

@@ -11,9 +11,12 @@ namespace pim
{ {
Generator::Generator() : Generator::Generator() :
typeStack(), typeStack(),
globalScope(new Scope()),
output(std::cout), output(std::cout),
labelCounter(0), labelCounter(0),
programCounter(0) programCounter(0),
program()
{ {
} }
@@ -33,16 +36,19 @@ namespace pim
void Generator::writeOpcode(int opcode) void Generator::writeOpcode(int opcode)
{ {
programCounter++; programCounter++;
printf("Opcode: %d\n", opcode);
program.push_back(opcode); program.push_back(opcode);
} }
void Generator::writeConstant(std::string constant) void Generator::writeConstant(std::string constant)
{ {
printf("Constant: %s\n", constant.c_str());
writeConstant(format::StringToNumber<int>(constant)); writeConstant(format::StringToNumber<int>(constant));
} }
void Generator::writeConstant(int constant) void Generator::writeConstant(int constant)
{ {
printf("Constant: %d\n", constant);
program.push_back(constant & 0xFF); program.push_back(constant & 0xFF);
program.push_back((constant>>8) & 0xFF); program.push_back((constant>>8) & 0xFF);
program.push_back((constant>>16) & 0xFF); program.push_back((constant>>16) & 0xFF);
@@ -51,6 +57,7 @@ namespace pim
void Generator::writeConstantPlaceholderOffset(int value, int * offset) void Generator::writeConstantPlaceholderOffset(int value, int * offset)
{ {
printf("Constant: %d\n", value);
valueOffsetPlaceholders.push_back(ValueOffsetPlaceholder(program.size(), std::pair<int, int*>(value, offset))); valueOffsetPlaceholders.push_back(ValueOffsetPlaceholder(program.size(), std::pair<int, int*>(value, offset)));
program.push_back(0); program.push_back(0);
program.push_back(0); program.push_back(0);
@@ -60,6 +67,7 @@ namespace pim
void Generator::writeConstantPlaceholder(std::string label) void Generator::writeConstantPlaceholder(std::string label)
{ {
printf("Constant: %s\n", label.c_str());
placeholders.push_back(Placeholder(program.size(), label)); placeholders.push_back(Placeholder(program.size(), label));
program.push_back(0); program.push_back(0);
program.push_back(0); program.push_back(0);
@@ -69,6 +77,7 @@ namespace pim
void Generator::writeConstantPlaceholder(int * value) void Generator::writeConstantPlaceholder(int * value)
{ {
printf("Constant: %p\n", value);
valuePlaceholders.push_back(ValuePlaceholder(program.size(), value)); valuePlaceholders.push_back(ValuePlaceholder(program.size(), value));
program.push_back(0); program.push_back(0);
program.push_back(0); program.push_back(0);
@@ -78,6 +87,7 @@ namespace pim
void Generator::writeConstantPropertyPlaceholder(std::string property) void Generator::writeConstantPropertyPlaceholder(std::string property)
{ {
printf("Constant: %s\n", property.c_str());
propertyPlaceholders.push_back(PropertyPlaceholder(program.size(), property)); propertyPlaceholders.push_back(PropertyPlaceholder(program.size(), property));
program.push_back(0); program.push_back(0);
program.push_back(0); program.push_back(0);
@@ -87,6 +97,7 @@ namespace pim
void Generator::writeConstantMacroPlaceholder(std::string macro) void Generator::writeConstantMacroPlaceholder(std::string macro)
{ {
printf("Constant: %s\n", macro.c_str());
macroPlaceholders.push_back(MacroPlaceholder(program.size(), macro)); macroPlaceholders.push_back(MacroPlaceholder(program.size(), macro));
program.push_back(0); program.push_back(0);
program.push_back(0); program.push_back(0);
@@ -150,13 +161,18 @@ namespace pim
} }
//Build file //Build file
int macroSizePos, propSizePos, codeSizePos, macroSize = 0, propSize = 0, codeSize = program.size(); int macroSizePos, propSizePos, codeSizePos, symtableSizePos, macroSize = 0, propSize = 0, symtableSize = 0, codeSize = program.size();
std::vector<unsigned char> file; std::vector<unsigned char> file;
file.push_back('P'); file.push_back('P');
file.push_back('V'); file.push_back('V');
file.push_back('M'); file.push_back('M');
file.push_back('1'); file.push_back('1');
//Heap size
file.push_back(globalScope->FrameSize & 0xFF);
file.push_back((globalScope->FrameSize >> 8) & 0xFF);
file.push_back((globalScope->FrameSize >> 16) & 0xFF);
file.push_back((globalScope->FrameSize >> 24) & 0xFF);
macroSizePos = file.size(); macroSizePos = file.size();
file.push_back(0); file.push_back(0);
@@ -170,6 +186,12 @@ namespace pim
file.push_back(0); file.push_back(0);
file.push_back(0); file.push_back(0);
symtableSizePos = file.size();
file.push_back(0);
file.push_back(0);
file.push_back(0);
file.push_back(0);
codeSizePos = file.size(); codeSizePos = file.size();
file.push_back(0); file.push_back(0);
file.push_back(0); file.push_back(0);
@@ -223,6 +245,50 @@ namespace pim
file[propSizePos+2] = (propSize >> 16) & 0xFF; file[propSizePos+2] = (propSize >> 16) & 0xFF;
file[propSizePos+3] = (propSize >> 24) & 0xFF; file[propSizePos+3] = (propSize >> 24) & 0xFF;
for(std::vector<Definition*>::iterator iter = globalScope->Definitions.begin(), end = globalScope->Definitions.end(); iter != end; ++iter)
{
Definition * d = *iter;
if(d->DefinitionType == Definition::Function)
file.push_back(255);
else
file.push_back(d->Type);
symtableSize++;
file.push_back(d->Name.length());
symtableSize++;
file.insert(file.end(), d->Name.begin(), d->Name.end());
symtableSize += d->Name.length();
file.push_back(d->StackPosition);
file.push_back((d->StackPosition >> 8) & 0xFF);
file.push_back((d->StackPosition >> 16) & 0xFF);
file.push_back((d->StackPosition >> 24) & 0xFF);
symtableSize += 4;
if(d->DefinitionType == Definition::Function)
{
FunctionDefinition * fd = (FunctionDefinition*)d;
if(fd->HasReturn)
file.push_back(fd->Type);
else
file.push_back(255);
symtableSize++;
file.push_back((char)fd->Arguments.size());
symtableSize++;
for(std::vector<int>::iterator iter = fd->Arguments.begin(), end = fd->Arguments.end(); iter != end; ++iter)
{
file.push_back((int)*iter);
symtableSize++;
}
}
}
file[symtableSizePos] = symtableSize & 0xFF;
file[symtableSizePos+1] = (symtableSize >> 8) & 0xFF;
file[symtableSizePos+2] = (symtableSize >> 16) & 0xFF;
file[symtableSizePos+3] = (symtableSize >> 24) & 0xFF;
file.insert(file.end(), program.begin(), program.end()); file.insert(file.end(), program.begin(), program.end());
file[codeSizePos] = codeSize & 0xFF; file[codeSizePos] = codeSize & 0xFF;
@@ -230,6 +296,8 @@ namespace pim
file[codeSizePos+2] = (codeSize >> 16) & 0xFF; file[codeSizePos+2] = (codeSize >> 16) & 0xFF;
file[codeSizePos+3] = (codeSize >> 24) & 0xFF; file[codeSizePos+3] = (codeSize >> 24) & 0xFF;
printf("codeSize: %d, codeSizePos: %d\n", codeSize, codeSizePos);
std::ofstream newFile("test.pvm"); std::ofstream newFile("test.pvm");
for(std::vector<unsigned char>::iterator iter = file.begin(), end = file.end(); iter != end; ++iter) for(std::vector<unsigned char>::iterator iter = file.begin(), end = file.end(); iter != end; ++iter)
{ {
@@ -360,15 +428,51 @@ namespace pim
throw TypeException(typeStack.top(), type); throw TypeException(typeStack.top(), type);
} }
void Generator::NewFunction()
{
funcDef = new FunctionDefinition();
}
void Generator::FunctionType(int type)
{
funcDef->HasReturn = true;
funcDef->Type = type;
}
void Generator::FunctionArgument(int type)
{
funcDef->Arguments.push_back(type);
}
void Generator::DeclareFunction(std::string name)
{
funcDef->Name = name;
funcDef->StackPosition = programCounter;
globalScope->Definitions.push_back(funcDef);
funcDef = NULL;
writeOpcode(Opcode::Begin);
output << "begin" << std::endl;
}
void Generator::ScopeVariable(std::string label) void Generator::ScopeVariable(std::string label)
{ {
currentScope->Definitions.push_back(Definition(label, variableType, currentScope->LocalFrameSize, currentScope)); currentScope->Definitions.push_back(new Definition(label, variableType, currentScope->LocalFrameSize, currentScope));
currentScope->FrameSize += 4; currentScope->FrameSize += 4;
currentScope->LocalFrameSize += 4; currentScope->LocalFrameSize += 4;
output << "#declare " << label << " " << currentScope->LocalFrameSize-4 << std::endl; output << "#declare " << label << " " << currentScope->LocalFrameSize-4 << std::endl;
} }
void Generator::GlobalVariable(std::string label)
{
globalScope->Definitions.push_back(new Definition(label, variableType, globalScope->FrameSize, NULL));
globalScope->FrameSize += 4;
output << "#global " << label << " " << globalScope->FrameSize-4 << std::endl;
}
void Generator::PushVariableAddress(std::string label) void Generator::PushVariableAddress(std::string label)
{ {
//writeOpcode("address"); << " " << currentScope->GetDefinition(label).StackPosition //writeOpcode("address"); << " " << currentScope->GetDefinition(label).StackPosition
@@ -376,29 +480,73 @@ namespace pim
void Generator::LoadVariable(std::string label) void Generator::LoadVariable(std::string label)
{ {
Definition d = currentScope->GetDefinition(label); Definition * d = currentScope->GetDefinition(label);
pushType(d.Type); if(!d)
writeOpcode(Opcode::Load); {
d = globalScope->GetDefinition(label);
writeConstant(d.StackPosition+(currentScope->FrameSize-d.MyScope->FrameSize)); if(!d)
throw VariableNotFoundException(label);
output << "load " << label << std::endl; if(d->DefinitionType == Definition::Function)
throw std::exception();//"Cannot use function as variable");
pushType(d->Type);
writeOpcode(Opcode::LoadAdr);
writeConstant(d->StackPosition);
output << "loadadr " << label << std::endl;
}
else
{
if(d->DefinitionType == Definition::Function)
throw std::exception();//"Cannot use function as variable");
pushType(d->Type);
writeOpcode(Opcode::Load);
writeConstant(d->StackPosition+(currentScope->FrameSize-d->MyScope->FrameSize));
output << "load " << label << std::endl;
}
} }
void Generator::StoreVariable(std::string label) void Generator::StoreVariable(std::string label)
{ {
Definition d = currentScope->GetDefinition(label); Definition * d = currentScope->GetDefinition(label);
ForceType(d.Type); if(!d)
popType(1); {
d = globalScope->GetDefinition(label);
if(!d)
throw VariableNotFoundException(label);
writeOpcode(Opcode::Store); if(d->DefinitionType == Definition::Function)
throw std::exception();//"Cannot use function as variable");
writeConstant(d.StackPosition+(currentScope->FrameSize-d.MyScope->FrameSize)); ForceType(d->Type);
//writeConstantPlaceholderOffset(currentScope->GetDefinition(label).StackPosition, &(currentScope->OldFrameSize)); popType(1);
//writeConstant(currentScope->GetDefinition(label).StackPosition);
output << "store " << label << std::endl; writeOpcode(Opcode::StoreAdr);
writeConstant(d->StackPosition);
//writeConstant(d->StackPosition+(currentScope->FrameSize-d->MyScope->FrameSize));
output << "storeadr " << label << std::endl;
}
else
{
if(d->DefinitionType == Definition::Function)
throw std::exception();//"Cannot use function as variable");
ForceType(d->Type);
popType(1);
writeOpcode(Opcode::Store);
writeConstant(d->StackPosition+(currentScope->FrameSize-d->MyScope->FrameSize));
output << "store " << label << std::endl;
}
} }
void Generator::RTConstant(std::string name) void Generator::RTConstant(std::string name)

View File

@@ -41,18 +41,31 @@ namespace pim
class Definition class Definition
{ {
public: public:
enum DefType { Function, Variable };
std::string Name; std::string Name;
DefType DefinitionType;
int Type; int Type;
int StackPosition; int StackPosition;
Scope * MyScope; Scope * MyScope;
Definition(std::string name, int type, int position, Scope * myScope) : Definition(std::string name, int type, int position, Scope * myScope) :
Type(type),
Name(name), Name(name),
DefinitionType(Variable),
Type(type),
StackPosition(position), StackPosition(position),
MyScope(myScope) MyScope(myScope)
{ {
} }
virtual ~Definition() {}
};
class FunctionDefinition : public Definition
{
public:
bool HasReturn;
std::vector<int> Arguments;
FunctionDefinition() : Definition("", 0, 0, NULL) { DefinitionType = Function; }
virtual ~FunctionDefinition() {}
}; };
struct Label struct Label
@@ -64,7 +77,7 @@ namespace pim
class Scope class Scope
{ {
public: public:
std::vector<Definition> Definitions; std::vector<Definition*> Definitions;
std::vector<Label> Labels; std::vector<Label> Labels;
int FrameSize; int FrameSize;
int LocalFrameSize; int LocalFrameSize;
@@ -76,14 +89,14 @@ namespace pim
{ {
} }
Definition GetDefinition(std::string name) Definition * GetDefinition(std::string name)
{ {
for(std::vector<Definition>::iterator iter = Definitions.begin(), end = Definitions.end(); iter != end; ++iter) for(std::vector<Definition*>::iterator iter = Definitions.begin(), end = Definitions.end(); iter != end; ++iter)
{ {
if((*iter).Name == name) if((*iter)->Name == name)
return *iter; return *iter;
} }
throw VariableNotFoundException(name); return NULL;
} }
}; };
@@ -93,6 +106,8 @@ namespace pim
std::stack<int> typeStack; std::stack<int> typeStack;
std::stack<Scope*> scopes; std::stack<Scope*> scopes;
Scope * currentScope; Scope * currentScope;
Scope * globalScope;
FunctionDefinition * funcDef;
std::ostream & output; std::ostream & output;
int labelCounter; int labelCounter;
int programCounter; int programCounter;
@@ -149,6 +164,12 @@ namespace pim
void ScopeLabel(std::string label); void ScopeLabel(std::string label);
void ScopeVariableType(int type); void ScopeVariableType(int type);
void ScopeVariable(std::string label); void ScopeVariable(std::string label);
void GlobalVariable(std::string label);
void NewFunction();
void FunctionType(int type);
void FunctionArgument(int type);
void DeclareFunction(std::string name);
void PushType(int type); void PushType(int type);
void PushVariableAddress(std::string label); void PushVariableAddress(std::string label);

View File

@@ -7,6 +7,7 @@
#include "Types.h" #include "Types.h"
#include "simulation/Simulation.h" #include "simulation/Simulation.h"
#include "X86Native.h" #include "X86Native.h"
#include "Exceptions.h"
namespace pim namespace pim
{ {
/*unsigned char * rom; /*unsigned char * rom;
@@ -33,37 +34,49 @@ namespace pim
{ {
int lastBit = 0; int lastBit = 0;
if(!(fileData[0] == 'P' && fileData[1] == 'V' && fileData[2] == 'M' && fileData[3] == '1' && fileData.size() >= 16)) if(!(fileData[0] == 'P' && fileData[1] == 'V' && fileData[2] == 'M' && fileData[3] == '1' && fileData.size() >= 24))
{ {
throw InvalidProgramException(); throw InvalidProgramException();
} }
int macroSize = 0, propSize = 0, codeSize = 0; int macroSize = 0, propSize = 0, codeSize = 0, heapSize = 0, symtableSize = 0;
macroSize = fileData[4];
macroSize |= fileData[5] << 8;
macroSize |= fileData[6] << 16;
macroSize |= fileData[7] << 24;
propSize = fileData[8]; heapSize = fileData[4];
propSize |= fileData[9] << 8; heapSize |= fileData[5] << 8;
propSize |= fileData[10] << 16; heapSize |= fileData[6] << 16;
propSize |= fileData[11] << 24; heapSize |= fileData[7] << 24;
codeSize = fileData[12]; macroSize = fileData[8];
codeSize |= fileData[13] << 8; macroSize |= fileData[9] << 8;
codeSize |= fileData[14] << 16; macroSize |= fileData[10] << 16;
codeSize |= fileData[15] << 24; macroSize |= fileData[11] << 24;
if(fileData.size() < 16 + macroSize + propSize + codeSize) propSize = fileData[12];
propSize |= fileData[13] << 8;
propSize |= fileData[14] << 16;
propSize |= fileData[15] << 24;
symtableSize = fileData[16];
symtableSize |= fileData[17] << 8;
symtableSize |= fileData[18] << 16;
symtableSize |= fileData[19] << 24;
codeSize = fileData[20];
codeSize |= fileData[21] << 8;
codeSize |= fileData[22] << 16;
codeSize |= fileData[23] << 24;
if(fileData.size() < 24 + macroSize + propSize + symtableSize + codeSize)
{ {
throw InvalidProgramException(); throw InvalidProgramException();
} }
//std::vector<std::pair<int, int> > insertions; //std::vector<std::pair<int, int> > insertions;
int macroOffset = 16; int macroOffset = 24;
int propOffset = macroOffset+macroSize; int propOffset = macroOffset+macroSize;
int codeOffset = propOffset+propSize; int symtableOffset = propOffset+propSize;
int codeOffset = symtableOffset+symtableSize;
int filePosition = macroOffset; int filePosition = macroOffset;
@@ -175,6 +188,59 @@ namespace pim
//insertions.push_back(std::pair<int, int>(macroPosition, macroValue)); //insertions.push_back(std::pair<int, int>(macroPosition, macroValue));
} }
filePosition = symtableOffset;
while(filePosition + 4 < symtableSize + symtableOffset)
{
std::string symbolName;
int stringLength = 0;
int symType = 0;
int position = 0;
symType = fileData[filePosition++];
stringLength = fileData[filePosition++];
if(filePosition + stringLength > symtableSize + symtableOffset)
{
printf("%d %d\n", filePosition + stringLength, symtableSize + symtableOffset);
throw InvalidProgramException();
}
symbolName.insert(symbolName.begin(), fileData.begin()+filePosition, fileData.begin()+filePosition+stringLength);
filePosition += stringLength;
position = fileData[filePosition++];
position |= fileData[filePosition++] << 8;
position |= fileData[filePosition++] << 16;
position |= fileData[filePosition++] << 24;
if(symType == 255)
{
std::vector<int> types = std::vector<int>();
int returnType = fileData[filePosition++];
int typeCount = fileData[filePosition++];
for(int i = 0; i < typeCount; i++)
{
types.push_back(fileData[filePosition++]);
}
std::string typeName = "void";
if(returnType != 255)
typeName = TypeName(returnType);
std::cout << "Symbol \"" << symbolName << "\", " << typeName << " (" << ArgsName(types) << ") at " << position << std::endl;
functions.push_back(Function(symbolName, position, returnType != 255, symType, types));
}
else
{
if(position + 4 > heapSize)
{
throw InvalidProgramException();
}
std::cout << "Symbol \"" << symbolName << "\", " << TypeName(symType) << " at " << position << std::endl;
variables.push_back(Variable(symbolName, position, symType));
}
}
std::vector<unsigned char> programData; std::vector<unsigned char> programData;
programData.insert(programData.begin(), fileData.begin()+codeOffset, fileData.begin()+codeOffset+codeSize); programData.insert(programData.begin(), fileData.begin()+codeOffset, fileData.begin()+codeOffset+codeSize);
@@ -186,6 +252,7 @@ namespace pim
rom = new Instruction[romSize]; rom = new Instruction[romSize];
int pc = 0; int pc = 0;
int programPosition = 0; int programPosition = 0;
@@ -213,6 +280,12 @@ namespace pim
throw InvalidProgramException(); throw InvalidProgramException();
} }
if(instruction.Opcode == Opcode::LoadAdr || instruction.Opcode == Opcode::StoreAdr)
{
if(tempInt > heapSize)
throw InvalidProgramException();
}
instruction.Parameter.Integer = tempInt; instruction.Parameter.Integer = tempInt;
programPosition += 4; programPosition += 4;
@@ -235,6 +308,9 @@ namespace pim
framePointer = callStack; framePointer = callStack;
callStack += WORDSIZE; //Since there's nothing on the stack, it shouldn't point to the item on the bottom callStack += WORDSIZE; //Since there's nothing on the stack, it shouldn't point to the item on the bottom
heap = new unsigned char[heapSize];
this->heapSize = heapSize;
} }
int VirtualMachine::opcodeArgSize(int opcode) int VirtualMachine::opcodeArgSize(int opcode)
@@ -242,7 +318,9 @@ namespace pim
switch(opcode) switch(opcode)
{ {
case Opcode::Load: case Opcode::Load:
case Opcode::LoadAdr:
case Opcode::Store: case Opcode::Store:
case Opcode::StoreAdr:
case Opcode::Constant: case Opcode::Constant:
case Opcode::Increment: case Opcode::Increment:
case Opcode::JumpEqual: case Opcode::JumpEqual:
@@ -257,6 +335,7 @@ namespace pim
case Opcode::LoadProperty: case Opcode::LoadProperty:
case Opcode::StoreProperty: case Opcode::StoreProperty:
return 4; return 4;
case Opcode::Begin:
case Opcode::Return: case Opcode::Return:
case Opcode::Discard: case Opcode::Discard:
case Opcode::Duplicate: case Opcode::Duplicate:
@@ -293,6 +372,8 @@ namespace pim
//std::cerr << programCounter << "\t" << names[rom[programCounter].Opcode] << "\t" << argument.Integer << std::endl;//"\t"; //std::cerr << programCounter << "\t" << names[rom[programCounter].Opcode] << "\t" << argument.Integer << std::endl;//"\t";
switch(rom[programCounter].Opcode) switch(rom[programCounter].Opcode)
{ {
case Opcode::Begin:
break;
case Opcode::Load: case Opcode::Load:
PSPush(CSA(argument.Integer)); PSPush(CSA(argument.Integer));
break; break;
@@ -431,7 +512,8 @@ namespace pim
nativeStack = new unsigned char [1024*1024]; nativeStack = new unsigned char [1024*1024];
std::vector<unsigned char> executableCode = native->Compile(sim, nativeStack + (1024*512), rom, romSize); std::vector<unsigned char> executableCode = native->Compile(sim, nativeStack + (1024*512), heap, rom, romSize);
virtualXToNative = native->GetAddressMap();
nativeRom = new unsigned char[executableCode.size()]; nativeRom = new unsigned char[executableCode.size()];
std::copy(executableCode.begin(), executableCode.end(), nativeRom); std::copy(executableCode.begin(), executableCode.end(), nativeRom);
@@ -439,19 +521,43 @@ namespace pim
delete native; delete native;
} }
void * VirtualMachine::GetNativeEntryPoint(std::string entryPoint) void * VirtualMachine::GetNativeEntryPoint(std::string entryPoint, std::string returnType, std::string argTypes)
{ {
for(std::vector<Function>::iterator iter = functions.begin(), end = functions.end(); iter != end; ++iter)
{
Function f = *iter;
if(f.Name == entryPoint)
{
printf("Got native entry point for %s at %p\n", entryPoint.c_str(), nativeRom+virtualXToNative[f.Position]);
fflush(stdout);
return nativeRom+virtualXToNative[f.Position];
}
}
throw FunctionNotFoundException(entryPoint, returnType, argTypes);
} }
void * VirtualMachine::GetNativeEntryPoint(intptr_t entryPoint) /*void * VirtualMachine::GetNativeEntryPoint(intptr_t entryPoint)
{ {
return nativeRom+entryPoint; return nativeRom+entryPoint;
}*/
int VirtualMachine::GetEntryPoint(std::string entryPoint, std::string returnType, std::string argTypes)
{
for(std::vector<Function>::iterator iter = functions.begin(), end = functions.end(); iter != end; ++iter)
{
Function f = *iter;
if(f.Name == entryPoint)
{
return f.Position;
//if()
}
}
throw FunctionNotFoundException(entryPoint, returnType, argTypes);
} }
void VirtualMachine::Run(std::string entryPoint) /*void VirtualMachine::Run(std::string entryPoint)
{ {
} }*/
void VirtualMachine::Run(int entryPoint) void VirtualMachine::Run(int entryPoint)
{ {

View File

@@ -3,6 +3,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <cstring> #include <cstring>
#include <map>
class Simulation; class Simulation;
namespace pim namespace pim
@@ -47,6 +48,36 @@ namespace pim
class VirtualMachine class VirtualMachine
{ {
class Variable
{
public:
std::string Name;
int Type;
int Position;
Variable(std::string name, int position, int type)
{
Name = name;
Position = position;
Type = type;
}
};
class Function
{
public:
std::string Name;
bool HasReturn;
int ReturnType;
std::vector<int> ArgTypes;
int Position;
Function(std::string name, int position, bool hasReturn, int returnType, std::vector<int> argTypes)
{
Name = name;
Position = position;
HasReturn = hasReturn;
ReturnType = returnType;
ArgTypes = argTypes;
}
};
#define WORDSIZE 4 #define WORDSIZE 4
//#define OPDEF(name) void op##name(int parameter); //#define OPDEF(name) void op##name(int parameter);
@@ -68,6 +99,8 @@ namespace pim
unsigned char * ram; unsigned char * ram;
int ramSize; int ramSize;
int ramMask; int ramMask;
unsigned char * heap;
int heapSize;
#define CSA(argument) (*((Word*)&ram[framePointer-argument])) #define CSA(argument) (*((Word*)&ram[framePointer-argument]))
#define CS() (*((Word*)&ram[callStack])) #define CS() (*((Word*)&ram[callStack]))
@@ -80,6 +113,10 @@ namespace pim
//Instruction * instructions; //Instruction * instructions;
std::vector<Function> functions;
std::vector<Variable> variables;
std::map<int, int> virtualXToNative;
int programCounter; int programCounter;
void run(); void run();
int opcodeArgSize(int opcode); int opcodeArgSize(int opcode);
@@ -87,9 +124,8 @@ namespace pim
VirtualMachine(Simulation * sim); VirtualMachine(Simulation * sim);
void LoadProgram(std::vector<unsigned char> programData); void LoadProgram(std::vector<unsigned char> programData);
void Compile(); void Compile();
void * GetNativeEntryPoint(std::string entryPoint); void * GetNativeEntryPoint(std::string entryPoint, std::string returnType, std::string argTypes);
void * GetNativeEntryPoint(intptr_t entryPoint); int GetEntryPoint(std::string entryPoint, std::string returnType, std::string argTypes);
void Run(std::string entryPoint);
void Run(int entryPoint); void Run(int entryPoint);
inline bool IsCompiled() inline bool IsCompiled()
{ {

View File

@@ -1,4 +1,5 @@
#include "Machine.h" #include "Machine.h"
#include <map>
namespace pim namespace pim
{ {
@@ -46,7 +47,8 @@ namespace pim
virtual void emitPlaceholder(int virtualAddress) {} virtual void emitPlaceholder(int virtualAddress) {}
public: public:
Native() : nativeRom() {} Native() : nativeRom() {}
virtual std::vector<unsigned char> Compile(Simulation * sim, unsigned char * machineStack, Instruction * rom, int romSize) {} virtual std::map<int, int> GetAddressMap() {}
virtual std::vector<unsigned char> Compile(Simulation * sim, unsigned char * machineStack, unsigned char * heap, Instruction * rom, int romSize) {}
}; };
} }

View File

@@ -1,7 +1,10 @@
OPDEF(Begin)
OPDEF(Load) OPDEF(Load)
OPDEF(LoadAdr)
OPDEF(ToFloat) OPDEF(ToFloat)
OPDEF(ToInteger) OPDEF(ToInteger)
OPDEF(Store) OPDEF(Store)
OPDEF(StoreAdr)
OPDEF(Constant) OPDEF(Constant)
OPDEF(Increment) OPDEF(Increment)
OPDEF(Discard) OPDEF(Discard)

View File

@@ -30,21 +30,12 @@ namespace pim
*/ */
void Parser::program() void Parser::program()
{ {
functionList(); globalList();
//functionList();
} }
/* /*
<function list> ::= <function> | <function> <function list> <function> ::= function identifier ( <declaration list> ) <block> end | function type identifier ( <declaration list> ) <block> end
*/
void Parser::functionList()
{
function();
while(look(Token::FunctionSymbol))
function();
}
/*
<function> ::= function identifier ( <declaration list> ) <block> end
*/ */
void Parser::function() void Parser::function()
{ {
@@ -52,6 +43,14 @@ namespace pim
expect(Token::FunctionSymbol); expect(Token::FunctionSymbol);
generator->NewFunction();
if(accept(Token::IntegerConstant))
generator->FunctionType(DataType::Integer);
else if(accept(Token::ParticleConstant))
generator->FunctionType(DataType::Integer);
else if(accept(Token::DecimalConstant))
generator->FunctionType(DataType::Float);
functionName = token.Source; functionName = token.Source;
generator->PushScope(functionName); generator->PushScope(functionName);
expect(Token::Identifier); expect(Token::Identifier);
@@ -62,6 +61,7 @@ namespace pim
argumentList(); argumentList();
expect(Token::RightBracket); expect(Token::RightBracket);
} }
generator->DeclareFunction(functionName);
block(); block();
expect(Token::EndSymbol); expect(Token::EndSymbol);
@@ -77,6 +77,7 @@ namespace pim
{ {
std::string functionName; std::string functionName;
//generator->BeginCall();
functionName = token.Source; functionName = token.Source;
expect(Token::Identifier); expect(Token::Identifier);
expect(Token::LeftBracket); expect(Token::LeftBracket);
@@ -127,6 +128,7 @@ namespace pim
if(!accept(Token::ParticleSymbol)) if(!accept(Token::ParticleSymbol))
throw ParserExpectException(token, "type name"); throw ParserExpectException(token, "type name");
generator->ScopeVariable(token.Source); generator->ScopeVariable(token.Source);
generator->FunctionArgument(type);
expect(Token::Identifier); expect(Token::Identifier);
} }
@@ -163,6 +165,49 @@ namespace pim
throw ParserExpectException(token, "type name"); throw ParserExpectException(token, "type name");
identifierList(); identifierList();
} }
/*
<global list> ::= <global> | <global> <global list>
*/
void Parser::globalList()
{
while(look(Token::IntegerSymbol) || look(Token::DecimalSymbol) || look(Token::ParticleSymbol) || look(Token::FunctionSymbol))
{
global();
}
}
/*
<global> ::= integer <identifier list> | decimal <identifier list> | particle <identifier list> | <function>
*/
void Parser::global()
{
int type;
if(look(Token::FunctionSymbol))
{
function();
}
else
{
switch(token.Symbol)
{
case Token::DecimalSymbol:
type = DataType::Float;
break;
case Token::IntegerSymbol:
case Token::ParticleSymbol:
type = DataType::Integer;
break;
}
generator->ScopeVariableType(type);
if(!accept(Token::IntegerSymbol))
if(!accept(Token::DecimalSymbol))
if(!accept(Token::ParticleSymbol))
throw ParserExpectException(token, "type name");
generator->GlobalVariable(token.Source);
expect(Token::Identifier);
}
}
/* /*
<identifier list> ::= identifier | identifier , <identifier list> <identifier list> ::= identifier | identifier , <identifier list>

View File

@@ -30,6 +30,8 @@ namespace pim
void argument(); void argument();
void declarationList(); void declarationList();
void declaration(); void declaration();
void globalList();
void global();
void identifierList(); void identifierList();
void statementList(); void statementList();
void statement(); void statement();

View File

@@ -2,12 +2,15 @@
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include "Scanner.h" #include "Scanner.h"
#include "Exceptions.h"
namespace pim namespace pim
{ {
namespace compiler namespace compiler
{ {
Scanner::Scanner(std::stringstream & source_) : Scanner::Scanner(std::stringstream & source_) :
cLine(1),
cCharNum(1),
source(source_) source(source_)
{ {
nextCharacter(); nextCharacter();
@@ -37,12 +40,18 @@ namespace pim
{ {
nextCharacter(); nextCharacter();
if(cChar == '\n') if(cChar == '\n')
{
cLine++; cLine++;
cCharNum = 1;
}
else else
continue; continue;
} }
else if(cChar == '\n') else if(cChar == '\n')
{
cLine++; cLine++;
cCharNum = 1;
}
nextCharacter(); nextCharacter();
} }
@@ -184,17 +193,27 @@ namespace pim
nextCharacter(); nextCharacter();
return Token(Token::DotSymbol, ".", cLine); return Token(Token::DotSymbol, ".", cLine);
} }
else if(cChar == 0)
{
return Token(Token::EndOfFile, "EOF", cLine);
}
else else
{ {
nextCharacter(); throw ScannerCharacterException(cChar, cLine, cCharNum);
return Token(Token::InvalidSymbol, std::string(1, cChar), cLine); //nextCharacter();
//return Token(Token::InvalidSymbol, std::string(1, cChar), cLine);
} }
} }
void Scanner::nextCharacter() void Scanner::nextCharacter()
{ {
if(source.good()) if(source.good() && !source.eof())
{
cCharNum++;
cChar = source.get(); cChar = source.get();
if(source.eof())
cChar = 0;
}
else else
cChar = 0; cChar = 0;
} }

View File

@@ -11,6 +11,7 @@ namespace pim
{ {
char cChar; char cChar;
int cLine; int cLine;
int cCharNum;
std::string cToken; std::string cToken;
std::stringstream & source; std::stringstream & source;
void nextCharacter(); void nextCharacter();

View File

@@ -45,7 +45,8 @@ namespace pim
"IDENTIFIER", "IDENTIFIER",
",", ",",
".", ".",
"INVALID SYMBOL" "INVALID SYMBOL",
"EOF"
}; };
} }
} }

View File

@@ -63,7 +63,9 @@ namespace pim
InvalidSymbol, InvalidSymbol,
SymbolNumber SymbolNumber,
EndOfFile
}; };
int Symbol; int Symbol;
int LineNumber; int LineNumber;

View File

@@ -1,4 +1,7 @@
#pragma once #pragma once
#include <string>
#include <vector>
#include <sstream>
namespace pim namespace pim
{ {
struct DataType struct DataType
@@ -10,4 +13,25 @@ namespace pim
Float Float
}; };
}; };
static std::string TypeName(int type)
{
if(type == DataType::Float)
return "decimal";
if(type == DataType::Integer)
return "integer";
}
static std::string ArgsName(std::vector<int> args)
{
std::stringstream newStream("");
for(std::vector<int>::iterator iter = args.begin(), end = args.end(); iter != end; iter++)
{
if(*iter == DataType::Float)
newStream << "D";
else if(*iter == DataType::Integer)
newStream << "I";
else
newStream << "V";
}
return newStream.str();
}
} }

View File

@@ -4,7 +4,7 @@
namespace pim namespace pim
{ {
std::vector<unsigned char> X86Native::Compile(Simulation * sim, unsigned char * machineStack, Instruction * rom, int romSize) std::vector<unsigned char> X86Native::Compile(Simulation * sim, unsigned char * machineStack, unsigned char * heap, Instruction * rom, int romSize)
{ {
#if defined(X86) && !defined(_64BIT) #if defined(X86) && !defined(_64BIT)
int programCounter = 0; int programCounter = 0;
@@ -12,10 +12,9 @@ namespace pim
for(int i = 0; i < 8; i++) { emit("90"); } //nop, helps find the code in memory with a debugger for(int i = 0; i < 8; i++) { emit("90"); } //nop, helps find the code in memory with a debugger
emit("BE"); //mov esi, machineStack //emit("BE"); //mov esi, machineStack
emitConstantP((intptr_t)machineStack); //emitConstantP((intptr_t)machineStack);
while(programCounter < romSize) while(programCounter < romSize)
{ {
@@ -23,6 +22,10 @@ namespace pim
virtualToNative[programCounter] = nativeRom.size(); virtualToNative[programCounter] = nativeRom.size();
switch(rom[programCounter].Opcode) switch(rom[programCounter].Opcode)
{ {
case Opcode::Begin:
emit("BE"); //mov esi, machineStack
emitConstantP((intptr_t)machineStack);
break;
case Opcode::Load: case Opcode::Load:
emit("83 EE 04"); //sub esi, 4 emit("83 EE 04"); //sub esi, 4
//Load value at base stack + offset into eax //Load value at base stack + offset into eax
@@ -40,6 +43,18 @@ namespace pim
emitConstantD(argument.Integer); emitConstantD(argument.Integer);
emit("83 C6 04"); //add esi, 4 emit("83 C6 04"); //add esi, 4
break; break;
case Opcode::LoadAdr:
emit("83 EE 04"); //sub esi, 4
emit("A1"); //mov eax, [offset]
emitConstantP(((intptr_t)heap)+argument.Integer);
emit("89 06"); //mov [esi], eax
break;
case Opcode::StoreAdr:
emit("8B 06"); //mov eax, [esi]
emit("A3"); //mov [offset], eax
emitConstantP(((intptr_t)heap)+argument.Integer);
emit("83 C6 04"); //add esi, 4
break;
case Opcode::Constant: case Opcode::Constant:
emit("83 EE 04"); //sub esi, 4 emit("83 EE 04"); //sub esi, 4
emit("C7 06"); //mov [esi], dword ptr constant emit("C7 06"); //mov [esi], dword ptr constant

View File

@@ -8,7 +8,8 @@ namespace pim
{ {
public: public:
X86Native() : Native() {} X86Native() : Native() {}
virtual std::vector<unsigned char> Compile(Simulation * sim, unsigned char * machineStack, Instruction * rom, int romSize); virtual std::vector<unsigned char> Compile(Simulation * sim, unsigned char * machineStack, unsigned char * heap, Instruction * rom, int romSize);
virtual std::map<int, int> GetAddressMap() { return virtualToNative; }
protected: protected:
virtual void emitConstantD(long int constant); virtual void emitConstantD(long int constant);
virtual void emitConstantP(intptr_t constant); virtual void emitConstantP(intptr_t constant);

View File

@@ -149,7 +149,7 @@ public:
TPT_NO_INLINE int create_part_add_props(int p, int x, int y, int tv, int rx, int ry); TPT_NO_INLINE int create_part_add_props(int p, int x, int y, int tv, int rx, int ry);
//int InCurrentBrush(int i, int j, int rx, int ry); //int InCurrentBrush(int i, int j, int rx, int ry);
//int get_brush_flags(); //int get_brush_flags();
TPT_NO_INLINE int create_part(int p, int x, int y, int t); TPT_NO_INLINE TPT_VM_CALLABLE int create_part(int p, int x, int y, int t);
TPT_NO_INLINE void delete_part(int x, int y, int flags); TPT_NO_INLINE void delete_part(int x, int y, int flags);
void get_sign_pos(int i, int *x0, int *y0, int *w, int *h); void get_sign_pos(int i, int *x0, int *y0, int *w, int *h);
TPT_NO_INLINE int is_wire(int x, int y); TPT_NO_INLINE int is_wire(int x, int y);