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());
78 addressMap.insert(make_pair(i->c_str(), cursor));
80 object.typeId = Interpreter::STRING_ID;
81 object.size = i->size() + 1;
82 Write(out, &object, sizeof(Object));
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.size = i->size;
146 Write(out, &array, sizeof(Array));
147 addressMap.insert(make_pair(i->data, cursor));
148 Write(out, i->data, array.size);
153 void Compiler::PrepareExport(Export &exp, const string &str) {
154 const Interpreter::ParsedDefinition &dfn
155 = intp.GetDefinition(str);
156 exp.nameOffset = addressMap[str.c_str()];
157 exp.typeId = dfn.type;
158 exp.dataOffset = addressMap[intp.GetObject(dfn.type, str)];
161 void Compiler::PrepareExternal(
163 const Interpreter::PostponedDefinition &def) {
164 ext.nameOffset = addressMap[def.identifier.c_str()];
165 ext.referenceOffset = addressMap[def.object] + (def.dest - def.object);
167 if (def.inlined) ext.inlined |= 1;
168 if (def.aggregate) ext.inlined |= 2;
171 void Compiler::PrepareObject(
173 const TypeDescription &td,
175 addressMap.insert(make_pair(data, cursor + sizeof(Object)));
176 object.typeId = td.TypeId();
177 switch (td.TypeId()) {
178 case Interpreter::STRING_ID:
179 object.size = strlen(
180 reinterpret_cast<char *>(data)) + 1;
183 object.size = td.Size();
188 void Compiler::Relocate(iostream &out) {
189 int bufferSize = TypeDescription::GetMaxSize();
190 char *buffer = new char[bufferSize];
191 for (;out && out.tellg() < fileHeader.objectsEnd;) {
194 out.read(reinterpret_cast<char *>(&object), sizeof(Object));
195 const TypeDescription &td = TypeDescription::Get(object.typeId);
196 if (td.NeedsLinking()) {
197 out.seekg(object.size, iostream::cur);
200 unsigned int pos = out.tellg();
202 out.read(buffer, object.size);
203 Relocate(buffer, td);
205 out.write(buffer, object.size);
206 out.seekg(out.tellp());
209 out.seekg(fileHeader.arraysBegin);
211 for (; out && out.tellg() < fileHeader.arraysEnd;) {
212 out.read(reinterpret_cast<char *>(&array), sizeof(Array));
214 out.seekg(array.size);
217 buffer = new char[array.size];
218 unsigned int pos = out.tellg();
220 out.read(buffer, array.size);
221 RelocateArray(buffer, array.size);
223 out.write(buffer, array.size);
224 out.seekg(out.tellp());
229 void Compiler::RelocateArray(char *array, int size) {
230 for (char *i = array, *end = array + size;
231 i < end; i += sizeof(void *)) {
232 char **dest = reinterpret_cast<char **>(i);
233 map<const void *, unsigned int>::const_iterator
234 entry(addressMap.find(*dest));
235 if (entry == addressMap.end()) {
236 throw runtime_error("unable to relocate array member");
238 unsigned int destOffset = entry->second;
239 *dest = reinterpret_cast<char *>(destOffset);
243 void Compiler::Relocate(char *object, const TypeDescription &td) {
244 for (TypeDescription::FieldIterator
245 i(td.FieldsBegin()), end(td.FieldsEnd());
247 const FieldDescription &fd = i->second;
248 if (!fd.IsAggregate() && !fd.IsReferenced()) {
251 char **dest = reinterpret_cast<char **>(
252 object + fd.Offset());
256 map<const void *, unsigned int>::const_iterator
257 entry(addressMap.find(*dest));
258 if (entry == addressMap.end()) {
259 throw runtime_error(string("unable to relocate field ")
260 + i->first + " in object of type " + td.TypeName());
262 unsigned int destOffset = entry->second;
263 *dest = reinterpret_cast<char *>(destOffset);
268 void Compiler::Write(ostream &out, const void *data, int amount) {
269 out.write(reinterpret_cast<const char *>(data), amount);
273 void Compiler::Pad(ostream &out, int to) {
274 Fill(out, Remaining(cursor, to));
277 void Compiler::Fill(ostream &out, int count, char c) {
278 for (int remaining(count); remaining > 0; --remaining) {
284 int Compiler::Remaining(int value, int alignment) {
285 int have(value % alignment);
286 return (have > 0) ? (16 - have) : 0;