X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=src%2Floader%2FCompiler.cpp;h=b2d23be9c5cb984ee969ae3402706fbe02cf6289;hb=8ef435410d1f8aff339e4afef87a5757e77eba45;hp=bb96b28728ecf82e1abb03fbb195722eb02dec83;hpb=45bb35881a10720ae26701ddf075f756419cd627;p=l2e.git diff --git a/src/loader/Compiler.cpp b/src/loader/Compiler.cpp index bb96b28..b2d23be 100644 --- a/src/loader/Compiler.cpp +++ b/src/loader/Compiler.cpp @@ -27,8 +27,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 +46,23 @@ 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(); 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 +82,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,6 +146,7 @@ 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); } } @@ -141,14 +158,28 @@ void Compiler::WriteArrays(ostream &out) { i(intp.Arrays().begin()), end(intp.Arrays().end()); i != end; ++i) { Array array; + array.typeId = i->typeId; 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::PrepareExport(Export &exp, const string &str) { const Interpreter::ParsedDefinition &dfn @@ -163,6 +194,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; @@ -172,7 +204,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: @@ -189,18 +220,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()); @@ -210,15 +236,18 @@ void Compiler::Relocate(iostream &out) { Array array; for (; out && out.tellg() < fileHeader.arraysEnd;) { out.read(reinterpret_cast(&array), sizeof(Array)); - if (!array.ref) { - out.seekg(array.size); - continue; - } buffer = new char[array.size]; unsigned int pos = out.tellg(); - out.seekg(pos); out.read(buffer, array.size); - RelocateArray(buffer, array.size); + if (array.ref) { + RelocateArray(buffer, array.size); + } else { + const TypeDescription &td = TypeDescription::Get(array.typeId); + for (char *i = buffer, *end = buffer + array.size; + i < end; i += td.Size()) { + Relocate(pos + (i - buffer), i, td); + } + } out.seekp(pos); out.write(buffer, array.size); out.seekg(out.tellp()); @@ -230,6 +259,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()) { @@ -240,44 +272,52 @@ 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; + 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); } - char **dest = reinterpret_cast( - object + fd.Offset()); - if (!(*dest)) { - continue; - } - 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); } } 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; } }