Compare commits

...

17 Commits

Author SHA1 Message Date
Simon Robertshaw
224d646297 Compiler: Fix label generation 2013-02-14 09:40:15 +00:00
Simon Robertshaw
4e1ea552f1 More VM callable functions 2013-02-13 20:59:11 +00:00
Simon Robertshaw
14991cba5f Enforce cdecl calling convention for callable code, global variables, symbol table for exporting programmes 2013-02-09 13:44:09 +00:00
Simon Robertshaw
f3cfa6106b Inform GCC of clobbered registers 2013-02-02 21:10:56 +00:00
Simon Robertshaw
f7b734de0b Better checking for coordinates in GET instruction, empty particles are id'd -1 2013-02-02 16:46:50 +00:00
Simon Robertshaw
316e940e53 Clean up VM and Lua loading functions 2013-02-02 14:46:45 +00:00
Simon Robertshaw
487647645e Don't backup esi/edx registers as there's no way of adjusting variable position on the stack, yet 2013-02-02 01:56:56 +00:00
Simon Robertshaw
acb126e162 More type conversion and enforcement 2013-02-02 01:31:19 +00:00
Simon Robertshaw
1e535a160d Merge 2013-02-01 20:25:48 +00:00
Simon Robertshaw
187bf11d3d tointeger and tofloat instructions. Detection and implicit conversion of number types 2013-02-01 15:21:21 +00:00
Simon Robertshaw
833cbf9b77 Merge 2013-01-31 23:43:11 +00:00
Simon Robertshaw
004710fcea Keep track of variable types 2013-01-31 23:35:16 +00:00
Simon Robertshaw
b1944dfda1 Remove old testing code 2013-01-31 22:41:24 +00:00
Simon Robertshaw
15503177a8 Correct compilation of JNE instruction 2013-01-31 20:58:48 +00:00
Simon Robertshaw
8fb020c59e Return from procedures, correctly address variables in nested scopes, make space for the return address from the callers stack 2013-01-30 23:44:05 +00:00
Simon Robertshaw
ca7c0d777b Working X86 JIT compilation/execution 2013-01-30 18:11:06 +00:00
Simon Robertshaw
c4e5e82fec Work on X86 native compiler 2013-01-28 00:08:22 +00:00
23 changed files with 1328 additions and 340 deletions

View File

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

View File

