3 #include "Interpreter.h"
4 #include "TypeDescription.h"
5 #include "../common/Script.h"
23 using std::runtime_error;
31 Compiler::Compiler(const Interpreter &intp)
33 int headerSize(sizeof(ObjectFileHeader));
35 fileHeader.exportsBegin = headerSize;
36 fileHeader.exportsEnd = fileHeader.exportsBegin
37 + (intp.ExportedIdentifiers().size() * sizeof(Export));
39 fileHeader.externalsBegin = fileHeader.exportsEnd;
40 fileHeader.externalsEnd = fileHeader.externalsBegin
41 + (intp.PostponedDefinitions().size() * sizeof(External));
43 fileHeader.objectsBegin = fileHeader.externalsEnd
44 + Remaining(fileHeader.externalsEnd, 16);
47 void Compiler::Write(iostream &out) {
51 fileHeader.objectsEnd = out.tellp();
53 fileHeader.arraysBegin = out.tellp();
55 fileHeader.arraysEnd = out.tellp();
56 fileHeader.scriptsBegin = out.tellp();
58 fileHeader.scriptsEnd = out.tellp();
63 out.seekg(fileHeader.objectsBegin);
66 fileHeader.imagesBegin = out.tellp();
68 fileHeader.imagesEnd = out.tellp();
73 void Compiler::ReserveHeader(ostream &out) {
74 Fill(out, fileHeader.objectsBegin);
77 void Compiler::WriteHeader(ostream &out) {
78 Write(out, &fileHeader, sizeof(ObjectFileHeader));
81 void Compiler::WriteOwnStrings(ostream &out) {
82 for (set<string>::const_iterator
83 i(intp.ExportedIdentifiers().begin()),
84 end(intp.ExportedIdentifiers().end());
87 object.typeId = Interpreter::STRING_ID;
88 object.size = i->size() + 1;
89 Write(out, &object, sizeof(Object));
90 addressMap.insert(make_pair(i->c_str(), out.tellp()));
91 Write(out, i->c_str(), object.size);
93 for(vector<Interpreter::PostponedDefinition>::const_iterator
94 i(intp.PostponedDefinitions().begin()),
95 end(intp.PostponedDefinitions().end());
98 object.typeId = Interpreter::STRING_ID;
99 object.size = i->identifier.size() + 1;
100 Write(out, &object, sizeof(Object));
101 addressMap.insert(make_pair(
102 i->identifier.c_str(), out.tellp()));
103 Write(out, i->identifier.c_str(), object.size);
105 for (std::map<std::string, SDL_Surface *>::const_iterator
106 i(intp.Images().begin()), end(intp.Images().end());
108 addressMap.insert(make_pair(
111 object.typeId = Interpreter::STRING_ID;
112 object.size = i->first.size() + 1;
113 Write(out, &object, sizeof(Object));
114 addressMap.insert(make_pair(
115 i->first.c_str(), out.tellp()));
116 Write(out, i->first.c_str(), object.size);
120 void Compiler::WriteExports(ostream &out) {
121 for (set<string>::const_iterator
122 i(intp.ExportedIdentifiers().begin()),
123 end(intp.ExportedIdentifiers().end());
126 PrepareExport(exp, *i);
127 Write(out, &exp, sizeof(Export));
131 void Compiler::WriteExternals(ostream &out) {
132 for(vector<Interpreter::PostponedDefinition>::const_iterator
133 i(intp.PostponedDefinitions().begin()),
134 end(intp.PostponedDefinitions().end());
137 PrepareExternal(ext, *i);
138 Write(out, &ext, sizeof(External));
142 void Compiler::WriteObjects(ostream &out) {
144 for (map<int, vector<void *> >::const_iterator
145 i(intp.Values().begin()), end(intp.Values().end());
147 const TypeDescription &td(TypeDescription::Get(i->first));
148 for (vector<void *>::const_iterator
149 j(i->second.begin()), jend(i->second.end());
152 PrepareObject(object, td, *j);
153 Write(out, &object, sizeof(Object));
154 addressMap.insert(make_pair(*j, out.tellp()));
155 Write(out, *j, object.size);
157 if (td.TypeId() == Interpreter::SCRIPT_ID) {
158 common::Script *script = reinterpret_cast<common::Script *>(*j);
159 scripts.push_back(make_pair(const_cast<char *>(script->text), script->textlen));
165 void Compiler::WriteArrays(ostream &out) {
167 for (vector<Interpreter::Array>::const_iterator
168 i(intp.Arrays().begin()), end(intp.Arrays().end());
171 array.typeId = i->typeId;
172 array.size = i->size;
174 Write(out, &array, sizeof(Array));
175 addressMap.insert(make_pair(i->data, out.tellp()));
176 Write(out, i->data, array.size);
180 void Compiler::WriteImages(ostream &out) {
181 for (std::map<unsigned int, void *>::const_iterator
182 i(images.begin()), end(images.end());
184 const string &path = intp.FindImage(
185 reinterpret_cast<SDL_Surface *>(i->second));
187 img.pathOffset = addressMap.at(path.c_str());
188 img.destOffset = i->first;
189 Write(out, &img, sizeof(Image));
193 void Compiler::WriteScripts(ostream &out) {
194 for (vector<pair<const char *, unsigned int> >::const_iterator
195 i(scripts.begin()), end(scripts.end());
199 Write(out, &s, sizeof(Script));
200 addressMap.insert(make_pair(i->first, out.tellp()));
201 Write(out, i->first, s.size);
206 void Compiler::PrepareExport(Export &exp, const string &str) {
207 const Interpreter::ParsedDefinition &dfn
208 = intp.GetDefinition(str);
209 exp.nameOffset = addressMap[str.c_str()];
210 exp.typeId = dfn.type;
211 exp.dataOffset = addressMap[intp.GetObject(dfn.type, str)];
214 void Compiler::PrepareExternal(
216 const Interpreter::PostponedDefinition &def) {
217 ext.nameOffset = addressMap[def.identifier.c_str()];
218 ext.referenceOffset = addressMap[def.object] + (def.dest - def.object);
219 ext.typeId = def.type;
221 if (def.inlined) ext.inlined |= 1;
222 if (def.aggregate) ext.inlined |= 2;
225 void Compiler::PrepareObject(
227 const TypeDescription &td,
229 object.typeId = td.TypeId();
230 switch (td.TypeId()) {
231 case Interpreter::STRING_ID:
232 object.size = strlen(
233 reinterpret_cast<char *>(data)) + 1;
236 object.size = td.Size();
241 void Compiler::Relocate(iostream &out) {
242 int bufferSize = TypeDescription::GetMaxSize();
243 char *buffer = new char[bufferSize];
244 for (;out && out.tellg() < fileHeader.objectsEnd;) {
246 out.read(reinterpret_cast<char *>(&object), sizeof(Object));
247 const TypeDescription &td = TypeDescription::Get(object.typeId);
248 unsigned int pos = out.tellg();
250 out.read(buffer, object.size);
251 Relocate(pos, buffer, td);
253 out.write(buffer, object.size);
254 out.seekg(out.tellp());
257 out.seekg(fileHeader.arraysBegin);
259 for (; out && out.tellg() < fileHeader.arraysEnd;) {
260 out.read(reinterpret_cast<char *>(&array), sizeof(Array));
261 buffer = new char[array.size];
262 unsigned int pos = out.tellg();
263 out.read(buffer, array.size);
265 RelocateArray(buffer, array.size);
267 const TypeDescription &td = TypeDescription::Get(array.typeId);
268 for (char *i = buffer, *end = buffer + array.size;
269 i < end; i += td.Size()) {
270 Relocate(pos + (i - buffer), i, td);
274 out.write(buffer, array.size);
275 out.seekg(out.tellp());
279 for (; out && out.tellg() < fileHeader.scriptsEnd;) {
280 out.read(reinterpret_cast<char *>(&script), sizeof(Script));
281 buffer = new char[script.size];
282 unsigned int pos = out.tellg();
283 out.read(buffer, script.size);
284 RelocateScript(buffer, script.size);
286 out.write(buffer, script.size);
287 out.seekg(out.tellp());
292 void Compiler::RelocateArray(char *array, int size) {
293 for (char *i = array, *end = array + size;
294 i < end; i += sizeof(void *)) {
295 char **dest = reinterpret_cast<char **>(i);
299 map<const void *, unsigned int>::const_iterator
300 entry(addressMap.find(*dest));
301 if (entry == addressMap.end()) {
302 throw runtime_error("unable to relocate array member");
304 unsigned int destOffset = entry->second;
305 *dest = reinterpret_cast<char *>(destOffset);
309 void Compiler::Relocate(
312 const TypeDescription &td) {
313 for (TypeDescription::FieldIterator
314 i(td.FieldsBegin()), end(td.FieldsEnd());
316 const FieldDescription &fd = i->second;
317 if (fd.IsAggregate() || fd.IsReferenced()) {
318 char **dest = reinterpret_cast<char **>(
319 object + fd.Offset());
323 if (fd.TypeId() == Interpreter::IMAGE_ID) {
324 images.insert(make_pair(
325 pos + fd.Offset(), *dest));
327 map<const void *, unsigned int>::const_iterator
328 entry(addressMap.find(*dest));
329 if (entry == addressMap.end()) {
330 throw runtime_error(string("unable to relocate field ")
331 + i->first + " in object of type " + td.TypeName());
333 unsigned int destOffset = entry->second;
334 *dest = reinterpret_cast<char *>(destOffset);
336 const TypeDescription &nestedType
337 = TypeDescription::Get(fd.TypeId());
338 Relocate(pos + fd.Offset(), object + fd.Offset(), nestedType);
343 void Compiler::RelocateScript(char *text, unsigned int textlen) {
344 for (char *i = text, *end = text + textlen; i < end;) {
345 common::Script::Code *code =
346 reinterpret_cast<common::Script::Code *>(i);
347 if (code->type == common::Script::TYPE_ADDRESS && code->numParams > 0) {
348 if (code->reg1 == 7) {
349 char *addr = i + sizeof(common::Script::Code);
350 std::map<const void *, unsigned int>::const_iterator
351 found(addressMap.find(*reinterpret_cast<void **>(addr)));
352 if (found == addressMap.end()) {
353 throw std::runtime_error("unable to relocate script code");
355 *reinterpret_cast<unsigned int *>(addr) = found->second;
358 if (code->numParams > 1 && code->reg2 == 7) {
359 char *addr = i + sizeof(common::Script::Code);
360 if (code->reg1 == 7) {
361 addr += sizeof(void *);
363 std::map<const void *, unsigned int>::const_iterator
364 found(addressMap.find(*reinterpret_cast<void **>(addr)));
365 if (found == addressMap.end()) {
366 throw std::runtime_error("unable to relocate script code");
368 *reinterpret_cast<unsigned int *>(addr) = found->second;
376 void Compiler::Write(ostream &out, const void *data, int amount) {
377 out.write(reinterpret_cast<const char *>(data), amount);
380 void Compiler::Pad(ostream &out, int to) {
381 Fill(out, Remaining(out.tellp(), to));
384 void Compiler::Fill(ostream &out, int count, char c) {
385 for (int remaining(count); remaining > 0; --remaining) {
390 int Compiler::Remaining(int value, int alignment) {
391 int have(value % alignment);
392 return (have > 0) ? (16 - have) : 0;