X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Floader%2FCompiler.cpp;h=13f3dfc24ba0b1416ef87bfdd2976b9f9c8003dd;hb=HEAD;hp=96c0cc1425b643a8068a7b5ff6c8e2ff3697069e;hpb=1970312e983541d32d4ff73c81b8d90156a7bb99;p=l2e.git diff --git a/src/loader/Compiler.cpp b/src/loader/Compiler.cpp index 96c0cc1..13f3dfc 100644 --- a/src/loader/Compiler.cpp +++ b/src/loader/Compiler.cpp @@ -2,6 +2,7 @@ #include "Interpreter.h" #include "TypeDescription.h" +#include "../common/Script.h" #include #include @@ -18,6 +19,7 @@ using std::iostream; using std::make_pair; using std::map; using std::ostream; +using std::pair; using std::runtime_error; using std::set; using std::string; @@ -51,6 +53,9 @@ void Compiler::Write(iostream &out) { fileHeader.arraysBegin = out.tellp(); WriteArrays(out); fileHeader.arraysEnd = out.tellp(); + fileHeader.scriptsBegin = out.tellp(); + WriteScripts(out); + fileHeader.scriptsEnd = out.tellp(); out.seekp(0); WriteHeader(out); WriteExports(out); @@ -148,6 +153,11 @@ void Compiler::WriteObjects(ostream &out) { Write(out, &object, sizeof(Object)); addressMap.insert(make_pair(*j, out.tellp())); Write(out, *j, object.size); + + if (td.TypeId() == Interpreter::SCRIPT_ID) { + common::Script *script = reinterpret_cast(*j); + scripts.push_back(make_pair(const_cast(script->text), script->textlen)); + } } } } @@ -180,6 +190,18 @@ void Compiler::WriteImages(ostream &out) { } } +void Compiler::WriteScripts(ostream &out) { + for (vector >::const_iterator + i(scripts.begin()), end(scripts.end()); + i != end; ++i) { + Script s; + s.size = i->second; + Write(out, &s, sizeof(Script)); + addressMap.insert(make_pair(i->first, out.tellp())); + Write(out, i->first, s.size); + } +} + void Compiler::PrepareExport(Export &exp, const string &str) { const Interpreter::ParsedDefinition &dfn @@ -194,6 +216,7 @@ void Compiler::PrepareExternal( const Interpreter::PostponedDefinition &def) { ext.nameOffset = addressMap[def.identifier.c_str()]; ext.referenceOffset = addressMap[def.object] + (def.dest - def.object); + ext.typeId = def.type; ext.inlined = 0; if (def.inlined) ext.inlined |= 1; if (def.aggregate) ext.inlined |= 2; @@ -252,12 +275,27 @@ void Compiler::Relocate(iostream &out) { out.seekg(out.tellp()); delete[] buffer; } + Script script; + for (; out && out.tellg() < fileHeader.scriptsEnd;) { + out.read(reinterpret_cast(&script), sizeof(Script)); + buffer = new char[script.size]; + unsigned int pos = out.tellg(); + out.read(buffer, script.size); + RelocateScript(buffer, script.size); + out.seekp(pos); + out.write(buffer, script.size); + out.seekg(out.tellp()); + delete[] buffer; + } } void Compiler::RelocateArray(char *array, int size) { for (char *i = array, *end = array + size; i < end; i += sizeof(void *)) { char **dest = reinterpret_cast(i); + if (!*dest) { + continue; + } map::const_iterator entry(addressMap.find(*dest)); if (entry == addressMap.end()) { @@ -302,6 +340,38 @@ void Compiler::Relocate( } } +void Compiler::RelocateScript(char *text, unsigned int textlen) { + for (char *i = text, *end = text + textlen; i < end;) { + common::Script::Code *code = + reinterpret_cast(i); + if (code->type == common::Script::TYPE_ADDRESS && code->numParams > 0) { + if (code->reg1 == 7) { + char *addr = i + sizeof(common::Script::Code); + std::map::const_iterator + found(addressMap.find(*reinterpret_cast(addr))); + if (found == addressMap.end()) { + throw std::runtime_error("unable to relocate script code"); + } + *reinterpret_cast(addr) = found->second; + } + + if (code->numParams > 1 && code->reg2 == 7) { + char *addr = i + sizeof(common::Script::Code); + if (code->reg1 == 7) { + addr += sizeof(void *); + } + std::map::const_iterator + found(addressMap.find(*reinterpret_cast(addr))); + if (found == addressMap.end()) { + throw std::runtime_error("unable to relocate script code"); + } + *reinterpret_cast(addr) = found->second; + } + } + i += code->Size(); + } +} + void Compiler::Write(ostream &out, const void *data, int amount) { out.write(reinterpret_cast(data), amount);