@ -950,6 +950,22 @@ void LuaScriptInterface::initElementsAPI()
}
pim::VirtualMachine * LuaScriptInterface::updateVirtualMachines[PT_NUM];
NativeUpdateFunc LuaScriptInterface::updateNativeCode[PT_NUM];
int LuaScriptInterface::updateNative(UPDATE_FUNC_ARGS)
{
/*void (*nativeFunction)(int, int, int) = updateNativeCode[parts[i].type];//(void(*)(int, int, int))nativeRom;
//int arg3 = CSPop().Integer;
//int arg2 = CSPop().Integer;
//int arg1 = CSPop().Integer;
//std::cout << arg1 << std::endl;
//std::cout << arg2 << std::endl;
//std::cout << arg3 << std::endl;
nativeFunction(i, x, y);*/
__asm__("nop": : :"ecx", "ebx", "esi");
updateNativeCode[parts[i].type](i, x, y);
return 0;
}
int LuaScriptInterface::updateVM(UPDATE_FUNC_ARGS)
{
@ -958,7 +974,8 @@ int LuaScriptInterface::updateVM(UPDATE_FUNC_ARGS)
machine->CSPush(i);
machine->CSPush(x);
machine->CSPush(y);
machine->Call(0);
//machine->Call(0);
machine->Run(0);
/*vm::VirtualMachine * vMachine = updateVirtualMachines[parts[i].type];
@ -1317,7 +1334,15 @@ int LuaScriptInterface::elements_property(lua_State * l)
else if(lua_type(l, 3) == LUA_TLIGHTUSERDATA)
{
updateVirtualMachines[id] = (pim::VirtualMachine*)lua_touserdata(l, 3);
luacon_sim->elements[id].Update = &updateVM;
if(updateVirtualMachines[id]->IsCompiled())
{
updateNativeCode[id] = (NativeUpdateFunc)updateVirtualMachines[id]->GetNativeEntryPoint("update", "I", "III");
luacon_sim->elements[id].Update = &updateNative;
}
else
{
luacon_sim->elements[id].Update = &updateVM;
}
}
else if(lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
{
@ -1456,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);
@ -1467,6 +1492,10 @@ int LuaScriptInterface::virtualMachine_loadProgram(lua_State * l)
pim::VirtualMachine * machine = new pim::VirtualMachine(luacon_sim);
machine->LoadProgram(programData);
#if defined(X86) && !defined(_64BIT)
machine->Compile();
#endif
lua_pushlightuserdata(l, machine);
return 1;
}

View File

@ -45,6 +45,8 @@ class Tool;
#define LUACON_EL_MODIFIED_MENUS 0x4
class TPTScriptInterface;
class LuaScriptInterface;
typedef void (TPT_VM_CALLABLE *NativeUpdateFunc)(int, int, int);
class LuaScriptInterface: public CommandInterface
{
int luacon_mousex, luacon_mousey, luacon_mousebutton, luacon_brushx, luacon_brushy;
@ -75,6 +77,8 @@ class LuaScriptInterface: public CommandInterface
//Elements
static pim::VirtualMachine * updateVirtualMachines[PT_NUM];
static NativeUpdateFunc updateNativeCode[PT_NUM];
static int updateNative(UPDATE_FUNC_ARGS);
static int updateVM(UPDATE_FUNC_ARGS);
//
void initElementsAPI();

70
src/pim/Exceptions.h Normal file
View File

@ -0,0 +1,70 @@
#pragma once
#include <cstring>
#include <string>
#include <cstdio>
#include "Token.h"
namespace pim
{
namespace compiler {
class ParserExpectException: public std::exception
{
char * error;
public:
ParserExpectException(Token token, int expectingSymbol) {
error = strdup(std::string("Expecting " + Token::SymbolNames[expectingSymbol] + " got " + token.Source).c_str());
}
ParserExpectException(Token token, std::string expectingString) {
error = strdup(std::string("Expecting " + expectingString + " got " + token.Source).c_str());
}
const char * what() const throw()
{
return error;
}
~ParserExpectException() throw() {};
};
class TypeException: public std::exception
{
char * error;
public:
TypeException(int type, int expectingType) {
error = strdup(std::string("Expecting a particular type, got a different type").c_str());
}
const char * what() const throw()
{
return error;
}
~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

@ -4,18 +4,27 @@
#include "Format.h"
#include "Generator.h"
#include "Opcodes.h"
#include "Exceptions.h"
namespace pim
{
namespace compiler
{
Generator::Generator() :
typeStack(),
globalScope(new Scope()),
output(std::cout),
labelCounter(0),
programCounter(0)
programCounter(0),
program()
{
}
Generator::~Generator()
{
}
void Generator::defineLabel(std::string label)
{
Label newLabel;
@ -43,6 +52,15 @@ namespace pim
program.push_back((constant>>24) & 0xFF);
}
void Generator::writeConstantPlaceholderOffset(int value, int * 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);
}
void Generator::writeConstantPlaceholder(std::string label)
{
placeholders.push_back(Placeholder(program.size(), label));
@ -118,14 +136,35 @@ namespace pim
program[cPosition.first+3] = (value >> 24) & 0xFF;
}
for(std::vector<ValueOffsetPlaceholder>::iterator iter = valueOffsetPlaceholders.begin(), end = valueOffsetPlaceholders.end(); iter != end; ++iter)
{
ValueOffsetPlaceholder cPosition = *iter;
int value = cPosition.second.first;
int offset = *cPosition.second.second;
std::cout << "Setting value placeholder at " << cPosition.first << " with " << value << " + " << offset << std::endl;
value += offset;
program[cPosition.first] = value & 0xFF;
program[cPosition.first+1] = (value >> 8) & 0xFF;
program[cPosition.first+2] = (value >> 16) & 0xFF;
program[cPosition.first+3] = (value >> 24) & 0xFF;
}
//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;
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);
@ -139,6 +178,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);
@ -192,6 +237,50 @@ namespace pim
file[propSizePos+2] = (propSize >> 16) & 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[codeSizePos] = codeSize & 0xFF;
@ -199,6 +288,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<unsigned char>::iterator iter = file.begin(), end = file.end(); iter != end; ++iter)
{
@ -214,7 +305,7 @@ namespace pim
std::stringstream label;
label << prefix;
label << "_";
label << labelCounter;
label << labelCounter++;
label << "_";
return label.str();
}
@ -224,6 +315,8 @@ namespace pim
scopes.push(currentScope);
Scope * prevScope = currentScope;
currentScope = new Scope();
currentScope->FrameSize += 4; //Space for return address
currentScope->LocalFrameSize += 4;
defineLabel(label);
output << "." << label << std::endl;
@ -236,6 +329,7 @@ namespace pim
currentScope = new Scope();
currentScope->Definitions.insert(currentScope->Definitions.begin(), prevScope->Definitions.begin(), prevScope->Definitions.end());
currentScope->FrameSize = prevScope->FrameSize;
currentScope->OldFrameSize = prevScope->OldFrameSize;
defineLabel(label);
output << "." << label << std::endl;
@ -243,16 +337,27 @@ namespace pim
void Generator::PopScope()
{
writeOpcode(Opcode::Return);
writeOpcode(Opcode::Leave);
writeConstant(currentScope->LocalFrameSize);
output << "return " << currentScope->LocalFrameSize << std::endl;
output << "leave " << currentScope->LocalFrameSize << std::endl;
currentScope = scopes.top();
scopes.pop();
}
void Generator::ExitScope()
{
currentScope = scopes.top();
scopes.pop();
}
void Generator::Return()
{
writeOpcode(Opcode::Return);
output << "return" << std::endl;
}
void Generator::ScopeLabel(std::string label)
{
//defineLabelwriteOpcode("." << label);
@ -274,13 +379,90 @@ namespace pim
variableType = type;
}
void Generator::PushType(int type)
{
typeStack.push(type);
}
void Generator::pushType(int type)
{
typeStack.push(type);
}
void Generator::popType(int count)
{
while(count--)
{
typeStack.pop();
}
}
void Generator::AssureType(int type)
{
int otherType = typeStack.top();
if(otherType != type)
{
if(otherType == DataType::Integer && type == DataType::Float)
{
ToFloat();
}
else if(otherType == DataType::Float && type == DataType::Integer)
{
ToInteger();
}
}
}
void Generator::ForceType(int type)
{
if(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)
{
currentScope->Definitions.push_back(Definition(label, variableType, currentScope->FrameSize));
currentScope->Definitions.push_back(new Definition(label, variableType, currentScope->LocalFrameSize, currentScope));
currentScope->FrameSize += 4;
currentScope->LocalFrameSize += 4;
output << "#declare " << label << " " << currentScope->FrameSize-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)
@ -290,22 +472,78 @@ namespace pim
void Generator::LoadVariable(std::string label)
{
writeOpcode(Opcode::Load);
writeConstant(currentScope->GetDefinition(label).StackPosition);
Definition * d = currentScope->GetDefinition(label);
output << "load " << label << std::endl;
if(!d)
{
d = globalScope->GetDefinition(label);
if(!d)
throw VariableNotFoundException(label);
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)
{
writeOpcode(Opcode::Store);
writeConstant(currentScope->GetDefinition(label).StackPosition);
Definition * d = currentScope->GetDefinition(label);
if(!d)
{
d = globalScope->GetDefinition(label);
if(!d)
throw VariableNotFoundException(label);
output << "store " << label << std::endl;
if(d->DefinitionType == Definition::Function)
throw std::exception();//"Cannot use function as variable");
ForceType(d->Type);
popType(1);
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)
{
pushType(DataType::Integer);
writeOpcode(Opcode::Constant);
writeConstantMacroPlaceholder(name);
@ -314,6 +552,7 @@ namespace pim
void Generator::Constant(std::string constant)
{
pushType(DataType::Integer);
writeOpcode(Opcode::Constant);
writeConstant(constant);
@ -331,6 +570,7 @@ namespace pim
void Generator::Discard()
{
popType(1);
writeOpcode(Opcode::Discard);
output << "discard" << std::endl;
@ -338,6 +578,7 @@ namespace pim
void Generator::Duplicate()
{
pushType(typeStack.top());
writeOpcode(Opcode::Duplicate);
output << "duplicate" << std::endl;
@ -345,6 +586,8 @@ namespace pim
void Generator::Add()
{
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Add);
output << "add" << std::endl;
@ -352,6 +595,8 @@ namespace pim
void Generator::Subtract()
{
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Subtract);
output << "sub" << std::endl;
@ -359,13 +604,36 @@ namespace pim
void Generator::Multiply()
{
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Multiply);
output << "mul" << std::endl;
}
void Generator::ToInteger()
{
popType(1);
pushType(DataType::Integer);
writeOpcode(Opcode::ToInteger);
output << "ftoi" << std::endl;
}
void Generator::ToFloat()
{
popType(1);
pushType(DataType::Float);
writeOpcode(Opcode::ToFloat);
output << "itof" << std::endl;
}
void Generator::Divide()
{
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Divide);
output << "div" << std::endl;
@ -373,6 +641,8 @@ namespace pim
void Generator::Modulus()
{
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Modulus);
output << "add" << std::endl;
@ -387,8 +657,18 @@ namespace pim
void Generator::CreateParticle()
{
ForceType(DataType::Integer);
popType(1);
ForceType(DataType::Integer);
popType(1);
ForceType(DataType::Integer);
popType(1);
ForceType(DataType::Integer);
popType(1);
writeOpcode(Opcode::Create);
pushType(DataType::Integer);
output << "create" << std::endl;
}
@ -401,6 +681,8 @@ namespace pim
void Generator::GetParticle()
{
popType(2);
pushType(DataType::Integer);
writeOpcode(Opcode::Get);
output << "getpart" << std::endl;
@ -408,6 +690,9 @@ namespace pim
void Generator::GetPosition()
{
popType(1);
pushType(DataType::Integer);
pushType(DataType::Integer);
writeOpcode(Opcode::Position);
output << "getpos" << std::endl;
@ -415,13 +700,19 @@ namespace pim
void Generator::KillParticle()
{
popType(1);
writeOpcode(Opcode::Kill);
pushType(DataType::Integer);
output << "kill" << std::endl;
}
void Generator::LoadProperty(std::string property)
void Generator::LoadProperty(std::string property, int type)
{
ForceType(DataType::Integer); //Particle type must be integer
popType(1);
pushType(type);
writeOpcode(Opcode::LoadProperty);
writeConstantPropertyPlaceholder(property);
@ -430,25 +721,19 @@ namespace pim
void Generator::StoreProperty(std::string property)
{
ForceType(DataType::Integer); //Ensure particle ID is an integer
popType(1); //Use particle ID
popType(1);
writeOpcode(Opcode::StoreProperty);
writeConstantPropertyPlaceholder(property);
output << "storeprop " << property << std::endl;
}
void Generator::IntegerToDecimal()
{
}
void Generator::DecimalToInteger()
{
}
void Generator::JumpEqual(std::string label)
{
popType(2);
writeOpcode(Opcode::JumpEqual);
writeConstantPlaceholder(label);
@ -457,6 +742,7 @@ namespace pim
void Generator::JumpNotEqual(std::string label)
{
popType(2);
writeOpcode(Opcode::JumpNotEqual);
writeConstantPlaceholder(label);
@ -465,6 +751,7 @@ namespace pim
void Generator::JumpGreater(std::string label)
{
popType(2);
writeOpcode(Opcode::JumpGreater);
writeConstantPlaceholder(label);
@ -473,6 +760,7 @@ namespace pim
void Generator::JumpGreaterEqual(std::string label)
{
popType(2);
writeOpcode(Opcode::JumpGreaterEqual);
writeConstantPlaceholder(label);
@ -481,6 +769,7 @@ namespace pim
void Generator::JumpLess(std::string label)
{
popType(2);
writeOpcode(Opcode::JumpLess);
writeConstantPlaceholder(label);
@ -489,6 +778,7 @@ namespace pim
void Generator::JumpLessEqual(std::string label)
{
popType(2);
writeOpcode(Opcode::JumpLessEqual);
writeConstantPlaceholder(label);
@ -497,6 +787,7 @@ namespace pim
void Generator::Jump(std::string label)
{
popType(2);
writeOpcode(Opcode::Jump);
writeConstantPlaceholder(label);
@ -509,10 +800,5 @@ namespace pim
}
void Generator::Return()
{
}
}
}

View File

@ -5,6 +5,7 @@
#include <stack>
#include <iostream>
#include "Token.h"
#include "Types.h"
namespace pim
{
namespace compiler
@ -36,23 +37,35 @@ namespace pim
}
~SymbolNotFoundException() throw() {};
};
class Type
{
enum { Integer = Token::IntegerSymbol, Decimal = Token::DecimalSymbol };
};
class Scope;
class Definition
{
public:
enum DefType { Function, Variable };
std::string Name;
DefType DefinitionType;
int Type;
int StackPosition;
Definition(std::string name, int type, int position) :
Type(type),
Scope * MyScope;
Definition(std::string name, int type, int position, Scope * myScope) :
Name(name),
StackPosition(position)
DefinitionType(Variable),
Type(type),
StackPosition(position),
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
@ -64,32 +77,37 @@ namespace pim
class Scope
{
public:
std::vector<Definition> Definitions;
std::vector<Definition*> Definitions;
std::vector<Label> Labels;
int FrameSize;
int LocalFrameSize;
int OldFrameSize;
Scope():
FrameSize(0),
LocalFrameSize(0)
LocalFrameSize(0),
OldFrameSize(0)
{
}
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;
}
throw VariableNotFoundException(name);
return NULL;
}
};
class Generator
{
int variableType;
std::stack<int> typeStack;
std::stack<Scope*> scopes;
Scope * currentScope;
Scope * globalScope;
FunctionDefinition * funcDef;
std::ostream & output;
int labelCounter;
int programCounter;
@ -100,6 +118,9 @@ namespace pim
typedef std::pair<int, int*> ValuePlaceholder;
std::vector<ValuePlaceholder> valuePlaceholders;
typedef std::pair<int, std::pair<int, int*> > ValueOffsetPlaceholder;
std::vector<ValueOffsetPlaceholder> valueOffsetPlaceholders;
typedef std::pair<int, std::string> PropertyPlaceholder;
std::vector<PropertyPlaceholder> propertyPlaceholders;
@ -110,31 +131,47 @@ namespace pim
std::vector<unsigned char> program;
void pushType(int type);
void popType(int count);
void defineLabel(std::string label);
void writeOpcode(int opcode);
void writeConstant(std::string constant);
void writeConstant(int constant);
void writeConstantPlaceholder(std::string label);
void writeConstantPlaceholder(int * value);
void writeConstantPlaceholderOffset(int value, int * offset);
void writeConstantMacroPlaceholder(std::string macro);
void writeConstantPropertyPlaceholder(std::string property);
public:
Generator();
virtual ~Generator();
std::vector<unsigned char> Finish();
std::string UniqueLabel(std::string prefix);
void AssureType(int type);
void ForceType(int type);
void PushScope(std::string label);
void PushLocalScope(std::string label);
void LocalEnter();
void PopScope();
void ExitScope();
void ScopeLabel(std::string label);
void ScopeVariableType(int type);
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 PushVariableAddress(std::string label);
// void Store();
void LoadVariable(std::string label);
@ -151,18 +188,17 @@ namespace pim
void Divide();
void Modulus();
void Negate();
void ToInteger();
void ToFloat();
void TransformParticle();
void CreateParticle();
void GetParticle();
void GetPosition();
void KillParticle();
void LoadProperty(std::string property);
void LoadProperty(std::string property, int type);
void StoreProperty(std::string property);
void IntegerToDecimal();
void DecimalToInteger();
void JumpEqual(std::string label);
void JumpNotEqual(std::string label);
void JumpGreater(std::string label);

View File

@ -1,9 +1,13 @@
//Virtual machine
#include <iostream>
#include <fstream>
#include "Machine.h"
#include "Opcodes.h"
#include "Types.h"
#include "simulation/Simulation.h"
#include "X86Native.h"
#include "Exceptions.h"
namespace pim
{
/*unsigned char * rom;
@ -20,7 +24,8 @@ namespace pim
VirtualMachine::VirtualMachine(Simulation * simulation) :
rom(NULL),
ram(NULL),
sim(simulation)
sim(simulation),
nativeRom(0)
{
}
@ -29,37 +34,49 @@ namespace pim
{
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();
}
int macroSize = 0, propSize = 0, codeSize = 0;
macroSize = fileData[4];
macroSize |= fileData[5] << 8;
macroSize |= fileData[6] << 16;
macroSize |= fileData[7] << 24;
int macroSize = 0, propSize = 0, codeSize = 0, heapSize = 0, symtableSize = 0;
propSize = fileData[8];
propSize |= fileData[9] << 8;
propSize |= fileData[10] << 16;
propSize |= fileData[11] << 24;
heapSize = fileData[4];
heapSize |= fileData[5] << 8;
heapSize |= fileData[6] << 16;
heapSize |= fileData[7] << 24;
codeSize = fileData[12];
codeSize |= fileData[13] << 8;
codeSize |= fileData[14] << 16;
codeSize |= fileData[15] << 24;
macroSize = fileData[8];
macroSize |= fileData[9] << 8;
macroSize |= fileData[10] << 16;
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();
}
//std::vector<std::pair<int, int> > insertions;
int macroOffset = 16;
int macroOffset = 24;
int propOffset = macroOffset+macroSize;
int codeOffset = propOffset+propSize;
int symtableOffset = propOffset+propSize;
int codeOffset = symtableOffset+symtableSize;
int filePosition = macroOffset;
@ -171,6 +188,59 @@ namespace pim
//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;
programData.insert(programData.begin(), fileData.begin()+codeOffset, fileData.begin()+codeOffset+codeSize);
@ -182,6 +252,7 @@ namespace pim
rom = new Instruction[romSize];
int pc = 0;
int programPosition = 0;
@ -190,7 +261,7 @@ namespace pim
int argSize = 0;
Instruction instruction;
instruction.Opcode = programData[programPosition++];
if(argSize = OpcodeArgSize(instruction.Opcode))
if(argSize = opcodeArgSize(instruction.Opcode))
{
if(argSize == 4 && programPosition+3 < programData.size())
{
@ -201,7 +272,7 @@ namespace pim
tempInt |= programData[programPosition+3] << 24;
std::cout << "Got integer " << tempInt << std::endl;
//std::cout << "Got integer " << tempInt << std::endl;
if(instruction.Opcode == Opcode::LoadProperty || instruction.Opcode == Opcode::StoreProperty)
{
@ -209,6 +280,12 @@ namespace pim
throw InvalidProgramException();
}
if(instruction.Opcode == Opcode::LoadAdr || instruction.Opcode == Opcode::StoreAdr)
{
if(tempInt > heapSize)
throw InvalidProgramException();
}
instruction.Parameter.Integer = tempInt;
programPosition += 4;
@ -231,14 +308,19 @@ namespace pim
framePointer = callStack;
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)
{
switch(opcode)
{
case Opcode::Load:
case Opcode::LoadAdr:
case Opcode::Store:
case Opcode::StoreAdr:
case Opcode::Constant:
case Opcode::Increment:
case Opcode::JumpEqual:
@ -248,11 +330,13 @@ namespace pim
case Opcode::JumpLess:
case Opcode::JumpLessEqual:
case Opcode::Jump:
case Opcode::Return:
case Opcode::Leave:
case Opcode::LocalEnter:
case Opcode::LoadProperty:
case Opcode::StoreProperty:
return 4;
case Opcode::Begin:
case Opcode::Return:
case Opcode::Discard:
case Opcode::Duplicate:
case Opcode::Add:
@ -266,11 +350,13 @@ namespace pim
case Opcode::Get:
case Opcode::Position:
case Opcode::Kill:
case Opcode::ToFloat:
case Opcode::ToInteger:
return 0;
}
}
void VirtualMachine::Run()
void VirtualMachine::run()
{
//std::cout << "CS: " << callStack << " PS: " << programStack << std::endl;
//std::string names[] = { "Load", "Store", "Constant", "Increment", "Discard", "Duplicate", "Add", "Subtract", "Multiply", "Divide", "Modulus", "Negate", "Create", "Transform", "Get", "Position", "Kill", "JumpEqual", "JumpNotEqual", "JumpGreater", "JumpGreaterEqual", "JumpLess", "JumpLessEqual", "Jump", "Return", "LocalEnter"};
@ -286,6 +372,8 @@ namespace pim
//std::cerr << programCounter << "\t" << names[rom[programCounter].Opcode] << "\t" << argument.Integer << std::endl;//"\t";
switch(rom[programCounter].Opcode)
{
case Opcode::Begin:
break;
case Opcode::Load:
PSPush(CSA(argument.Integer));
break;
@ -399,9 +487,11 @@ namespace pim
case Opcode::Jump:
programCounter = argument.Integer-1;
break;
case Opcode::Return:
case Opcode::Leave:
callStack += argument.Integer;
break;
case Opcode::Return:
break;
case Opcode::LocalEnter:
callStack -= argument.Integer;
break;
@ -414,224 +504,64 @@ namespace pim
void VirtualMachine::Compile()
{
while(programCounter < romSize)
Native * native = new X86Native();
if(nativeRom)
delete[] nativeRom;
if(nativeStack)
delete[] nativeStack;
nativeStack = new unsigned char [1024*1024];
std::vector<unsigned char> executableCode = native->Compile(sim, nativeStack + (1024*512), heap, rom, romSize);
virtualXToNative = native->GetAddressMap();
nativeRom = new unsigned char[executableCode.size()];
std::copy(executableCode.begin(), executableCode.end(), nativeRom);
delete native;
}
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)
{
Word argument = rom[programCounter].Parameter;
switch(rom[programCounter].Opcode)
Function f = *iter;
if(f.Name == entryPoint)
{
case Opcode::Load:
emit("83 EF 04"); //sub edi 4
//Load value at base stack + offset into eax
emit("8B 85"); //mov eax [ebp+ram+offset]
emit((intptr_t) (ram - argument.Integer));
//Store value in eax onto top of program stack
emit("89 07"); //mov [edi], eax
emit((intptr_t) (ram));
break;
case Opcode::Store:
//Load value on top of the program stack into eax
emit("8B 07"); //mov eax [edi]
emit((intptr_t) (ram));
//Load value in eax onto top of program stack
emit("89 85"); //mov [ebp+ram+offset], eax
emit((intptr_t) (ram - argument.Integer));
emit("83 C7 04"); //add edi 4
break;
case Opcode::Constant:
emit("83 EF 04"); //sub edi 4
emit("C7 07"); //mov [edi] constant
emit((int) (argument.Integer));
break;
case Opcode::Increment:
emit("81 07"); //add [edi] constant
emit((int) (argument.Integer));
break;
case Opcode::Discard:
emit("83 C7 04"); //add edi 4
break;
case Opcode::Duplicate:
//Copy value on stack into register
emit("8B 07"); //mov eax [edi]
//Adjust program stack pointer
emit("83 EF 04"); //sub edi 4
//Move value in eax into program stack
emit("89 07"); //mov [edi], eax
break;
case Opcode::Add:
emit("8B 07"); //mov eax [edi]
emit("01 47 04"); //add [edi+4] eax
emit("83 C7 04"); //add edi 4
break;
case Opcode::Subtract:
emit("8B 07"); //mov eax [edi]
emit("29 47 04"); //sub [edi+4] eax
emit("83 C7 04"); //add edi 4
break;
case Opcode::Multiply:
emit("8B 47 04"); //mov eax [edi+4]
emit("F7 2F"); //imul [edi]
emit("89 47 04"); //mov [edi+4] eax
emit("83 C7 04"); //add edi 4
break;
case Opcode::Divide:
emit("8B 47 04");//mov eax [edi+4]
emit("99"); //cdq
emit("F7 3F"); //idiv [edi]
emit("89 47 04"); //mov [edi+4] eax
emit("83 C7 04"); //add edi 4
break;
case Opcode::Modulus:
emit("8B 47 04"); // mov eax [edi+4]
emit("99"); // cdq
emit("F7 3F"); // idiv [edi]
emit("89 57 04"); // mov [edi+4] edx
emit("83 C7 04"); //add edi 4
break;
case Opcode::Negate:
emit("F7 1F"); //neg [edi]
break;
case Opcode::Create:
//temp1 = PSPop();
//temp2 = PSPop();
//temp3 = PSPop();
//PSPush(sim->create_part(PSPop().Integer, temp3.Integer, temp2.Integer, temp1.Integer));
break;
case Opcode::Transform:
//PSPop();
//PSPop();
//PSPush((Word)-1);
break;
case Opcode::Get:
//temp1 = PSPop();
//temp2 = PSPop();
//if(temp1.Integer < 0 || temp1.Integer >= YRES || temp2.Integer < 0 || temp2.Integer >= XRES || !(temp = sim->pmap[temp1.Integer][temp2.Integer]))
//{
// PSPush(-1);
// break;
//}
//PSPush(temp>>8);
break;
case Opcode::Position:
//temp1 = PSPop();
//if(temp1.Integer < 0 || temp1.Integer >= NPART || !sim->parts[temp1.Integer].type)
//{
// PSPush(-1);
// PSPush(-1);
// break;
//}
//PSPush((int)sim->parts[temp1.Integer].x);
//PSPush((int)sim->parts[temp1.Integer].y);
break;
case Opcode::Kill:
//sim->kill_part(PSPop().Integer);
//PSPush((Word)0);
break;
case Opcode::LoadProperty:
//PSPush(PPROP(PSPop().Integer, argument.Integer));
break;
case Opcode::StoreProperty:
//temp1 = PSPop();
//PPROP(temp1.Integer, argument.Integer) = PSPop();
break;
case Opcode::JumpEqual:
emit("83 C7 04"); //add edi 8
emit("8B 47 FC"); //mov eax, dword ptr [edi-4]
emit("3B 47 F7"); //cmp eax, dword ptr [edi-8]
emit("75 06"); //jne +6
emit("FF 25"); //jmp [0x12345678]
emit(0);
break;
case Opcode::JumpNotEqual:
emit("83 C7 04"); //add edi 8
emit("8B 47 FC"); //mov eax, dword ptr [edi-4]
emit("3B 47 F7"); //cmp eax, dword ptr [edi-8]
emit("74 06"); //je +6
emit("FF 25"); //jmp [0x12345678]
emit(0);
break;
case Opcode::JumpGreater:
emit("83 C7 04"); //add edi 8
emit("8B 47 FC"); //mov eax, dword ptr [edi-4]
emit("3B 47 F7"); //cmp eax, dword ptr [edi-8]
emit("7E 06"); //jng +6
emit("FF 25"); //jmp [0x12345678]
emit(0);
break;
case Opcode::JumpGreaterEqual:
emit("83 C7 04"); //add edi 8
emit("8B 47 FC"); //mov eax, dword ptr [edi-4]
emit("3B 47 F7"); //cmp eax, dword ptr [edi-8]
emit("7C 06"); //jnge +6
emit("FF 25"); //jmp [0x12345678]
emit(0);
break;
case Opcode::JumpLess:
emit("83 C7 04"); //add edi 8
emit("8B 47 FC"); //mov eax, dword ptr [edi-4]
emit("3B 47 F7"); //cmp eax, dword ptr [edi-8]
emit("7D 06"); //jnl +6
emit("FF 25"); //jmp [0x12345678]
emit(0);
break;
case Opcode::JumpLessEqual:
emit("83 C7 04"); //add edi 8
emit("8B 47 FC"); //mov eax, dword ptr [edi-4]
emit("3B 47 F7"); //cmp eax, dword ptr [edi-8]
emit("7F 06"); //jnle +6
emit("FF 25"); //jmp [0x12345678]
emit(0);
break;
case Opcode::Jump:
//programCounter = argument.Integer-1;
break;
case Opcode::Return:
emit("81 C6"); //add esi constant
emit(argument.Integer);
break;
case Opcode::LocalEnter:
emit("81 EE"); //sub esi constant
emit(argument.Integer);
break;
printf("Got native entry point for %s at %p\n", entryPoint.c_str(), nativeRom+virtualXToNative[f.Position]);
fflush(stdout);
return nativeRom+virtualXToNative[f.Position];
}
//std::cout << programStack << std::endl;
programCounter++;
}
//std::cout << "CS: " << callStack << " PS: " << programStack << std::endl;
throw FunctionNotFoundException(entryPoint, returnType, argTypes);
}
void VirtualMachine::emit(std::string opcode)
/*void * VirtualMachine::GetNativeEntryPoint(intptr_t entryPoint)
{
return nativeRom+entryPoint;
}*/
}
void VirtualMachine::emit(int constant)
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::CallCompiled(std::string entryPoint)
/*void VirtualMachine::Run(std::string entryPoint)
{
}*/
}
void VirtualMachine::CallCompiled(int entryPoint)
{
}
void VirtualMachine::Call(std::string entryPoint)
{
}
void VirtualMachine::Call(int entryPoint)
void VirtualMachine::Run(int entryPoint)
{
programCounter = entryPoint;
Run();
run();
}
}

