]> git.localhorst.tv Git - l2e.git/blob - src/loader/Compiler.cpp
added Compiler to turn an interpretation into an object file
[l2e.git] / src / loader / Compiler.cpp
1 /*
2  * Compiler.cpp
3  *
4  *  Created on: Sep 11, 2012
5  *      Author: holy
6  */
7
8 #include "Compiler.h"
9
10 #include "Interpreter.h"
11
12 #include <cstring>
13 #include <map>
14 #include <ostream>
15 #include <set>
16 #include <string>
17 #include <vector>
18
19 using std::map;
20 using std::ostream;
21 using std::set;
22 using std::string;
23 using std::vector;
24
25 namespace loader {
26
27 Compiler::Compiler(const Interpreter &intp)
28 : intp(intp)
29 , cursor(0) {
30         int headerSize(4 + (5 * sizeof(int)) + (intp.Values().size() * 2 * sizeof(int)));
31
32         exportsOffset = headerSize + Remaining(headerSize, 16);
33         int exportsSize(intp.ExportedIdentifiers().size() * sizeof(Export));
34
35         externalsOffset = exportsOffset + exportsSize + Remaining(exportsSize, 16);
36         int externalsSize(intp.PostponedDefinitions().size() * sizeof(External));
37
38         exportStringsOffset = externalsOffset + externalsSize + Remaining(externalsSize, 16);
39         int exportStringsSize(0);
40         for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
41                 exportStringsSize += i->size() + 1;
42         }
43
44         externalStringsOffset = exportStringsOffset + exportStringsSize + Remaining(exportStringsSize, 16);
45         int externalStringsSize(0);
46         for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
47                 externalStringsSize += std::strlen(i->identifier) + 1;
48         }
49
50         imagesOffset = externalStringsOffset + externalStringsSize + Remaining(externalStringsSize, 16);
51         int imagesSize(intp.Images().size() * sizeof(ImageProperties));
52         for (map<string, SDL_Surface *>::const_iterator i(intp.Images().begin()), end(intp.Images().end()); i != end; ++i) {
53                 imagesSize += i->second->w * i->second->h * i->second->format->BytesPerPixel;
54         }
55
56         objectsOffset = imagesOffset + imagesSize + Remaining(imagesSize, 16);
57         int objectsSize(0);
58         for (map<int, vector<void *> >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) {
59                 const TypeDescription &td(TypeDescription::Get(i->first));
60                 objectOffsets[i->first] = objectsOffset + objectsSize;
61                 objectsSize += td.Size() * i->second.size();
62                 objectsSize += Remaining(objectsSize, 16);
63         }
64 }
65
66 void Compiler::Write(ostream &out) {
67         WriteHeader(out);
68         Pad(out, 16);
69         WriteExports(out);
70         Pad(out, 16);
71         WriteExternals(out);
72         Pad(out, 16);
73         WriteExportStrings(out);
74         Pad(out, 16);
75         WriteExternalStrings(out);
76         Pad(out, 16);
77         WriteImages(out);
78         Pad(out, 16);
79         WriteObjects(out);
80 }
81
82
83 void Compiler::WriteHeader(ostream &out) {
84         Write(out, "L2O\n", 4);
85         Write(out, reinterpret_cast<const char *>(&exportsOffset), sizeof(int));
86         Write(out, reinterpret_cast<const char *>(&externalsOffset), sizeof(int));
87         Write(out, reinterpret_cast<const char *>(&externalStringsOffset), sizeof(int));
88         Write(out, reinterpret_cast<const char *>(&exportStringsOffset), sizeof(int));
89         Write(out, reinterpret_cast<const char *>(&imagesOffset), sizeof(int));
90         Write(out, reinterpret_cast<const char *>(&objectsOffset), sizeof(int));
91         for(map<int, vector<void *> >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) {
92                 Write(out, reinterpret_cast<const char *>(&i->first), sizeof(int));
93                 int typeOffset(TypeOffset(i->first));
94                 Write(out, reinterpret_cast<const char *>(&typeOffset), sizeof(int));
95         }
96 }
97
98 void Compiler::WriteExports(ostream &out) {
99         int nameOffset(externalStringsOffset);
100         for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
101                 const Interpreter::ParsedDefinition &dfn(intp.GetDefinition(*i));
102                 Export exp;
103                 exp.nameOffset = nameOffset;
104                 exp.typeId = dfn.type;
105                 exp.dataOffset = ObjectOffset(dfn.type, dfn.id);
106                 Write(out, reinterpret_cast<char *>(&exp), sizeof(Export));
107                 nameOffset += i->size() + 1;
108         }
109 }
110
111 void Compiler::WriteExternals(ostream &out) {
112         int nameOffset(exportStringsOffset);
113         for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
114                 External ext;
115                 ext.nameOffset = nameOffset;
116                 ext.referenceOffset = ReferenceOffset(i->type, i->id, i->offset);
117                 ext.inlined = i->inlined ? 1 : 0;
118                 Write(out, reinterpret_cast<char *>(&ext), sizeof(External));
119                 nameOffset += std::strlen(i->identifier) + 1;
120         }
121 }
122
123 void Compiler::WriteExportStrings(ostream &out) {
124         for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
125                 Write(out, i->c_str(), i->size() + 1);
126         }
127 }
128
129 void Compiler::WriteExternalStrings(ostream &out) {
130         for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
131                 Write(out, i->identifier, std::strlen(i->identifier) + 1);
132         }
133 }
134
135 void Compiler::WriteImages(ostream &out) {
136         for (map<string, SDL_Surface *>::const_iterator i(intp.Images().begin()), end(intp.Images().end()); i != end; ++i) {
137                 ImageProperties ip;
138                 ip.flags = i->second->flags;
139                 ip.width = i->second->w;
140                 ip.height = i->second->h;
141                 ip.depth = i->second->format->BitsPerPixel;
142                 ip.rmask = i->second->format->Rmask;
143                 ip.gmask = i->second->format->Gmask;
144                 ip.bmask = i->second->format->Bmask;
145                 ip.amask = i->second->format->Amask;
146                 Write(out, reinterpret_cast<char *>(&ip), sizeof(ImageProperties));
147                 SDL_LockSurface(i->second);
148                 Write(out, reinterpret_cast<char *>(i->second->pixels), ip.width * ip.height * i->second->format->BytesPerPixel);
149                 // TODO: store palette too?
150                 SDL_UnlockSurface(i->second);
151         }
152 }
153
154 void Compiler::WriteObjects(ostream &out) {
155         for (map<int, vector<void *> >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) {
156                 const TypeDescription &td(TypeDescription::Get(i->first));
157                 for (vector<void *>::const_iterator j(i->second.begin()), jend(i->second.end()); j != jend; ++j) {
158                         Write(out, reinterpret_cast<char *>(*j), td.Size());
159                 }
160                 Pad(out, 16);
161         }
162 }
163
164
165 void Compiler::Write(ostream &out, const char *data, int amount) {
166         out.write(data, amount);
167         cursor += amount;
168 }
169
170 void Compiler::Pad(ostream &out, int to) {
171         for (int remaining(Remaining(cursor, to)); remaining > 0; --remaining) {
172                 out.put(0);
173                 ++cursor;
174         }
175 }
176
177 int Compiler::Remaining(int value, int alignment) {
178         int have(value % alignment);
179         return (have > 0) ? (16 - have) : 0;
180 }
181
182
183 int Compiler::ReferenceOffset(int typeId, int objectId, std::ptrdiff_t fieldOffset) const {
184         return ObjectOffset(typeId, objectId) + fieldOffset;
185 }
186
187 int Compiler::ObjectOffset(int typeId, int objectId) const {
188         const TypeDescription &td(TypeDescription::Get(typeId));
189         return TypeOffset(typeId) + (td.Size() * objectId);
190 }
191
192 int Compiler::TypeOffset(int typeId) const {
193         return objectOffsets.at(typeId);
194 }
195
196 }