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);
198 if (def.inlined) ext.inlined |= 1;
199 if (def.aggregate) ext.inlined |= 2;
202 void Compiler::PrepareObject(
204 const TypeDescription &td,
206 object.typeId = td.TypeId();
207 switch (td.TypeId()) {
208 case Interpreter::STRING_ID:
209 object.size = strlen(
210 reinterpret_cast<char *>(data)) + 1;
213 object.size = td.Size();
218 void Compiler::Relocate(iostream &out) {
219 int bufferSize = TypeDescription::GetMaxSize();
220 char *buffer = new char[bufferSize];
221 for (;out && out.tellg() < fileHeader.objectsEnd;) {
223 out.read(reinterpret_cast<char *>(&object), sizeof(Object));
224 const TypeDescription &td = TypeDescription::Get(object.typeId);
225 unsigned int pos = out.tellg();
227 out.read(buffer, object.size);
228 Relocate(pos, buffer, td);
230 out.write(buffer, object.size);
231 out.seekg(out.tellp());
234 out.seekg(fileHeader.arraysBegin);
236 for (; out && out.tellg() < fileHeader.arraysEnd;) {
237 out.read(reinterpret_cast<char *>(&array), sizeof(Array));
238 buffer = new char[array.size];
239 unsigned int pos = out.tellg();
240 out.read(buffer, array.size);
242 RelocateArray(buffer, array.size);
244 const TypeDescription &td = TypeDescription::Get(array.typeId);
245 for (char *i = buffer, *end = buffer + array.size;
246 i < end; i += td.Size()) {
247 Relocate(pos + (i - buffer), i, td);
251 out.write(buffer, array.size);
252 out.seekg(out.tellp());
257 void Compiler::RelocateArray(char *array, int size) {
258 for (char *i = array, *end = array + size;
259 i < end; i += sizeof(void *)) {
260 char **dest = reinterpret_cast<char **>(i);
261 map<const void *, unsigned int>::const_iterator
262 entry(addressMap.find(*dest));
263 if (entry == addressMap.end()) {
264 throw runtime_error("unable to relocate array member");
266 unsigned int destOffset = entry->second;
267 *dest = reinterpret_cast<char *>(destOffset);
271 void Compiler::Relocate(
274 const TypeDescription &td) {
275 for (TypeDescription::FieldIterator
276 i(td.FieldsBegin()), end(td.FieldsEnd());
278 const FieldDescription &fd = i->second;
279 if (fd.IsAggregate() || fd.IsReferenced()) {
280 char **dest = reinterpret_cast<char **>(
281 object + fd.Offset());
285 if (fd.TypeId() == Interpreter::IMAGE_ID) {
286 images.insert(make_pair(
287 pos + fd.Offset(), *dest));
289 map<const void *, unsigned int>::const_iterator
290 entry(addressMap.find(*dest));
291 if (entry == addressMap.end()) {
292 throw runtime_error(string("unable to relocate field ")
293 + i->first + " in object of type " + td.TypeName());
295 unsigned int destOffset = entry->second;
296 *dest = reinterpret_cast<char *>(destOffset);
298 const TypeDescription &nestedType
299 = TypeDescription::Get(fd.TypeId());
300 Relocate(pos + fd.Offset(), object + fd.Offset(), nestedType);
306 void Compiler::Write(ostream &out, const void *data, int amount) {
307 out.write(reinterpret_cast<const char *>(data), amount);
310 void Compiler::Pad(ostream &out, int to) {
311 Fill(out, Remaining(out.tellp(), to));
314 void Compiler::Fill(ostream &out, int count, char c) {
315 for (int remaining(count); remaining > 0; --remaining) {
320 int Compiler::Remaining(int value, int alignment) {
321 int have(value % alignment);
322 return (have > 0) ? (16 - have) : 0;