View File

@ -3,6 +3,7 @@
#include <vector>
#include <string>
#include <cstring>
#include <map>
class Simulation;
namespace pim
@ -47,6 +48,36 @@ namespace pim
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 OPDEF(name) void op##name(int parameter);
@ -59,12 +90,17 @@ namespace pim
int romSize;
int romMask;
unsigned char * nativeRom;
unsigned char * nativeStack;
unsigned char * compiledRom;
int compiledRomSize;
unsigned char * ram;
int ramSize;
int ramMask;
unsigned char * heap;
int heapSize;
#define CSA(argument) (*((Word*)&ram[framePointer-argument]))
#define CS() (*((Word*)&ram[callStack]))
@ -77,20 +113,24 @@ namespace pim
//Instruction * instructions;
int programCounter;
std::vector<Function> functions;
std::vector<Variable> variables;
std::map<int, int> virtualXToNative;
void emit(std::string opcode);
void emit(int constant);
int programCounter;
void run();
int opcodeArgSize(int opcode);
public:
VirtualMachine(Simulation * sim);
int OpcodeArgSize(int opcode);
void LoadProgram(std::vector<unsigned char> programData);
void Run();
void Compile();
void CallCompiled(std::string entryPoint);
void CallCompiled(int entryPoint);
void Call(std::string entryPoint);
void Call(int entryPoint);
void * GetNativeEntryPoint(std::string entryPoint, std::string returnType, std::string argTypes);
int GetEntryPoint(std::string entryPoint, std::string returnType, std::string argTypes);
void Run(int entryPoint);
inline bool IsCompiled()
{
return nativeRom != 0;
}
inline void PSPush(Word word)
{
programStack -= WORDSIZE;

54
src/pim/Native.h Normal file
View File

@ -0,0 +1,54 @@
#include "Machine.h"
#include <map>
namespace pim
{
class Native
{
protected:
std::vector<unsigned char> nativeRom;
void emit(std::string opcode)
{
unsigned char c1, c2;
unsigned char v;
const char * string = opcode.c_str();
while (true)
{
c1 = string[0];
c2 = string[1];
v = (hex( c1 ) << 4) | hex(c2);
nativeRom.push_back(v);
if (!string[2])
{
break;
}
string += 3;
}
}
unsigned char hex(char c)
{
if (c >= 'a' && c <= 'f')
return 10 + c - 'a';
if (c >= 'A' && c <= 'F')
return 10 + c - 'A';
if (c >= '0' && c <= '9')
return c - '0';
return 0;
}
virtual void emitConstantS(short int constant) {} //Single
virtual void emitConstantD(long int constant) {} //Double
virtual void emitConstantP(intptr_t constant) {} //Pointer
virtual void emitConstantQ(long long int constant) {} //Quad
virtual void emitCall(intptr_t objectPtr, intptr_t functionAddress, int stackSize) {}
virtual void emitPlaceholder(int virtualAddress) {}
public:
Native() : nativeRom() {}
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

@ -2,6 +2,7 @@ namespace pim
{
struct Opcode
{
public:
enum
{
#define OPDEF(name) name,

View File

@ -1,5 +1,10 @@
OPDEF(Begin)
OPDEF(Load)
OPDEF(LoadAdr)
OPDEF(ToFloat)
OPDEF(ToInteger)
OPDEF(Store)
OPDEF(StoreAdr)
OPDEF(Constant)
OPDEF(Increment)
OPDEF(Discard)
@ -25,4 +30,5 @@ OPDEF(JumpLess)
OPDEF(JumpLessEqual)
OPDEF(Jump)
OPDEF(Return)
OPDEF(Leave)
OPDEF(LocalEnter)

View File

@ -1,6 +1,10 @@
//Syntax analyser
#include "Parser.h"
#include "Format.h"
#include "Types.h"
#include "Exceptions.h"
#include "simulation/Particle.h"
#include "simulation/StructProperty.h"
namespace pim
{
namespace compiler
@ -26,21 +30,12 @@ namespace pim
*/
void Parser::program()
{
functionList();
globalList();
//functionList();
}
/*
<function list> ::= <function> | <function> <function list>
*/
void Parser::functionList()
{
function();
while(look(Token::FunctionSymbol))
function();
}
/*
<function> ::= function identifier ( <declaration list> ) <block> end
<function> ::= function identifier ( <declaration list> ) <block> end | function type identifier ( <declaration list> ) <block> end
*/
void Parser::function()
{
@ -48,8 +43,15 @@ namespace pim
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;
//generator->ScopeLabel(functionName); //Function name
generator->PushScope(functionName);
expect(Token::Identifier);
@ -59,11 +61,13 @@ namespace pim
argumentList();
expect(Token::RightBracket);
}
generator->DeclareFunction(functionName);
block();
expect(Token::EndSymbol);
generator->ExitScope();
generator->Return();
generator->PopScope();
}
/*
@ -73,6 +77,7 @@ namespace pim
{
std::string functionName;
//generator->BeginCall();
functionName = token.Source;
expect(Token::Identifier);
expect(Token::LeftBracket);
@ -106,12 +111,24 @@ namespace pim
*/
void Parser::argument()
{
generator->ScopeVariableType(token.Symbol);
int type;
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->ScopeVariable(token.Source);
generator->FunctionArgument(type);
expect(Token::Identifier);
}
@ -130,13 +147,67 @@ namespace pim
*/
void Parser::declaration()
{
generator->ScopeVariableType(token.Symbol);
int type;
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");
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>
@ -238,12 +309,16 @@ namespace pim
expect(Token::CreateSymbol);
expect(Token::LeftBracket);
expression();
generator->AssureType(DataType::Integer);
expect(Token::CommaSymbol);
expression();
generator->AssureType(DataType::Integer);
expect(Token::CommaSymbol);
expression();
generator->AssureType(DataType::Integer);
expect(Token::CommaSymbol);
expression();
generator->AssureType(DataType::Integer);
expect(Token::RightBracket);
generator->CreateParticle();
}
@ -296,7 +371,7 @@ namespace pim
generator->PushLocalScope(loopLabel+"Start");
neighbourVariable = token.Source;
expect(Token::Identifier);
generator->ScopeVariableType(Token::IntegerConstant);
generator->ScopeVariableType(DataType::Integer);
generator->ScopeVariable(neighbourVariable);
generator->ScopeVariable(xVar);
generator->ScopeVariable(yVar);
@ -331,10 +406,6 @@ namespace pim
generator->ScopeLabel(loopLabel+"Next");
//Check X
generator->LoadVariable(xVar);
generator->LoadVariable(xMax);
@ -378,7 +449,7 @@ namespace pim
generator->Jump(loopLabel+"Next");
generator->ScopeLabel(loopLabel+"End");
generator->Return();
//generator->Return();
generator->PopScope();
expect(Token::EndSymbol);
}
@ -471,6 +542,8 @@ namespace pim
expect(Token::Identifier);
expect(Token::AssignSymbol);
expression();
generator->AssureType(GetPropertyType(property));
generator->LoadVariable(variable);
generator->StoreProperty(property);
}
@ -566,7 +639,11 @@ namespace pim
void Parser::variableValue()
{
std::string variable = token.Source;
if(accept(Token::Identifier))
if(look(Token::CreateSymbol) || look(Token::KillSymbol) || look(Token::GetSymbol) || look(Token::TransformSymbol))
{
particleAction();
}
else if(accept(Token::Identifier))
{
if(look(Token::LeftBracket))
{
@ -580,7 +657,7 @@ namespace pim
std::string property = token.Source;
expect(Token::Identifier);
generator->LoadVariable(variable);
generator->LoadProperty(property);
generator->LoadProperty(property, GetPropertyType(property));
}
else
{
@ -592,10 +669,6 @@ namespace pim
{
generator->RTConstant(variable);
}
else
{
particleAction();
}
}
bool Parser::accept(int symbol)
@ -649,5 +722,23 @@ namespace pim
if(!accept(symbol))
throw ParserExpectException(token, symbol);
}
int Parser::GetPropertyType(std::string property)
{
int t2 = DataType::Integer;
StructProperty::PropertyType t = Particle::GetProperty(property).Type;
switch(t){
case StructProperty::ParticleType:
case StructProperty::Colour:
case StructProperty::Integer:
case StructProperty::UInteger:
t2 = DataType::Integer;
break;
case StructProperty::Float:
t2 = DataType::Float;
break;
}
return t2;
}
}
}

View File

@ -10,22 +10,6 @@ namespace pim
{
namespace compiler
{
class ParserExpectException: public std::exception
{
char * error;
public:
ParserExpectException(Token token, int expectingSymbol) {
error = strdup(std::string("Expecting " + Token::SymbolNames[expectingSymbol] + " got " + token.Source).c_str());
}
ParserExpectException(Token token, std::string expectingString) {
error = strdup(std::string("Expecting " + expectingString + " got " + token.Source).c_str());
}
const char * what() const throw()
{
return error;
}
~ParserExpectException() throw() {};
};
class Parser
{
std::stringstream & source;
@ -46,6 +30,8 @@ namespace pim
void argument();
void declarationList();
void declaration();
void globalList();
void global();
void identifierList();
void statementList();
void statement();
@ -74,6 +60,7 @@ namespace pim
Parser(std::stringstream & source_);
std::vector<unsigned char> Compile();
int GetPropertyType(std::string property);
};
}
}

View File

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

View File

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

View File

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

View File

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

37
src/pim/Types.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include <string>
#include <vector>
#include <sstream>
namespace pim
{
struct DataType
{
public:
enum
{
Integer,
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();
}
}

355
src/pim/X86Native.cpp Normal file
View File

@ -0,0 +1,355 @@
#include "Opcodes.h"
#include "X86Native.h"
#include "simulation/Simulation.h"
namespace pim
{
std::vector<unsigned char> X86Native::Compile(Simulation * sim, unsigned char * machineStack, unsigned char * heap, Instruction * rom, int romSize)
{
#if defined(X86) && !defined(_64BIT)
int programCounter = 0;
nativeRom.clear();
for(int i = 0; i < 8; i++) { emit("90"); } //nop, helps find the code in memory with a debugger
//emit("BE"); //mov esi, machineStack
//emitConstantP((intptr_t)machineStack);
while(programCounter < romSize)
{
Word argument = rom[programCounter].Parameter;
virtualToNative[programCounter] = nativeRom.size();
switch(rom[programCounter].Opcode)
{
case Opcode::Begin:
emit("BE"); //mov esi, machineStack
emitConstantP((intptr_t)machineStack);
break;
case Opcode::Load:
emit("83 EE 04"); //sub esi, 4
//Load value at base stack + offset into eax
//emit("8B 85"); //mov eax, [ebp+offset]
emit("8B 84 24"); //mov eax, [esp+offset]
emitConstantP(argument.Integer);
//Store value in eax onto top of program stack
emit("89 06"); //mov [esi], eax
break;
case Opcode::Store:
//Load value on top of the program stack into eax
emit("8B 06"); //mov eax, [esi]
//Load value in eax into memory
emit("89 84 24"); //mov [esp+offset], eax
emitConstantD(argument.Integer);
emit("83 C6 04"); //add esi, 4
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:
emit("83 EE 04"); //sub esi, 4
emit("C7 06"); //mov [esi], dword ptr constant
emitConstantD(argument.Integer);
break;
case Opcode::Increment:
if(argument.Integer > 0) {
emit("81 06"); //add [esi], dword ptr constant
emitConstantD(argument.Integer);
} else {
emit("81 2E"); //sub [esi], dword ptr constant
emitConstantD(-argument.Integer);
}
break;
case Opcode::Discard:
emit("83 C6 04"); //add esi, 4
break;
case Opcode::Duplicate:
//Copy value on stack into register
emit("8B 06"); //mov eax, [esi]
//Adjust program stack pointer
emit("83 EE 04"); //sub esi, 4
//Move value in eax into program stack
emit("89 06"); //mov [esi], eax
break;
case Opcode::Add:
emit("8B 06"); //mov eax, [esi]
emit("83 C6 04"); //add esi, 4
emit("01 06"); //add [esi], eax
break;
case Opcode::Subtract:
emit("8B 06"); //mov eax, [esi]
emit("83 C6 04"); //add esi, 4
emit("29 06"); //sub [esi], eax
break;
case Opcode::Multiply:
emit("8B 46 04"); //mov eax, [esi+4]
emit("F7 2E"); //imul [esi]
emit("83 C6 04"); //add esi, 4
emit("89 06"); //mov [esi], eax
break;
case Opcode::Divide:
emit("8B 46 04"); //mov eax [esi+4]
emit("99"); //cdq
emit("F7 3E"); //idiv [esi]
emit("83 C6 04"); //add esi, 4
emit("89 06"); //mov [esi], eax
break;
case Opcode::Modulus:
emit("8B 46 04"); //mov eax [esi+4]
emit("99"); //cdq
emit("F7 3E"); //idiv [esi]
emit("83 C6 04"); //add esi, 4
emit("89 16"); //mov [esi], edx
break;
case Opcode::Negate:
emit("F7 1E"); //neg [esi]
break;
case Opcode::Create:
emit("8B 06"); //mov eax, [esi]
emit("50"); //push eax
emit("8B 46 04"); //mov eax, [esi+4]
emit("50"); //push eax
emit("8B 46 08"); //mov eax, [esi+8]
emit("50"); //push eax
emit("8B 46 0C"); //mov eax, [esi+12]
emit("50"); //push eax
emit("83 C6 08"); //add esi, 8
emitCall((intptr_t)sim, (intptr_t)((void*)&Simulation::create_part), 16);
emit("89 06"); //mov [esi], eax
break;
case Opcode::Transform:
//PSPop();
//PSPop();
//PSPush((Word)-1);
break;
case Opcode::Get:
{
intptr_t partsArray = (intptr_t)sim->pmap;
emit("8B 06"); //mov eax, [esi]
emit("8B 4E 04"); //mov ecx, [esi+4]
emit("81 F9"); //cmp ecx, XRES //Push -1 if y is out of range
emitConstantD((int)XRES);
emit("7D 2C"); //|--< //jge 34
emit("83 F9 00"); //| //cmp ecx, 0
emit("78 27"); //|--< //js 32
emit("3D"); //| //cmp eax, YRES //Push -1 if x is out of range
emitConstantD((int)YRES); //|
emit("7D 20"); //|--< //jge 25
emit("83 F8 00"); //| //cmp eax, 0
emit("78 1B"); //|--< //js 23
emit("69 C0"); //| //imul eax, 612
emitConstantD((int)XRES); //|
emit("01 C8"); //| //add eax, ecx
emit("8B 04 85"); //| //mov eax, [eax*4+pmap]
emitConstantP((int)partsArray); //|
emit("85 C0"); //| //test eax, eax //Push 0 if location if empty
emit("74 08"); //| |-< //je +5
emit("C1 F8 08"); //| | //sar eax, 8
emit("89 46 04"); //| | //mov [esi+4], eax #Copy eax onto stack
emit("EB 07"); //| |-< //jmp +7
emit("C7 46 04 FF FF FF FF"); //L-+-> //mov [esi+4], -1
emit("83 C6 04"); // L-> //add esi, 4
}
break;
case Opcode::Position:
{
intptr_t partsArray = (intptr_t)sim->parts;
emit("8B 06"); //mov eax, [esi] #Load index from stack
emit("3D"); //cmp eax, NPART
emitConstantD((int)NPART);
emit("7D 26"); //|--< //jge 31
emit("83 F8 00"); //| //cmp eax, 0
emit("78 21"); //|--< //js 29
emit("C1 E0 03"); //| //sal eax, 3 #Shift index left (multiply by 8)
emit("8D 14 C5 00 00 00 00"); //| //lea edx, [eax*8] #Mutiply by 8 again and copy into edx //Size of 56 is represented by (1*(8^2))-(1*8)
emit("89 D1"); //| //mov ecx, edx
emit("29 C1"); //| //sub ecx, eax #Subtract index*8^2 by index*8 to get the index*56
emit("D9 81"); //| //fld [ecx+xOffset+partsArray]
emitConstantP(partsArray+offsetof(Particle, x));
emit("DB 1E"); //| //fistp [esi]
emit("D9 81"); //| //fld [ecx+xOffset+partsArray]
emitConstantP(partsArray+offsetof(Particle, y));
emit("DB 5E FC"); //| //fistp [esi-4], eax #Copy eax onto stack
emit("EB 0D"); //| |-< //jmp +13
emit("C7 06 FF FF FF FF"); //L-+-> //mov [esi], -1
emit("C7 46 FC FF FF FF FF"); // | //mov [esi-4] -1
emit("83 EE 04"); // L-> //sub esi, 4
}
break;
case Opcode::Kill:
emit("8B 06"); //mov eax, [esi]
emit("50"); //push eax
emitCall((intptr_t)sim, (intptr_t)((void*)&Simulation::kill_part), 4);
emit("C7 06 00 00 00 00"); //mov [esi], eax
break;
case Opcode::LoadProperty:
{
intptr_t propertyOffset = argument.Integer;
intptr_t partsArray = (intptr_t)sim->parts;
emit("8B 06"); //mov eax, [esi] #Load index from stack
emit("C1 E0 03"); //sal eax, 3 #Shift index left (multiply by 8)
emit("8D 14 C5 00 00 00 00"); //lea edx, [eax*8] #Mutiply by 8 again and copy into edx //Size of 56 is represented by (1*(8^2))-(1*8)
emit("89 D1"); //mov ecx, edx
emit("29 C1"); //sub ecx, eax #Subtract index*8^2 by index*8 to get the index*56
emit("8B 81"); //mov eax, [ecx+propertyOffset+partsArray] #Copy value at index+baseAddress+propertyOffset into eax
emitConstantP(partsArray+propertyOffset);
emit("89 06"); //mov [esi], eax #Copy eax onto stack
}
break;
case Opcode::StoreProperty:
{
intptr_t propertyOffset = argument.Integer;
intptr_t partsArray = (intptr_t)sim->parts;
emit("8B 06"); //mov eax, [esi]
emit("C1 E0 03"); //sal eax, 3
emit("8D 14 C5 00 00 00 00"); //lea edx, [eax*8]
emit("89 D1"); //mov ecx, edx
emit("29 C1"); //sub ecx, eax
emit("8B 46 04"); //mov eax, [esi+4]
emit("89 81"); //mov [ecx+propertyOffset+partsArray], eax
emitConstantP(partsArray+propertyOffset);
emit("83 C6 08"); //add esi, 8
}
break;
case Opcode::ToFloat:
emit("DB 06"); //fild [esi]
emit("D9 1E"); //fstp [esi]
break;
case Opcode::ToInteger:
emit("D9 06"); //fld [esi]
emit("DB 1E"); //fistp [esi]
break;
case Opcode::JumpEqual:
emit("83 C6 08"); //add esi, 8
emit("8B 46 FC"); //mov eax, [esi-4]
emit("3B 46 F8"); //cmp eax, [esi-8]
emit("75 05"); //jne 8
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
break;
case Opcode::JumpNotEqual:
emit("83 C6 08"); //add esi, 8
emit("8B 46 FC"); //mov eax, [esi-4]
emit("3B 46 F8"); //cmp eax, [esi-8]
emit("74 05"); //je 8
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
break;
case Opcode::JumpGreater:
emit("83 C6 08"); //add esi 8
emit("8B 46 FC"); //mov eax, [esi-4]
emit("3B 46 F8"); //cmp eax, [esi-8]
emit("7E 05"); //jng 8
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
break;
case Opcode::JumpGreaterEqual:
emit("83 C6 08"); //add esi 8
emit("8B 46 FC"); //mov eax, [esi-4]
emit("3B 46 F8"); //cmp eax, [esi-8]
emit("7C 05"); //jnge +6
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
break;
case Opcode::JumpLess:
emit("83 C6 08"); //add esi 8
emit("8B 46 FC"); //mov eax, [esi-4]
emit("3B 46 F8"); //cmp eax, [esi-8]
emit("7D 05"); //jnl +6
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
break;
case Opcode::JumpLessEqual:
emit("83 C6 08"); //add esi 8
emit("8B 46 FC"); //mov eax, [esi-4]
emit("3B 46 F8"); //cmp eax, [esi-8]
emit("7F 08"); //jnle +6
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
break;
case Opcode::Jump:
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
break;
case Opcode::Return:
emit("C3"); //ret
break;
case Opcode::Leave:
emit("81 C4"); //add esp, constant
emitConstantD(argument.Integer);
break;
case Opcode::LocalEnter:
emit("81 EC"); //sub esp constant
emitConstantD(argument.Integer);
break;
}
//std::cout << programStack << std::endl;
programCounter++;
}
for(int i = 0; i < 8; i++) { emit("90"); } //nop, helps find the code in memory with a debugger
for(std::map<int, int>::iterator iter = placeholders.begin(), end = placeholders.end(); iter != end; ++iter)
{
std::pair<int, int> placeholder = *iter;
int newNativeAddress = virtualToNative[placeholder.second]-placeholder.first-4;
nativeRom[placeholder.first] = newNativeAddress & 0xFF;
nativeRom[placeholder.first+1] = (newNativeAddress >> 8) & 0xFF;
nativeRom[placeholder.first+2] = (newNativeAddress >> 16) & 0xFF;
nativeRom[placeholder.first+3] = (newNativeAddress >> 24) & 0xFF;
}
//std::cout << "CS: " << callStack << " PS: " << programStack << std::endl;
return nativeRom;
#endif
}
void X86Native::emitPlaceholder(int virtualAddress)
{
placeholders[nativeRom.size()] = virtualAddress;
emitConstantD((int)0);
}
void X86Native::emitCall(intptr_t objectPtr, intptr_t functionAddress, int stackSize)
{
#ifdef _MSC_VER
//MSVC puts the instance pointer in ecx, not on the stack
emit("B9"); //mov ecx, instancePointer
emitConstantP(objectPtr);
emit("B8"); //mov eax, functionAddress
emitConstantP(functionAddress);
emit("FF D0"); //call eax
emit("81 C4"); //add esp, stacksize
emitConstantD(stackSize);
#else
emit("68"); //push instancePointer
emitConstantP(objectPtr);
emit("B8"); //mov eax, functionAddress
emitConstantP(functionAddress);
emit("FF D0"); //call eax
emit("81 C4"); //add esp, stacksize
emitConstantD(stackSize+sizeof(intptr_t));
#endif
}
void X86Native::emitConstantD(long int constant)
{
nativeRom.push_back(constant & 0xFF);
nativeRom.push_back((constant >> 8) & 0xFF);
nativeRom.push_back((constant >> 16) & 0xFF);
nativeRom.push_back((constant >> 24) & 0xFF);
}
void X86Native::emitConstantP(intptr_t constant)
{
emitConstantD(constant);
}
}

21
src/pim/X86Native.h Normal file
View File

@ -0,0 +1,21 @@
#include <vector>
#include <map>
#include "Native.h"
namespace pim
{
class X86Native : public Native
{
public:
X86Native() : Native() {}
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:
virtual void emitConstantD(long int constant);
virtual void emitConstantP(intptr_t constant);
virtual void emitCall(intptr_t objectPtr, intptr_t functionAddress, int stackSize);
virtual void emitPlaceholder(int virtualAddress);
std::map<int, int> virtualToNative;
std::map<int, int> placeholders;
};
}

View File

@ -25,3 +25,15 @@ std::vector<StructProperty> Particle::GetProperties()
properties.push_back(StructProperty("dcolour", StructProperty::UInteger, offsetof(Particle, dcolour)));
return properties;
}
StructProperty Particle::GetProperty(std::string propertyName)
{
std::vector<StructProperty> types = GetProperties();
for(std::vector<StructProperty>::iterator iter = types.begin(), end = types.end(); iter != end; ++iter)
{
if((*iter).Name == propertyName)
return *iter;
}
return StructProperty("unknown", StructProperty::Float, 0);
}

View File

@ -26,6 +26,7 @@ struct Particle
/** Returns a list of properties, their type and offset within the structure that can be changed
by higher-level processes refering to them by name such as Lua or the property tool **/
static std::vector<StructProperty> GetProperties();
static StructProperty GetProperty(std::string propertyName);
};
#endif

View File

@ -140,7 +140,7 @@ public:
void init_can_move();
void create_cherenkov_photon(int pp);
void create_gain_photon(int pp);
TPT_NO_INLINE void kill_part(int i);
TPT_NO_INLINE TPT_VM_CALLABLE void kill_part(int i);
int flood_prop(int x, int y, size_t propoffset, void * propvalue, StructProperty::PropertyType proptype);
int flood_prop_2(int x, int y, size_t propoffset, void * propvalue, StructProperty::PropertyType proptype, int parttype, char * bitmap);
int flood_water(int x, int y, int i, int originaly, int check);
@ -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);
//int InCurrentBrush(int i, int j, int rx, int ry);
//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);
void get_sign_pos(int i, int *x0, int *y0, int *w, int *h);
TPT_NO_INLINE int is_wire(int x, int y);