From 14991cba5f06bebaa70b9c1651e403e8c7eb4a02 Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Sat, 9 Feb 2013 13:44:09 +0000 Subject: [PATCH] Enforce cdecl calling convention for callable code, global variables, symbol table for exporting programmes --- src/Config.h | 2 + src/cat/LuaScriptInterface.cpp | 4 +- src/pim/Exceptions.h | 30 ++++++ src/pim/Generator.cpp | 180 ++++++++++++++++++++++++++++++--- src/pim/Generator.h | 33 ++++-- src/pim/Machine.cpp | 152 +++++++++++++++++++++++----- src/pim/Machine.h | 42 +++++++- src/pim/Native.h | 4 +- src/pim/Opcodes.inl | 3 + src/pim/Parser.cpp | 69 ++++++++++--- src/pim/Parser.h | 2 + src/pim/Scanner.cpp | 25 ++++- src/pim/Scanner.h | 1 + src/pim/Token.cpp | 3 +- src/pim/Token.h | 4 +- src/pim/Types.h | 24 +++++ src/pim/X86Native.cpp | 23 ++++- src/pim/X86Native.h | 3 +- src/simulation/Simulation.h | 2 +- 19 files changed, 532 insertions(+), 74 deletions(-) diff --git a/src/Config.h b/src/Config.h index dafaf18b8..2776e4382 100644 --- a/src/Config.h +++ b/src/Config.h @@ -212,6 +212,8 @@ extern unsigned char ZSIZE; #define TPT_NO_INLINE inline #endif +#define TPT_VM_CALLABLE __cdecl + #define SDEUT //#define REALHEAT diff --git a/src/cat/LuaScriptInterface.cpp b/src/cat/LuaScriptInterface.cpp index f1984ee60..9be6442d2 100644 --- a/src/cat/LuaScriptInterface.cpp +++ b/src/cat/LuaScriptInterface.cpp @@ -1336,7 +1336,7 @@ int LuaScriptInterface::elements_property(lua_State * l) updateVirtualMachines[id] = (pim::VirtualMachine*)lua_touserdata(l, 3); 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; } else @@ -1481,7 +1481,7 @@ int LuaScriptInterface::virtualMachine_loadProgram(lua_State * l) return luaL_error(l, "Unable to load program"); } 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); diff --git a/src/pim/Exceptions.h b/src/pim/Exceptions.h index 7f48e0e85..c24e673dd 100644 --- a/src/pim/Exceptions.h +++ b/src/pim/Exceptions.h @@ -2,6 +2,7 @@ #include #include +#include #include "Token.h" namespace pim @@ -36,5 +37,34 @@ namespace pim } ~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; }; + }; } \ No newline at end of file diff --git a/src/pim/Generator.cpp b/src/pim/Generator.cpp index 9122e9145..49d59ea61 100644 --- a/src/pim/Generator.cpp +++ b/src/pim/Generator.cpp @@ -11,9 +11,12 @@ namespace pim { Generator::Generator() : typeStack(), + globalScope(new Scope()), output(std::cout), labelCounter(0), - programCounter(0) + programCounter(0), + program() + { } @@ -33,16 +36,19 @@ namespace pim void Generator::writeOpcode(int opcode) { programCounter++; + printf("Opcode: %d\n", opcode); program.push_back(opcode); } void Generator::writeConstant(std::string constant) { + printf("Constant: %s\n", constant.c_str()); writeConstant(format::StringToNumber(constant)); } void Generator::writeConstant(int constant) { + printf("Constant: %d\n", constant); program.push_back(constant & 0xFF); program.push_back((constant>>8) & 0xFF); program.push_back((constant>>16) & 0xFF); @@ -51,6 +57,7 @@ namespace pim void Generator::writeConstantPlaceholderOffset(int value, int * offset) { + printf("Constant: %d\n", value); valueOffsetPlaceholders.push_back(ValueOffsetPlaceholder(program.size(), std::pair(value, offset))); program.push_back(0); program.push_back(0); @@ -60,6 +67,7 @@ namespace pim void Generator::writeConstantPlaceholder(std::string label) { + printf("Constant: %s\n", label.c_str()); placeholders.push_back(Placeholder(program.size(), label)); program.push_back(0); program.push_back(0); @@ -69,6 +77,7 @@ namespace pim void Generator::writeConstantPlaceholder(int * value) { + printf("Constant: %p\n", value); valuePlaceholders.push_back(ValuePlaceholder(program.size(), value)); program.push_back(0); program.push_back(0); @@ -78,6 +87,7 @@ namespace pim void Generator::writeConstantPropertyPlaceholder(std::string property) { + printf("Constant: %s\n", property.c_str()); propertyPlaceholders.push_back(PropertyPlaceholder(program.size(), property)); program.push_back(0); program.push_back(0); @@ -87,6 +97,7 @@ namespace pim void Generator::writeConstantMacroPlaceholder(std::string macro) { + printf("Constant: %s\n", macro.c_str()); macroPlaceholders.push_back(MacroPlaceholder(program.size(), macro)); program.push_back(0); program.push_back(0); @@ -150,13 +161,18 @@ namespace pim } //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 file; file.push_back('P'); file.push_back('V'); file.push_back('M'); 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(); file.push_back(0); @@ -170,6 +186,12 @@ namespace pim 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(); file.push_back(0); file.push_back(0); @@ -223,6 +245,50 @@ namespace pim file[propSizePos+2] = (propSize >> 16) & 0xFF; file[propSizePos+3] = (propSize >> 24) & 0xFF; + for(std::vector::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::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[codeSizePos] = codeSize & 0xFF; @@ -230,6 +296,8 @@ namespace pim file[codeSizePos+2] = (codeSize >> 16) & 0xFF; file[codeSizePos+3] = (codeSize >> 24) & 0xFF; + printf("codeSize: %d, codeSizePos: %d\n", codeSize, codeSizePos); + std::ofstream newFile("test.pvm"); for(std::vector::iterator iter = file.begin(), end = file.end(); iter != end; ++iter) { @@ -360,15 +428,51 @@ namespace pim 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) { - 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->LocalFrameSize += 4; 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) { //writeOpcode("address"); << " " << currentScope->GetDefinition(label).StackPosition @@ -376,29 +480,73 @@ namespace pim void Generator::LoadVariable(std::string label) { - Definition d = currentScope->GetDefinition(label); + Definition * d = currentScope->GetDefinition(label); - pushType(d.Type); - writeOpcode(Opcode::Load); + if(!d) + { + 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) { - Definition d = currentScope->GetDefinition(label); - ForceType(d.Type); - popType(1); + Definition * d = currentScope->GetDefinition(label); + if(!d) + { + 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)); - //writeConstantPlaceholderOffset(currentScope->GetDefinition(label).StackPosition, &(currentScope->OldFrameSize)); - //writeConstant(currentScope->GetDefinition(label).StackPosition); + ForceType(d->Type); + popType(1); - 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) diff --git a/src/pim/Generator.h b/src/pim/Generator.h index 024a6c24a..e96456838 100644 --- a/src/pim/Generator.h +++ b/src/pim/Generator.h @@ -41,18 +41,31 @@ namespace pim class Definition { public: + enum DefType { Function, Variable }; std::string Name; + DefType DefinitionType; int Type; int StackPosition; Scope * MyScope; Definition(std::string name, int type, int position, Scope * myScope) : - Type(type), Name(name), + DefinitionType(Variable), + Type(type), StackPosition(position), MyScope(myScope) { } + virtual ~Definition() {} + }; + + class FunctionDefinition : public Definition + { + public: + bool HasReturn; + std::vector Arguments; + FunctionDefinition() : Definition("", 0, 0, NULL) { DefinitionType = Function; } + virtual ~FunctionDefinition() {} }; struct Label @@ -64,7 +77,7 @@ namespace pim class Scope { public: - std::vector Definitions; + std::vector Definitions; std::vector