X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Floader%2FCompiler.cpp;h=13f3dfc24ba0b1416ef87bfdd2976b9f9c8003dd;hb=HEAD;hp=b583aabb298a46017fb87d23d1772e1e79fed12e;hpb=7b3710c47f24e64e0d01378a4564730bcb2f6ef2;p=l2e.git diff --git a/src/loader/Compiler.cpp b/src/loader/Compiler.cpp index b583aab..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; @@ -27,8 +29,7 @@ using std::vector; namespace loader { Compiler::Compiler(const Interpreter &intp) -: intp(intp) -, cursor(0) { +: intp(intp) { int headerSize(sizeof(ObjectFileHeader)); fileHeader.exportsBegin = headerSize; @@ -47,19 +48,26 @@ void Compiler::Write(iostream &out) { ReserveHeader(out); WriteObjects(out); WriteOwnStrings(out); - fileHeader.objectsEnd = cursor; + fileHeader.objectsEnd = out.tellp(); Pad(out, 16); - fileHeader.arraysBegin = cursor; + fileHeader.arraysBegin = out.tellp(); WriteArrays(out); - fileHeader.arraysEnd = cursor; + fileHeader.arraysEnd = out.tellp(); + fileHeader.scriptsBegin = out.tellp(); + WriteScripts(out); + fileHeader.scriptsEnd = out.tellp(); out.seekp(0); - cursor = 0; WriteHeader(out); WriteExports(out); WriteExternals(out); out.seekg(fileHeader.objectsBegin); out.clear(); Relocate(out); + fileHeader.imagesBegin = out.tellp(); + WriteImages(out); + fileHeader.imagesEnd = out.tellp(); + out.seekp(0); + WriteHeader(out); } void Compiler::ReserveHeader(ostream &out) { @@ -79,21 +87,34 @@ void Compiler::WriteOwnStrings(ostream &out) { object.typeId = Interpreter::STRING_ID; object.size = i->size() + 1; Write(out, &object, sizeof(Object)); - addressMap.insert(make_pair(i->c_str(), cursor)); + addressMap.insert(make_pair(i->c_str(), out.tellp())); Write(out, i->c_str(), object.size); } for(vector::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) { - addressMap.insert(make_pair( - i->identifier.c_str(), cursor)); Object object; object.typeId = Interpreter::STRING_ID; object.size = i->identifier.size() + 1; Write(out, &object, sizeof(Object)); + addressMap.insert(make_pair( + i->identifier.c_str(), out.tellp())); Write(out, i->identifier.c_str(), object.size); } + for (std::map::const_iterator + i(intp.Images().begin()), end(intp.Images().end()); + i != end; ++i) { + addressMap.insert(make_pair( + i->second, 0)); + Object object; + object.typeId = Interpreter::STRING_ID; + object.size = i->first.size() + 1; + Write(out, &object, sizeof(Object)); + addressMap.insert(make_pair( + i->first.c_str(), out.tellp())); + Write(out, i->first.c_str(), object.size); + } } void Compiler::WriteExports(ostream &out) { @@ -130,7 +151,13 @@ void Compiler::WriteObjects(ostream &out) { Object object; PrepareObject(object, td, *j); 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)); + } } } } @@ -145,11 +172,36 @@ void Compiler::WriteArrays(ostream &out) { array.size = i->size; array.ref = i->ref; Write(out, &array, sizeof(Array)); - addressMap.insert(make_pair(i->data, cursor)); + addressMap.insert(make_pair(i->data, out.tellp())); Write(out, i->data, array.size); } } +void Compiler::WriteImages(ostream &out) { + for (std::map::const_iterator + i(images.begin()), end(images.end()); + i != end; ++i) { + const string &path = intp.FindImage( + reinterpret_cast(i->second)); + Image img; + img.pathOffset = addressMap.at(path.c_str()); + img.destOffset = i->first; + Write(out, &img, sizeof(Image)); + } +} + +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 @@ -164,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; @@ -173,7 +226,6 @@ void Compiler::PrepareObject( Object &object, const TypeDescription &td, void *data) { - addressMap.insert(make_pair(data, cursor + sizeof(Object))); object.typeId = td.TypeId(); switch (td.TypeId()) { case Interpreter::STRING_ID: @@ -190,18 +242,13 @@ void Compiler::Relocate(iostream &out) { int bufferSize = TypeDescription::GetMaxSize(); char *buffer = new char[bufferSize]; for (;out && out.tellg() < fileHeader.objectsEnd;) { - // 20785 Object object; out.read(reinterpret_cast(&object), sizeof(Object)); const TypeDescription &td = TypeDescription::Get(object.typeId); - if (!td.NeedsLinking()) { - out.seekg(object.size, iostream::cur); - continue; - } unsigned int pos = out.tellg(); - out.seekg(pos); + out.read(buffer, object.size); - Relocate(buffer, td); + Relocate(pos, buffer, td); out.seekp(pos); out.write(buffer, object.size); out.seekg(out.tellp()); @@ -211,23 +258,34 @@ void Compiler::Relocate(iostream &out) { Array array; for (; out && out.tellg() < fileHeader.arraysEnd;) { out.read(reinterpret_cast(&array), sizeof(Array)); + buffer = new char[array.size]; + unsigned int pos = out.tellg(); + out.read(buffer, array.size); if (array.ref) { - buffer = new char[array.size]; - unsigned int pos = out.tellg(); - out.seekg(pos); - out.read(buffer, array.size); RelocateArray(buffer, array.size); - out.seekp(pos); - out.write(buffer, array.size); - out.seekg(out.tellp()); - delete[] buffer; } else { const TypeDescription &td = TypeDescription::Get(array.typeId); - for (char *i = array.Data(), *end = array.Data() + array.size; + for (char *i = buffer, *end = buffer + array.size; i < end; i += td.Size()) { - Relocate(i, td); + Relocate(pos + (i - buffer), i, td); } } + out.seekp(pos); + out.write(buffer, array.size); + 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; } } @@ -235,6 +293,9 @@ 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()) { @@ -245,44 +306,84 @@ void Compiler::RelocateArray(char *array, int size) { } } -void Compiler::Relocate(char *object, const TypeDescription &td) { +void Compiler::Relocate( + unsigned int pos, + char *object, + const TypeDescription &td) { for (TypeDescription::FieldIterator i(td.FieldsBegin()), end(td.FieldsEnd()); i != end; ++i) { const FieldDescription &fd = i->second; - if (!fd.IsAggregate() && !fd.IsReferenced()) { - continue; - } - char **dest = reinterpret_cast( - object + fd.Offset()); - if (!(*dest)) { - continue; + if (fd.IsAggregate() || fd.IsReferenced()) { + char **dest = reinterpret_cast( + object + fd.Offset()); + if (!(*dest)) { + continue; + } + if (fd.TypeId() == Interpreter::IMAGE_ID) { + images.insert(make_pair( + pos + fd.Offset(), *dest)); + } + map::const_iterator + entry(addressMap.find(*dest)); + if (entry == addressMap.end()) { + throw runtime_error(string("unable to relocate field ") + + i->first + " in object of type " + td.TypeName()); + } + unsigned int destOffset = entry->second; + *dest = reinterpret_cast(destOffset); + } else { + const TypeDescription &nestedType + = TypeDescription::Get(fd.TypeId()); + Relocate(pos + fd.Offset(), object + fd.Offset(), nestedType); } - map::const_iterator - entry(addressMap.find(*dest)); - if (entry == addressMap.end()) { - throw runtime_error(string("unable to relocate field ") - + i->first + " in object of type " + td.TypeName()); + } +} + +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; + } } - unsigned int destOffset = entry->second; - *dest = reinterpret_cast(destOffset); + i += code->Size(); } } void Compiler::Write(ostream &out, const void *data, int amount) { out.write(reinterpret_cast(data), amount); - cursor += amount; } void Compiler::Pad(ostream &out, int to) { - Fill(out, Remaining(cursor, to)); + Fill(out, Remaining(out.tellp(), to)); } void Compiler::Fill(ostream &out, int count, char c) { for (int remaining(count); remaining > 0; --remaining) { out.put(c); - ++cursor; } }