3 #include "Interpreter.h"
4 #include "TypeDescription.h"
21 using std::runtime_error;
29 Compiler::Compiler(const Interpreter &intp)
32 int headerSize(sizeof(ObjectFileHeader));
34 fileHeader.exportsBegin = headerSize;
35 fileHeader.exportsEnd = fileHeader.exportsBegin
36 + (intp.ExportedIdentifiers().size() * sizeof(Export));
38 fileHeader.externalsBegin = fileHeader.exportsEnd;
39 fileHeader.externalsEnd = fileHeader.externalsBegin
40 + (intp.PostponedDefinitions().size() * sizeof(External));
42 fileHeader.objectsBegin = fileHeader.externalsEnd
43 + Remaining(fileHeader.externalsEnd, 16);
46 void Compiler::Write(iostream &out) {
50 fileHeader.objectsEnd = cursor;
52 fileHeader.arraysBegin = cursor;
54 fileHeader.arraysEnd = cursor;
60 out.seekg(fileHeader.objectsBegin);
65 void Compiler::ReserveHeader(ostream &out) {
66 Fill(out, fileHeader.objectsBegin);
69 void Compiler::WriteHeader(ostream &out) {
70 Write(out, &fileHeader, sizeof(ObjectFileHeader));
73 void Compiler::WriteOwnStrings(ostream &out) {
74 for (set<string>::const_iterator
75 i(intp.ExportedIdentifiers().begin()),
76 end(intp.ExportedIdentifiers().end());
79 object.typeId = Interpreter::STRING_ID;
80 object.size = i->size() + 1;
81 Write(out, &object, sizeof(Object));
82 addressMap.insert(make_pair(i->c_str(), cursor));
83 Write(out, i->c_str(), object.size);
85 for(vector<Interpreter::PostponedDefinition>::const_iterator
86 i(intp.PostponedDefinitions().begin()),
87 end(intp.PostponedDefinitions().end());
89 addressMap.insert(make_pair(
90 i->identifier.c_str(), cursor));
92 object.typeId = Interpreter::STRING_ID;
93 object.size = i->identifier.size() + 1;
94 Write(out, &object, sizeof(Object));
95 Write(out, i->identifier.c_str(), object.size);
99 void Compiler::WriteExports(ostream &out) {
100 for (set<string>::const_iterator
101 i(intp.ExportedIdentifiers().begin()),
102 end(intp.ExportedIdentifiers().end());
105 PrepareExport(exp, *i);
106 Write(out, &exp, sizeof(Export));
110 void Compiler::WriteExternals(ostream &out) {
111 for(vector<Interpreter::PostponedDefinition>::const_iterator
112 i(intp.PostponedDefinitions().begin()),
113 end(intp.PostponedDefinitions().end());
116 PrepareExternal(ext, *i);
117 Write(out, &ext, sizeof(External));
121 void Compiler::WriteObjects(ostream &out) {
123 for (map<int, vector<void *> >::const_iterator
124 i(intp.Values().begin()), end(intp.Values().end());
126 const TypeDescription &td(TypeDescription::Get(i->first));
127 for (vector<void *>::const_iterator
128 j(i->second.begin()), jend(i->second.end());
131 PrepareObject(object, td, *j);
132 Write(out, &object, sizeof(Object));
133 Write(out, *j, object.size);
138 void Compiler::WriteArrays(ostream &out) {
140 for (vector<Interpreter::Array>::const_iterator
141 i(intp.Arrays().begin()), end(intp.Arrays().end());
144 array.typeId = i->typeId;
145 array.size = i->size;
147 Write(out, &array, sizeof(Array));
148 addressMap.insert(make_pair(i->data, cursor));
149 Write(out, i->data, array.size);
154 void Compiler::PrepareExport(Export &exp, const string &str) {
155 const Interpreter::ParsedDefinition &dfn
156 = intp.GetDefinition(str);
157 exp.nameOffset = addressMap[str.c_str()];
158 exp.typeId = dfn.type;
159 exp.dataOffset = addressMap[intp.GetObject(dfn.type, str)];
162 void Compiler::PrepareExternal(
164 const Interpreter::PostponedDefinition &def) {
165 ext.nameOffset = addressMap[def.identifier.c_str()];
166 ext.referenceOffset = addressMap[def.object] + (def.dest - def.object);
168 if (def.inlined) ext.inlined |= 1;
169 if (def.aggregate) ext.inlined |= 2;
172 void Compiler::PrepareObject(
174 const TypeDescription &td,
176 addressMap.insert(make_pair(data, cursor + sizeof(Object)));
177 object.typeId = td.TypeId();
178 switch (td.TypeId()) {
179 case Interpreter::STRING_ID:
180 object.size = strlen(
181 reinterpret_cast<char *>(data)) + 1;
184 object.size = td.Size();
189 void Compiler::Relocate(iostream &out) {
190 int bufferSize = TypeDescription::GetMaxSize();
191 char *buffer = new char[bufferSize];
192 for (;out && out.tellg() < fileHeader.objectsEnd;) {
195 out.read(reinterpret_cast<char *>(&object), sizeof(Object));
196 const TypeDescription &td = TypeDescription::Get(object.typeId);
197 if (!td.NeedsLinking()) {
198 out.seekg(object.size, iostream::cur);
201 unsigned int pos = out.tellg();
203 out.read(buffer, object.size);
204 Relocate(buffer, td);
206 out.write(buffer, object.size);
207 out.seekg(out.tellp());
210 out.seekg(fileHeader.arraysBegin);
212 for (; out && out.tellg() < fileHeader.arraysEnd;) {
213 out.read(reinterpret_cast<char *>(&array), sizeof(Array));
215 buffer = new char[array.size];
216 unsigned int pos = out.tellg();
218 out.read(buffer, array.size);
219 RelocateArray(buffer, array.size);
221 out.write(buffer, array.size);
222 out.seekg(out.tellp());
225 const TypeDescription &td = TypeDescription::Get(array.typeId);
226 for (char *i = array.Data(), *end = array.Data() + array.size;
227 i < end; i += td.Size()) {
234 void Compiler::RelocateArray(char *array, int size) {
235 for (char *i = array, *end = array + size;
236 i < end; i += sizeof(void *)) {
237 char **dest = reinterpret_cast<char **>(i);
238 map<const void *, unsigned int>::const_iterator
239 entry(addressMap.find(*dest));
240 if (entry == addressMap.end()) {
241 throw runtime_error("unable to relocate array member");
243 unsigned int destOffset = entry->second;
244 *dest = reinterpret_cast<char *>(destOffset);
248 void Compiler::Relocate(char *object, const TypeDescription &td) {
249 for (TypeDescription::FieldIterator
250 i(td.FieldsBegin()), end(td.FieldsEnd());
252 const FieldDescription &fd = i->second;
253 if (!fd.IsAggregate() && !fd.IsReferenced()) {
256 char **dest = reinterpret_cast<char **>(
257 object + fd.Offset());
261 map<const void *, unsigned int>::const_iterator
262 entry(addressMap.find(*dest));
263 if (entry == addressMap.end()) {
264 throw runtime_error(string("unable to relocate field ")
265 + i->first + " in object of type " + td.TypeName());
267 unsigned int destOffset = entry->second;
268 *dest = reinterpret_cast<char *>(destOffset);
273 void Compiler::Write(ostream &out, const void *data, int amount) {
274 out.write(reinterpret_cast<const char *>(data), amount);
278 void Compiler::Pad(ostream &out, int to) {
279 Fill(out, Remaining(cursor, to));
282 void Compiler::Fill(ostream &out, int count, char c) {
283 for (int remaining(count); remaining > 0; --remaining) {
289 int Compiler::Remaining(int value, int alignment) {
290 int have(value % alignment);
291 return (have > 0) ? (16 - have) : 0;