3 #include "Interpreter.h"
4 #include "TypeDescription.h"
21 using std::runtime_error;
29 Compiler::Compiler(const Interpreter &intp)
31 int headerSize(sizeof(ObjectFileHeader));
33 fileHeader.exportsBegin = headerSize;
34 fileHeader.exportsEnd = fileHeader.exportsBegin
35 + (intp.ExportedIdentifiers().size() * sizeof(Export));
37 fileHeader.externalsBegin = fileHeader.exportsEnd;
38 fileHeader.externalsEnd = fileHeader.externalsBegin
39 + (intp.PostponedDefinitions().size() * sizeof(External));
41 fileHeader.objectsBegin = fileHeader.externalsEnd
42 + Remaining(fileHeader.externalsEnd, 16);
45 void Compiler::Write(iostream &out) {
49 fileHeader.objectsEnd = out.tellp();
51 fileHeader.arraysBegin = out.tellp();
53 fileHeader.arraysEnd = out.tellp();
58 out.seekg(fileHeader.objectsBegin);
61 fileHeader.imagesBegin = out.tellp();
63 fileHeader.imagesEnd = out.tellp();
68 void Compiler::ReserveHeader(ostream &out) {
69 Fill(out, fileHeader.objectsBegin);
72 void Compiler::WriteHeader(ostream &out) {
73 Write(out, &fileHeader, sizeof(ObjectFileHeader));
76 void Compiler::WriteOwnStrings(ostream &out) {
77 for (set<string>::const_iterator
78 i(intp.ExportedIdentifiers().begin()),
79 end(intp.ExportedIdentifiers().end());
82 object.typeId = Interpreter::STRING_ID;
83 object.size = i->size() + 1;
84 Write(out, &object, sizeof(Object));
85 addressMap.insert(make_pair(i->c_str(), out.tellp()));
86 Write(out, i->c_str(), object.size);
88 for(vector<Interpreter::PostponedDefinition>::const_iterator
89 i(intp.PostponedDefinitions().begin()),
90 end(intp.PostponedDefinitions().end());
93 object.typeId = Interpreter::STRING_ID;
94 object.size = i->identifier.size() + 1;
95 Write(out, &object, sizeof(Object));
96 addressMap.insert(make_pair(
97 i->identifier.c_str(), out.tellp()));
98 Write(out, i->identifier.c_str(), object.size);
100 for (std::map<std::string, SDL_Surface *>::const_iterator
101 i(intp.Images().begin()), end(intp.Images().end());
103 addressMap.insert(make_pair(
106 object.typeId = Interpreter::STRING_ID;
107 object.size = i->first.size() + 1;
108 Write(out, &object, sizeof(Object));
109 addressMap.insert(make_pair(
110 i->first.c_str(), out.tellp()));
111 Write(out, i->first.c_str(), object.size);
115 void Compiler::WriteExports(ostream &out) {
116 for (set<string>::const_iterator
117 i(intp.ExportedIdentifiers().begin()),
118 end(intp.ExportedIdentifiers().end());
121 PrepareExport(exp, *i);
122 Write(out, &exp, sizeof(Export));
126 void Compiler::WriteExternals(ostream &out) {
127 for(vector<Interpreter::PostponedDefinition>::const_iterator
128 i(intp.PostponedDefinitions().begin()),
129 end(intp.PostponedDefinitions().end());
132 PrepareExternal(ext, *i);
133 Write(out, &ext, sizeof(External));
137 void Compiler::WriteObjects(ostream &out) {
139 for (map<int, vector<void *> >::const_iterator
140 i(intp.Values().begin()), end(intp.Values().end());
142 const TypeDescription &td(TypeDescription::Get(i->first));
143 for (vector<void *>::const_iterator
144 j(i->second.begin()), jend(i->second.end());
147 PrepareObject(object, td, *j);
148 Write(out, &object, sizeof(Object));
149 addressMap.insert(make_pair(*j, out.tellp()));
150 Write(out, *j, object.size);
155 void Compiler::WriteArrays(ostream &out) {
157 for (vector<Interpreter::Array>::const_iterator
158 i(intp.Arrays().begin()), end(intp.Arrays().end());
161 array.typeId = i->typeId;
162 array.size = i->size;
164 Write(out, &array, sizeof(Array));
165 addressMap.insert(make_pair(i->data, out.tellp()));
166 Write(out, i->data, array.size);
170 void Compiler::WriteImages(ostream &out) {
171 for (std::map<unsigned int, void *>::const_iterator
172 i(images.begin()), end(images.end());
174 const string &path = intp.FindImage(
175 reinterpret_cast<SDL_Surface *>(i->second));
177 img.pathOffset = addressMap.at(path.c_str());
178 img.destOffset = i->first;
179 Write(out, &img, sizeof(Image));
184 void Compiler::PrepareExport(Export &exp, const string &str) {
185 const Interpreter::ParsedDefinition &dfn
186 = intp.GetDefinition(str);
187 exp.nameOffset = addressMap[str.c_str()];
188 exp.typeId = dfn.type;
189 exp.dataOffset = addressMap[intp.GetObject(dfn.type, str)];
192 void Compiler::PrepareExternal(
194 const Interpreter::PostponedDefinition &def) {
195 ext.nameOffset = addressMap[def.identifier.c_str()];
196 ext.referenceOffset = addressMap[def.object] + (def.dest - def.object);
197 ext.typeId = def.type;
199 if (def.inlined) ext.inlined |= 1;
200 if (def.aggregate) ext.inlined |= 2;
203 void Compiler::PrepareObject(
205 const TypeDescription &td,
207 object.typeId = td.TypeId();
208 switch (td.TypeId()) {
209 case Interpreter::STRING_ID:
210 object.size = strlen(
211 reinterpret_cast<char *>(data)) + 1;
214 object.size = td.Size();
219 void Compiler::Relocate(iostream &out) {
220 int bufferSize = TypeDescription::GetMaxSize();
221 char *buffer = new char[bufferSize];
222 for (;out && out.tellg() < fileHeader.objectsEnd;) {
224 out.read(reinterpret_cast<char *>(&object), sizeof(Object));
225 const TypeDescription &td = TypeDescription::Get(object.typeId);
226 unsigned int pos = out.tellg();
228 out.read(buffer, object.size);
229 Relocate(pos, buffer, td);
231 out.write(buffer, object.size);
232 out.seekg(out.tellp());
235 out.seekg(fileHeader.arraysBegin);
237 for (; out && out.tellg() < fileHeader.arraysEnd;) {
238 out.read(reinterpret_cast<char *>(&array), sizeof(Array));
239 buffer = new char[array.size];
240 unsigned int pos = out.tellg();
241 out.read(buffer, array.size);
243 RelocateArray(buffer, array.size);
245 const TypeDescription &td = TypeDescription::Get(array.typeId);
246 for (char *i = buffer, *end = buffer + array.size;
247 i < end; i += td.Size()) {
248 Relocate(pos + (i - buffer), i, td);
252 out.write(buffer, array.size);
253 out.seekg(out.tellp());
258 void Compiler::RelocateArray(char *array, int size) {
259 for (char *i = array, *end = array + size;
260 i < end; i += sizeof(void *)) {
261 char **dest = reinterpret_cast<char **>(i);
265 map<const void *, unsigned int>::const_iterator
266 entry(addressMap.find(*dest));
267 if (entry == addressMap.end()) {
268 throw runtime_error("unable to relocate array member");
270 unsigned int destOffset = entry->second;
271 *dest = reinterpret_cast<char *>(destOffset);
275 void Compiler::Relocate(
278 const TypeDescription &td) {
279 for (TypeDescription::FieldIterator
280 i(td.FieldsBegin()), end(td.FieldsEnd());
282 const FieldDescription &fd = i->second;
283 if (fd.IsAggregate() || fd.IsReferenced()) {
284 char **dest = reinterpret_cast<char **>(
285 object + fd.Offset());
289 if (fd.TypeId() == Interpreter::IMAGE_ID) {
290 images.insert(make_pair(
291 pos + fd.Offset(), *dest));
293 map<const void *, unsigned int>::const_iterator
294 entry(addressMap.find(*dest));
295 if (entry == addressMap.end()) {
296 throw runtime_error(string("unable to relocate field ")
297 + i->first + " in object of type " + td.TypeName());
299 unsigned int destOffset = entry->second;
300 *dest = reinterpret_cast<char *>(destOffset);
302 const TypeDescription &nestedType
303 = TypeDescription::Get(fd.TypeId());
304 Relocate(pos + fd.Offset(), object + fd.Offset(), nestedType);
310 void Compiler::Write(ostream &out, const void *data, int amount) {
311 out.write(reinterpret_cast<const char *>(data), amount);
314 void Compiler::Pad(ostream &out, int to) {
315 Fill(out, Remaining(out.tellp(), to));
318 void Compiler::Fill(ostream &out, int count, char c) {
319 for (int remaining(count); remaining > 0; --remaining) {
324 int Compiler::Remaining(int value, int alignment) {
325 int have(value % alignment);
326 return (have > 0) ? (16 - have) : 0;