mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-30 11:19:51 +02:00
Enforce cdecl calling convention for callable code, global variables, symbol table for exporting programmes
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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; };
|
||||||
|
};
|
||||||
}
|
}
|
@@ -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)
|
||||||
|
@@ -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);
|
||||||
|
@@ -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)
|
||||||
{
|
{
|
||||||
|
@@ -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()
|
||||||
{
|
{
|
||||||
|
@@ -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) {}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
@@ -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)
|
||||||
|
@@ -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>
|
||||||
|
@@ -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();
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
|
@@ -45,7 +45,8 @@ namespace pim
|
|||||||
"IDENTIFIER",
|
"IDENTIFIER",
|
||||||
",",
|
",",
|
||||||
".",
|
".",
|
||||||
"INVALID SYMBOL"
|
"INVALID SYMBOL",
|
||||||
|
"EOF"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -63,7 +63,9 @@ namespace pim
|
|||||||
|
|
||||||
InvalidSymbol,
|
InvalidSymbol,
|
||||||
|
|
||||||
SymbolNumber
|
SymbolNumber,
|
||||||
|
|
||||||
|
EndOfFile
|
||||||
};
|
};
|
||||||
int Symbol;
|
int Symbol;
|
||||||
int LineNumber;
|
int LineNumber;
|
||||||
|
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user