From 587a9fc38235475f1c25424bee3e3aeb892a25e2 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Thu, 13 Sep 2012 22:35:18 +0200 Subject: [PATCH] added Compiler to turn an interpretation into an object file --- src/loader/Compiler.cpp | 196 ++++++++++++++++++++++++++++++++++++++++ src/loader/Compiler.h | 90 ++++++++++++++++++ 2 files changed, 286 insertions(+) create mode 100644 src/loader/Compiler.cpp create mode 100644 src/loader/Compiler.h diff --git a/src/loader/Compiler.cpp b/src/loader/Compiler.cpp new file mode 100644 index 0000000..59bebfb --- /dev/null +++ b/src/loader/Compiler.cpp @@ -0,0 +1,196 @@ +/* + * Compiler.cpp + * + * Created on: Sep 11, 2012 + * Author: holy + */ + +#include "Compiler.h" + +#include "Interpreter.h" + +#include +#include +#include +#include +#include +#include + +using std::map; +using std::ostream; +using std::set; +using std::string; +using std::vector; + +namespace loader { + +Compiler::Compiler(const Interpreter &intp) +: intp(intp) +, cursor(0) { + int headerSize(4 + (5 * sizeof(int)) + (intp.Values().size() * 2 * sizeof(int))); + + exportsOffset = headerSize + Remaining(headerSize, 16); + int exportsSize(intp.ExportedIdentifiers().size() * sizeof(Export)); + + externalsOffset = exportsOffset + exportsSize + Remaining(exportsSize, 16); + int externalsSize(intp.PostponedDefinitions().size() * sizeof(External)); + + exportStringsOffset = externalsOffset + externalsSize + Remaining(externalsSize, 16); + int exportStringsSize(0); + for (set::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) { + exportStringsSize += i->size() + 1; + } + + externalStringsOffset = exportStringsOffset + exportStringsSize + Remaining(exportStringsSize, 16); + int externalStringsSize(0); + for(vector::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) { + externalStringsSize += std::strlen(i->identifier) + 1; + } + + imagesOffset = externalStringsOffset + externalStringsSize + Remaining(externalStringsSize, 16); + int imagesSize(intp.Images().size() * sizeof(ImageProperties)); + for (map::const_iterator i(intp.Images().begin()), end(intp.Images().end()); i != end; ++i) { + imagesSize += i->second->w * i->second->h * i->second->format->BytesPerPixel; + } + + objectsOffset = imagesOffset + imagesSize + Remaining(imagesSize, 16); + int objectsSize(0); + for (map >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) { + const TypeDescription &td(TypeDescription::Get(i->first)); + objectOffsets[i->first] = objectsOffset + objectsSize; + objectsSize += td.Size() * i->second.size(); + objectsSize += Remaining(objectsSize, 16); + } +} + +void Compiler::Write(ostream &out) { + WriteHeader(out); + Pad(out, 16); + WriteExports(out); + Pad(out, 16); + WriteExternals(out); + Pad(out, 16); + WriteExportStrings(out); + Pad(out, 16); + WriteExternalStrings(out); + Pad(out, 16); + WriteImages(out); + Pad(out, 16); + WriteObjects(out); +} + + +void Compiler::WriteHeader(ostream &out) { + Write(out, "L2O\n", 4); + Write(out, reinterpret_cast(&exportsOffset), sizeof(int)); + Write(out, reinterpret_cast(&externalsOffset), sizeof(int)); + Write(out, reinterpret_cast(&externalStringsOffset), sizeof(int)); + Write(out, reinterpret_cast(&exportStringsOffset), sizeof(int)); + Write(out, reinterpret_cast(&imagesOffset), sizeof(int)); + Write(out, reinterpret_cast(&objectsOffset), sizeof(int)); + for(map >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) { + Write(out, reinterpret_cast(&i->first), sizeof(int)); + int typeOffset(TypeOffset(i->first)); + Write(out, reinterpret_cast(&typeOffset), sizeof(int)); + } +} + +void Compiler::WriteExports(ostream &out) { + int nameOffset(externalStringsOffset); + for (set::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) { + const Interpreter::ParsedDefinition &dfn(intp.GetDefinition(*i)); + Export exp; + exp.nameOffset = nameOffset; + exp.typeId = dfn.type; + exp.dataOffset = ObjectOffset(dfn.type, dfn.id); + Write(out, reinterpret_cast(&exp), sizeof(Export)); + nameOffset += i->size() + 1; + } +} + +void Compiler::WriteExternals(ostream &out) { + int nameOffset(exportStringsOffset); + for(vector::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) { + External ext; + ext.nameOffset = nameOffset; + ext.referenceOffset = ReferenceOffset(i->type, i->id, i->offset); + ext.inlined = i->inlined ? 1 : 0; + Write(out, reinterpret_cast(&ext), sizeof(External)); + nameOffset += std::strlen(i->identifier) + 1; + } +} + +void Compiler::WriteExportStrings(ostream &out) { + for (set::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) { + Write(out, i->c_str(), i->size() + 1); + } +} + +void Compiler::WriteExternalStrings(ostream &out) { + for(vector::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) { + Write(out, i->identifier, std::strlen(i->identifier) + 1); + } +} + +void Compiler::WriteImages(ostream &out) { + for (map::const_iterator i(intp.Images().begin()), end(intp.Images().end()); i != end; ++i) { + ImageProperties ip; + ip.flags = i->second->flags; + ip.width = i->second->w; + ip.height = i->second->h; + ip.depth = i->second->format->BitsPerPixel; + ip.rmask = i->second->format->Rmask; + ip.gmask = i->second->format->Gmask; + ip.bmask = i->second->format->Bmask; + ip.amask = i->second->format->Amask; + Write(out, reinterpret_cast(&ip), sizeof(ImageProperties)); + SDL_LockSurface(i->second); + Write(out, reinterpret_cast(i->second->pixels), ip.width * ip.height * i->second->format->BytesPerPixel); + // TODO: store palette too? + SDL_UnlockSurface(i->second); + } +} + +void Compiler::WriteObjects(ostream &out) { + for (map >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) { + const TypeDescription &td(TypeDescription::Get(i->first)); + for (vector::const_iterator j(i->second.begin()), jend(i->second.end()); j != jend; ++j) { + Write(out, reinterpret_cast(*j), td.Size()); + } + Pad(out, 16); + } +} + + +void Compiler::Write(ostream &out, const char *data, int amount) { + out.write(data, amount); + cursor += amount; +} + +void Compiler::Pad(ostream &out, int to) { + for (int remaining(Remaining(cursor, to)); remaining > 0; --remaining) { + out.put(0); + ++cursor; + } +} + +int Compiler::Remaining(int value, int alignment) { + int have(value % alignment); + return (have > 0) ? (16 - have) : 0; +} + + +int Compiler::ReferenceOffset(int typeId, int objectId, std::ptrdiff_t fieldOffset) const { + return ObjectOffset(typeId, objectId) + fieldOffset; +} + +int Compiler::ObjectOffset(int typeId, int objectId) const { + const TypeDescription &td(TypeDescription::Get(typeId)); + return TypeOffset(typeId) + (td.Size() * objectId); +} + +int Compiler::TypeOffset(int typeId) const { + return objectOffsets.at(typeId); +} + +} diff --git a/src/loader/Compiler.h b/src/loader/Compiler.h new file mode 100644 index 0000000..d2f0361 --- /dev/null +++ b/src/loader/Compiler.h @@ -0,0 +1,90 @@ +/* + * Compiler.h + * + * Created on: Sep 11, 2012 + * Author: holy + */ + +#ifndef LOADER_COMPILER_H_ +#define LOADER_COMPILER_H_ + +#include +#include +#include +#include + +namespace loader { + +class Interpreter; + +class Compiler { + +public: + explicit Compiler(const Interpreter &intp); + ~Compiler() { } +private: + Compiler(const Compiler &); + Compiler &operator =(const Compiler &); + +public: + void Write(std::ostream &); + + struct Export { + int nameOffset; + int typeId; + int dataOffset; + }; + + struct External { + int nameOffset; + int referenceOffset; + int inlined; + }; + + struct ImageProperties { + Uint32 flags; + int width; + int height; + int depth; + Uint32 rmask; + Uint32 gmask; + Uint32 bmask; + Uint32 amask; + }; + +private: + void WriteHeader(std::ostream &); + void WriteExports(std::ostream &); + void WriteExternals(std::ostream &); + void WriteExportStrings(std::ostream &); + void WriteExternalStrings(std::ostream &); + void WriteImages(std::ostream &); + void WriteObjects(std::ostream &); + + void Write(std::ostream &, const char *data, int amount); + void Pad(std::ostream &, int to); + static int Remaining(int value, int alignment); + + int ReferenceOffset(int typeId, int objectId, std::ptrdiff_t fieldOffset) const; + int ObjectOffset(int typeId, int objectId) const; + int TypeOffset(int typeId) const; + +private: + const Interpreter &intp; + + int cursor; + + int exportsOffset; + int externalsOffset; + int externalStringsOffset; + int exportStringsOffset; + int imagesOffset; + int objectsOffset; + + std::map objectOffsets; + +}; + +} + +#endif /* LOADER_COMPILER_H_ */ -- 2.39.2