Mercurial > projects > ldc
comparison gen/classes.cpp @ 797:340acf1535d0
Removed KDevelop3 project files, CMake can generate them just fine!
Fixed function literals in static initializers.
Changed alignment of delegates from 2*PTRSIZE to just PTRSIZE.
Changed errors to go to stderr instead of stdout.
Fairly major rewriting of struct/union/class handling, STILL A BIT BUGGY !!!
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sat, 29 Nov 2008 21:25:43 +0100 |
parents | 6e7a4c3b64d2 |
children | 9f92b6e40fd3 d14e4594c7d7 |
comparison
equal
deleted
inserted
replaced
796:6e7a4c3b64d2 | 797:340acf1535d0 |
---|---|
19 | 19 |
20 #include "ir/irstruct.h" | 20 #include "ir/irstruct.h" |
21 | 21 |
22 ////////////////////////////////////////////////////////////////////////////////////////// | 22 ////////////////////////////////////////////////////////////////////////////////////////// |
23 | 23 |
24 static void LLVM_AddBaseClassInterfaces(ClassDeclaration* target, BaseClasses* bcs) | 24 // adds interface b to target, if newinstance != 0, then target must provide all |
25 { | 25 // functions required to implement b (it reimplements b) |
26 // add base class data members first | 26 static void add_interface(ClassDeclaration* target, BaseClass* b, int newinstance) |
27 for (int j=0; j<bcs->dim; j++) | 27 { |
28 { | 28 Logger::println("adding interface: %s", b->base->toChars()); |
29 BaseClass* bc = (BaseClass*)(bcs->data[j]); | 29 LOG_SCOPE; |
30 | 30 |
31 // base *classes* might add more interfaces? | 31 InterfaceDeclaration* inter = b->base->isInterfaceDeclaration(); |
32 DtoResolveClass(bc->base); | 32 DtoResolveClass(inter); |
33 LLVM_AddBaseClassInterfaces(target, &bc->base->baseclasses); | 33 |
34 | 34 assert(inter); |
35 // resolve interfaces while we're at it | 35 IrStruct* irstruct = target->ir.irStruct; |
36 if (bc->base->isInterfaceDeclaration()) | 36 assert(irstruct); |
37 | |
38 // add interface to map/list | |
39 // if it's already inserted in the map, it's because another interface has it as baseclass | |
40 // but if it appears here, it's because we're reimplementing it, so we overwrite the IrInterface entry | |
41 IrInterface* iri; | |
42 bool overwrite = false; | |
43 if (irstruct->interfaceMap.find(inter) != irstruct->interfaceMap.end()) | |
44 { | |
45 overwrite = true; | |
46 } | |
47 | |
48 iri = new IrInterface(b); | |
49 // add to map | |
50 if (overwrite) | |
51 irstruct->interfaceMap[b->base] = iri; | |
52 else | |
53 irstruct->interfaceMap.insert(std::make_pair(b->base, iri)); | |
54 // add to ordered list | |
55 irstruct->interfaceVec.push_back(iri); | |
56 | |
57 // assign this iri to all base interfaces of this one | |
58 for (unsigned j = 0; j < b->baseInterfaces_dim; j++) | |
59 { | |
60 BaseClass *bc = &b->baseInterfaces[j]; | |
61 // add to map | |
62 if (irstruct->interfaceMap.find(bc->base) == irstruct->interfaceMap.end()) | |
37 { | 63 { |
38 // don't add twice | 64 irstruct->interfaceMap.insert(std::make_pair(bc->base, iri)); |
39 if (target->ir.irStruct->interfaceMap.find(bc->base) == target->ir.irStruct->interfaceMap.end()) | |
40 { | |
41 Logger::println("adding interface '%s'", bc->base->toPrettyChars()); | |
42 IrInterface* iri = new IrInterface(bc); | |
43 | |
44 // add to map | |
45 target->ir.irStruct->interfaceMap.insert(std::make_pair(bc->base, iri)); | |
46 // add to ordered list | |
47 target->ir.irStruct->interfaceVec.push_back(iri); | |
48 | |
49 // Fill in vtbl[] | |
50 if (!target->isAbstract()) { | |
51 bc->fillVtbl(target, &bc->vtbl, 0); | |
52 } | |
53 } | |
54 } | 65 } |
55 } | 66 } |
56 } | 67 |
57 | 68 // build the interface vtable |
58 ////////////////////////////////////////////////////////////////////////////////////////// | 69 b->fillVtbl(target, &b->vtbl, newinstance); |
59 | 70 |
60 static void LLVM_AddBaseClassData(IrStruct* irstruct, BaseClasses* bcs) | 71 // add the vtable type |
61 { | 72 assert(inter->type->ir.type); |
62 // add base class data members first | 73 irstruct->types.push_back( inter->type->ir.type->get() ); |
63 for (int j=0; j<bcs->dim; j++) | 74 // set and increment index |
64 { | 75 iri->index = irstruct->index++; |
65 BaseClass* bc = (BaseClass*)(bcs->data[j]); | 76 } |
66 | 77 |
67 // interfaces never add data fields | 78 static void add_class_data(ClassDeclaration* target, ClassDeclaration* cd) |
68 if (bc->base->isInterfaceDeclaration()) | 79 { |
69 continue; | 80 Logger::println("Adding data from class: %s", cd->toChars()); |
70 | 81 LOG_SCOPE; |
71 // recursively add baseclass data | 82 |
72 LLVM_AddBaseClassData(irstruct, &bc->base->baseclasses); | 83 // recurse into baseClasses |
73 | 84 if (cd->baseClass) |
74 Array* arr = &bc->base->fields; | 85 { |
75 if (arr->dim == 0) | 86 add_class_data(target, cd->baseClass); |
76 continue; | 87 //offset = baseClass->structsize; |
77 | 88 } |
78 Logger::println("Adding base class members of %s", bc->base->toChars()); | 89 |
79 LOG_SCOPE; | 90 // add members |
80 | 91 Array* arr = cd->members; |
81 for (int k=0; k < arr->dim; k++) { | 92 for (int k=0; k < arr->dim; k++) { |
82 VarDeclaration* v = (VarDeclaration*)(arr->data[k]); | 93 Dsymbol* s = (Dsymbol*)arr->data[k]; |
83 Logger::println("Adding field: %s %s", v->type->toChars(), v->toChars()); | 94 s->toObjFile(0); |
84 // init fields, used to happen in VarDeclaration::toObjFile | 95 } |
85 irstruct->addField(v); | 96 |
97 // add interfaces | |
98 if (cd->vtblInterfaces) | |
99 { | |
100 Logger::println("num vtbl interfaces: %u", cd->vtblInterfaces->dim); | |
101 for (int i = 0; i < cd->vtblInterfaces->dim; i++) | |
102 { | |
103 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; | |
104 assert(b); | |
105 // create new instances only for explicitly derived interfaces | |
106 add_interface(target, b, (cd == target)); | |
86 } | 107 } |
87 } | 108 } |
88 } | 109 } |
89 | 110 |
90 ////////////////////////////////////////////////////////////////////////////////////////// | 111 ////////////////////////////////////////////////////////////////////////////////////////// |
91 | 112 |
92 void DtoResolveClass(ClassDeclaration* cd) | 113 static void DtoResolveInterface(InterfaceDeclaration* cd) |
93 { | 114 { |
94 if (cd->ir.resolved) return; | 115 if (cd->ir.resolved) return; |
95 cd->ir.resolved = true; | 116 cd->ir.resolved = true; |
96 | 117 |
97 Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | 118 Logger::println("DtoResolveInterface(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); |
98 LOG_SCOPE; | 119 LOG_SCOPE; |
99 | |
100 //printf("resolve class: %s\n", cd->toPrettyChars()); | |
101 | 120 |
102 // get the TypeClass | 121 // get the TypeClass |
103 assert(cd->type->ty == Tclass); | 122 assert(cd->type->ty == Tclass); |
104 TypeClass* ts = (TypeClass*)cd->type; | 123 TypeClass* ts = (TypeClass*)cd->type; |
105 | 124 |
106 // make sure the IrStruct is created | 125 // create the IrStruct, we need somewhere to store the classInfo |
107 IrStruct* irstruct = cd->ir.irStruct; | 126 assert(!cd->ir.irStruct); |
108 if (!irstruct) { | 127 IrStruct* irstruct = new IrStruct(cd); |
109 irstruct = new IrStruct(ts); | 128 cd->ir.irStruct = irstruct; |
110 cd->ir.irStruct = irstruct; | 129 |
130 // handle base interfaces | |
131 if (cd->baseclasses.dim) | |
132 { | |
133 Logger::println("num baseclasses: %u", cd->baseclasses.dim); | |
134 LOG_SCOPE; | |
135 | |
136 for (int i=0; i<cd->baseclasses.dim; i++) | |
137 { | |
138 BaseClass* bc = (BaseClass*)cd->baseclasses.data[i]; | |
139 Logger::println("baseclass %d: %s", i, bc->base->toChars()); | |
140 | |
141 InterfaceDeclaration* id = bc->base->isInterfaceDeclaration(); | |
142 assert(id); | |
143 | |
144 DtoResolveInterface(id); | |
145 | |
146 // add to interfaceInfos | |
147 IrInterface* iri = new IrInterface(bc); | |
148 irstruct->interfaceVec.push_back(iri); | |
149 } | |
150 } | |
151 | |
152 // create the type | |
153 const LLType* t = LLArrayType::get(getVoidPtrType(), cd->vtbl.dim); | |
154 assert(!ts->ir.type); | |
155 ts->ir.type = new LLPATypeHolder(getPtrToType(t)); | |
156 | |
157 // request declaration | |
158 gIR->declareList.push_back(cd); | |
159 | |
160 // handle members | |
161 // like "nested" interfaces | |
162 Array* arr = cd->members; | |
163 for (int k=0; k < arr->dim; k++) { | |
164 Dsymbol* s = (Dsymbol*)arr->data[k]; | |
165 s->toObjFile(0); | |
166 } | |
167 } | |
168 | |
169 ////////////////////////////////////////////////////////////////////////////////////////// | |
170 | |
171 // FIXME: this needs to be cleaned up | |
172 | |
173 void DtoResolveClass(ClassDeclaration* cd) | |
174 { | |
175 if (InterfaceDeclaration* id = cd->isInterfaceDeclaration()) | |
176 { | |
177 DtoResolveInterface(id); | |
178 return; | |
179 } | |
180 | |
181 if (cd->ir.resolved) return; | |
182 cd->ir.resolved = true; | |
183 | |
184 Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | |
185 LOG_SCOPE; | |
186 | |
187 //printf("resolve class: %s\n", cd->toPrettyChars()); | |
188 | |
189 // get the TypeClass | |
190 assert(cd->type->ty == Tclass); | |
191 TypeClass* ts = (TypeClass*)cd->type; | |
192 | |
193 // create the IrStruct | |
194 assert(!cd->ir.irStruct); | |
195 IrStruct* irstruct = new IrStruct(cd); | |
196 cd->ir.irStruct = irstruct; | |
197 | |
198 // create the type | |
199 ts->ir.type = new LLPATypeHolder(llvm::OpaqueType::get()); | |
200 | |
201 // if it just a forward declaration? | |
202 if (cd->sizeok != 1) | |
203 { | |
204 // just name the type | |
205 gIR->module->addTypeName(cd->mangle(), ts->ir.type->get()); | |
206 return; | |
111 } | 207 } |
112 | 208 |
113 // resolve the base class | 209 // resolve the base class |
114 if (cd->baseClass) { | 210 if (cd->baseClass) { |
115 DtoResolveClass(cd->baseClass); | 211 DtoResolveClass(cd->baseClass); |
116 } | 212 } |
117 | 213 |
118 // resolve interface vtables | |
119 /*if (cd->vtblInterfaces) { | |
120 Logger::println("Vtbl interfaces for '%s'", cd->toPrettyChars()); | |
121 LOG_SCOPE; | |
122 for (int i=0; i < cd->vtblInterfaces->dim; i++) { | |
123 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; | |
124 ClassDeclaration *id = b->base; | |
125 Logger::println("Vtbl interface: '%s'", id->toPrettyChars()); | |
126 DtoResolveClass(id); | |
127 // Fill in vtbl[] | |
128 b->fillVtbl(cd, &b->vtbl, 1); | |
129 } | |
130 }*/ | |
131 | |
132 // push state | 214 // push state |
133 gIR->structs.push_back(irstruct); | 215 gIR->structs.push_back(irstruct); |
134 gIR->classes.push_back(cd); | |
135 | |
136 // vector holding the field types | |
137 std::vector<const LLType*> fieldtypes; | |
138 | 216 |
139 // add vtable | 217 // add vtable |
140 ts->ir.vtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); | 218 irstruct->types.push_back(getPtrToType(irstruct->vtblTy.get())); |
141 const LLType* vtabty = getPtrToType(ts->ir.vtblType->get()); | 219 irstruct->index++; |
142 fieldtypes.push_back(vtabty); | |
143 | 220 |
144 // add monitor | 221 // add monitor |
145 fieldtypes.push_back(getVoidPtrType()); | 222 irstruct->types.push_back(getVoidPtrType()); |
146 | 223 irstruct->index++; |
147 // add base class data fields first | 224 |
148 LLVM_AddBaseClassData(irstruct, &cd->baseclasses); | 225 // add class data fields and interface vtables recursively |
149 | 226 add_class_data(cd, cd); |
150 // add own fields | 227 |
151 Array* fields = &cd->fields; | 228 // check if errors occured while building interface vtables |
152 for (int k=0; k < fields->dim; k++) | 229 if (global.errors) |
153 { | 230 fatal(); |
154 VarDeclaration* v = (VarDeclaration*)fields->data[k]; | |
155 Logger::println("Adding field: %s %s", v->type->toChars(), v->toChars()); | |
156 // init fields, used to happen in VarDeclaration::toObjFile | |
157 irstruct->addField(v); | |
158 } | |
159 | |
160 // then add other members of us, if any | |
161 if(cd->members) { | |
162 for (int k=0; k < cd->members->dim; k++) { | |
163 Dsymbol* dsym = (Dsymbol*)(cd->members->data[k]); | |
164 dsym->toObjFile(0); // TODO: multiobj | |
165 } | |
166 } | |
167 | |
168 // resolve class data fields (possibly unions) | |
169 Logger::println("doing class fields"); | |
170 | |
171 if (irstruct->offsets.empty()) | |
172 { | |
173 Logger::println("has no fields"); | |
174 } | |
175 else | |
176 { | |
177 Logger::println("has fields"); | |
178 unsigned prevsize = (unsigned)-1; | |
179 unsigned lastoffset = (unsigned)-1; | |
180 const LLType* fieldtype = NULL; | |
181 VarDeclaration* fieldinit = NULL; | |
182 size_t fieldpad = 0; | |
183 int idx = 0; | |
184 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | |
185 // first iteration | |
186 if (lastoffset == (unsigned)-1) { | |
187 lastoffset = i->first; | |
188 fieldtype = i->second.type; | |
189 fieldinit = i->second.var; | |
190 prevsize = getABITypeSize(fieldtype); | |
191 i->second.var->ir.irField->index = idx; | |
192 } | |
193 // colliding offset? | |
194 else if (lastoffset == i->first) { | |
195 size_t s = getABITypeSize(i->second.type); | |
196 if (s > prevsize) { | |
197 fieldpad += s - prevsize; | |
198 prevsize = s; | |
199 } | |
200 cd->ir.irStruct->hasUnions = true; | |
201 i->second.var->ir.irField->index = idx; | |
202 } | |
203 // intersecting offset? | |
204 else if (i->first < (lastoffset + prevsize)) { | |
205 size_t s = getABITypeSize(i->second.type); | |
206 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size | |
207 cd->ir.irStruct->hasUnions = true; | |
208 i->second.var->ir.irField->index = idx; | |
209 i->second.var->ir.irField->indexOffset = (i->first - lastoffset) / s; | |
210 } | |
211 // fresh offset | |
212 else { | |
213 // commit the field | |
214 fieldtypes.push_back(fieldtype); | |
215 irstruct->defaultFields.push_back(fieldinit); | |
216 if (fieldpad) { | |
217 fieldtypes.push_back(llvm::ArrayType::get(LLType::Int8Ty, fieldpad)); | |
218 irstruct->defaultFields.push_back(NULL); | |
219 idx++; | |
220 } | |
221 | |
222 idx++; | |
223 | |
224 // start new | |
225 lastoffset = i->first; | |
226 fieldtype = i->second.type; | |
227 fieldinit = i->second.var; | |
228 prevsize = getABITypeSize(fieldtype); | |
229 i->second.var->ir.irField->index = idx; | |
230 fieldpad = 0; | |
231 } | |
232 } | |
233 fieldtypes.push_back(fieldtype); | |
234 irstruct->defaultFields.push_back(fieldinit); | |
235 if (fieldpad) { | |
236 fieldtypes.push_back(llvm::ArrayType::get(LLType::Int8Ty, fieldpad)); | |
237 irstruct->defaultFields.push_back(NULL); | |
238 } | |
239 } | |
240 | |
241 // populate interface map | |
242 { | |
243 Logger::println("Adding interfaces to '%s'", cd->toPrettyChars()); | |
244 LOG_SCOPE; | |
245 LLVM_AddBaseClassInterfaces(cd, &cd->baseclasses); | |
246 Logger::println("%d interfaces added", cd->ir.irStruct->interfaceVec.size()); | |
247 assert(cd->ir.irStruct->interfaceVec.size() == cd->ir.irStruct->interfaceMap.size()); | |
248 } | |
249 | |
250 // add interface vtables at the end | |
251 int interIdx = (int)fieldtypes.size(); | |
252 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) | |
253 { | |
254 IrInterface* iri = *i; | |
255 ClassDeclaration* id = iri->decl; | |
256 | |
257 // set vtbl type | |
258 TypeClass* itc = (TypeClass*)id->type; | |
259 const LLType* ivtblTy = itc->ir.vtblType->get(); | |
260 assert(ivtblTy); | |
261 if (Logger::enabled()) | |
262 Logger::cout() << "interface vtbl type: " << *ivtblTy << '\n'; | |
263 fieldtypes.push_back(getPtrToType(ivtblTy)); | |
264 | |
265 // fix the interface vtable type | |
266 assert(iri->vtblTy == NULL); | |
267 iri->vtblTy = new llvm::PATypeHolder(ivtblTy); | |
268 | |
269 // set index | |
270 iri->index = interIdx++; | |
271 } | |
272 Logger::println("%d interface vtables added", cd->ir.irStruct->interfaceVec.size()); | |
273 assert(cd->ir.irStruct->interfaceVec.size() == cd->ir.irStruct->interfaceMap.size()); | |
274 | 231 |
275 // create type | 232 // create type |
276 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); | 233 assert(irstruct->index == irstruct->types.size()); |
234 const LLType* structtype = irstruct->build(); | |
277 | 235 |
278 // refine abstract types for stuff like: class C {C next;} | 236 // refine abstract types for stuff like: class C {C next;} |
279 assert(irstruct->recty != 0); | 237 llvm::PATypeHolder* spa = ts->ir.type; |
280 llvm::PATypeHolder& spa = irstruct->recty; | 238 llvm::cast<llvm::OpaqueType>(spa->get())->refineAbstractTypeTo(structtype); |
281 llvm::cast<llvm::OpaqueType>(spa.get())->refineAbstractTypeTo(structtype); | 239 structtype = isaStruct(spa->get()); |
282 structtype = isaStruct(spa.get()); | |
283 | |
284 // make it official | |
285 if (!ts->ir.type) | |
286 ts->ir.type = new llvm::PATypeHolder(structtype); | |
287 else | |
288 *ts->ir.type = structtype; | |
289 spa = *ts->ir.type; | |
290 | 240 |
291 // name the type | 241 // name the type |
292 gIR->module->addTypeName(cd->mangle(), ts->ir.type->get()); | 242 gIR->module->addTypeName(cd->mangle(), ts->ir.type->get()); |
293 | 243 |
294 // create vtable type | 244 // refine vtable type |
295 llvm::GlobalVariable* svtblVar = 0; | 245 |
296 #if OPAQUE_VTBLS | |
297 // void*[vtbl.dim] | 246 // void*[vtbl.dim] |
298 const llvm::ArrayType* svtbl_ty | 247 llvm::cast<llvm::OpaqueType>(irstruct->vtblTy.get())->refineAbstractTypeTo(LLArrayType::get(getVoidPtrType(), cd->vtbl.dim)); |
299 = llvm::ArrayType::get(getVoidPtrType(), cd->vtbl.dim); | |
300 | |
301 #else | |
302 std::vector<const LLType*> sinits_ty; | |
303 | |
304 for (int k=0; k < cd->vtbl.dim; k++) | |
305 { | |
306 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; | |
307 assert(dsym); | |
308 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; | |
309 | |
310 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { | |
311 DtoResolveFunction(fd); | |
312 //assert(fd->type->ty == Tfunction); | |
313 //TypeFunction* tf = (TypeFunction*)fd->type; | |
314 //const LLType* fpty = getPtrToType(tf->ir.type->get()); | |
315 const llvm::FunctionType* vfty = DtoBaseFunctionType(fd); | |
316 const LLType* vfpty = getPtrToType(vfty); | |
317 sinits_ty.push_back(vfpty); | |
318 } | |
319 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { | |
320 Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars()); | |
321 const LLType* cinfoty; | |
322 if (cd->isInterfaceDeclaration()) { | |
323 cinfoty = DtoInterfaceInfoType(); | |
324 } | |
325 else if (cd != ClassDeclaration::classinfo) { | |
326 cinfoty = ClassDeclaration::classinfo->type->ir.type->get(); | |
327 } | |
328 else { | |
329 // this is the ClassInfo class, the type is this type | |
330 cinfoty = ts->ir.type->get(); | |
331 } | |
332 const LLType* cty = getPtrToType(cinfoty); | |
333 sinits_ty.push_back(cty); | |
334 } | |
335 else | |
336 assert(0); | |
337 } | |
338 | |
339 // get type | |
340 assert(!sinits_ty.empty()); | |
341 const llvm::StructType* svtbl_ty = llvm::StructType::get(sinits_ty); | |
342 #endif | |
343 | |
344 // refine for final vtable type | |
345 llvm::cast<llvm::OpaqueType>(ts->ir.vtblType->get())->refineAbstractTypeTo(svtbl_ty); | |
346 | |
347 #if !OPAQUE_VTBLS | |
348 // name vtbl type | |
349 std::string styname(cd->mangle()); | |
350 styname.append("__vtblType"); | |
351 gIR->module->addTypeName(styname, svtbl_ty); | |
352 #endif | |
353 | 248 |
354 // log | 249 // log |
355 //Logger::cout() << "final class type: " << *ts->ir.type->get() << '\n'; | 250 Logger::cout() << "final class type: " << *ts->ir.type->get() << '\n'; |
356 | 251 |
357 // pop state | 252 // pop state |
358 gIR->classes.pop_back(); | |
359 gIR->structs.pop_back(); | 253 gIR->structs.pop_back(); |
360 | 254 |
361 // queue declare | 255 // queue declare |
362 gIR->declareList.push_back(cd); | 256 gIR->declareList.push_back(cd); |
363 } | 257 } |
364 | 258 |
365 ////////////////////////////////////////////////////////////////////////////////////////// | 259 ////////////////////////////////////////////////////////////////////////////////////////// |
366 | 260 |
367 void DtoDeclareClass(ClassDeclaration* cd) | 261 static void DtoDeclareInterface(InterfaceDeclaration* cd) |
368 { | 262 { |
369 if (cd->ir.declared) return; | 263 if (cd->ir.declared) return; |
370 cd->ir.declared = true; | 264 cd->ir.declared = true; |
371 | 265 |
372 Logger::println("DtoDeclareClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | 266 Logger::println("DtoDeclareInterface(%s): %s", cd->toPrettyChars(), cd->locToChars()); |
267 LOG_SCOPE; | |
268 | |
269 assert(cd->ir.irStruct); | |
270 IrStruct* irstruct = cd->ir.irStruct; | |
271 | |
272 // get interface info type | |
273 const llvm::StructType* infoTy = DtoInterfaceInfoType(); | |
274 | |
275 // interface info array | |
276 if (!irstruct->interfaceVec.empty()) { | |
277 // symbol name | |
278 std::string nam = "_D"; | |
279 nam.append(cd->mangle()); | |
280 nam.append("16__interfaceInfosZ"); | |
281 | |
282 llvm::GlobalValue::LinkageTypes linkage = DtoLinkage(cd); | |
283 | |
284 // resolve array type | |
285 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, irstruct->interfaceVec.size()); | |
286 // declare global | |
287 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, linkage, NULL, nam, gIR->module); | |
288 | |
289 // do each interface info | |
290 unsigned idx = 0; | |
291 size_t n = irstruct->interfaceVec.size(); | |
292 for (size_t i=0; i < n; i++) | |
293 { | |
294 IrInterface* iri = irstruct->interfaceVec[i]; | |
295 ClassDeclaration* id = iri->decl; | |
296 | |
297 // always create interfaceinfos | |
298 LLConstant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)}; | |
299 iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2); | |
300 idx++; | |
301 } | |
302 } | |
303 | |
304 // declare the classinfo | |
305 DtoDeclareClassInfo(cd); | |
306 | |
307 // request const init | |
308 gIR->constInitList.push_back(cd); | |
309 | |
310 // emit typeinfo and request definition | |
311 if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) | |
312 { | |
313 gIR->defineList.push_back(cd); | |
314 DtoTypeInfoOf(cd->type, false); | |
315 } | |
316 } | |
317 | |
318 ////////////////////////////////////////////////////////////////////////////////////////// | |
319 | |
320 // FIXME: this needs to be cleaned up | |
321 | |
322 void DtoDeclareClass(ClassDeclaration* cd) | |
323 { | |
324 if (InterfaceDeclaration* id = cd->isInterfaceDeclaration()) | |
325 { | |
326 DtoDeclareInterface(id); | |
327 return; | |
328 } | |
329 | |
330 if (cd->ir.declared) return; | |
331 cd->ir.declared = true; | |
332 | |
333 Logger::println("DtoDeclareClass(%s): %s", cd->toPrettyChars(), cd->locToChars()); | |
373 LOG_SCOPE; | 334 LOG_SCOPE; |
374 | 335 |
375 //printf("declare class: %s\n", cd->toPrettyChars()); | 336 //printf("declare class: %s\n", cd->toPrettyChars()); |
376 | 337 |
377 assert(cd->type->ty == Tclass); | 338 assert(cd->type->ty == Tclass); |
379 | 340 |
380 assert(cd->ir.irStruct); | 341 assert(cd->ir.irStruct); |
381 IrStruct* irstruct = cd->ir.irStruct; | 342 IrStruct* irstruct = cd->ir.irStruct; |
382 | 343 |
383 gIR->structs.push_back(irstruct); | 344 gIR->structs.push_back(irstruct); |
384 gIR->classes.push_back(cd); | |
385 | 345 |
386 bool needs_definition = false; | 346 bool needs_definition = false; |
387 if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) { | 347 if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) { |
388 needs_definition = true; | 348 needs_definition = true; |
389 } | 349 } |
390 | 350 |
391 llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(cd); | 351 llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(cd); |
392 | 352 |
393 // interfaces have no static initializer | 353 // create vtbl symbol |
394 // same goes for abstract classes | 354 std::string varname("_D"); |
395 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { | 355 varname.append(cd->mangle()); |
396 // vtable | 356 varname.append("6__vtblZ"); |
397 std::string varname("_D"); | 357 irstruct->vtbl = new llvm::GlobalVariable(irstruct->vtblInitTy.get(), true, _linkage, 0, varname, gIR->module); |
398 varname.append(cd->mangle()); | |
399 varname.append("6__vtblZ"); | |
400 cd->ir.irStruct->vtbl = new llvm::GlobalVariable(ts->ir.vtblType->get(), true, _linkage, 0, varname, gIR->module); | |
401 } | |
402 | 358 |
403 // get interface info type | 359 // get interface info type |
404 const llvm::StructType* infoTy = DtoInterfaceInfoType(); | 360 const llvm::StructType* infoTy = DtoInterfaceInfoType(); |
405 | 361 |
406 // interface info array | 362 // interface info array |
407 if (!cd->ir.irStruct->interfaceVec.empty()) { | 363 if (!irstruct->interfaceVec.empty()) { |
408 // symbol name | 364 // symbol name |
409 std::string nam = "_D"; | 365 std::string nam = "_D"; |
410 nam.append(cd->mangle()); | 366 nam.append(cd->mangle()); |
411 nam.append("16__interfaceInfosZ"); | 367 nam.append("16__interfaceInfosZ"); |
412 // resolve array type | 368 // resolve array type |
413 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->ir.irStruct->interfaceVec.size()); | 369 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, irstruct->interfaceVec.size()); |
414 // declare global | 370 // declare global |
415 irstruct->interfaceInfosTy = arrTy; | |
416 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module); | 371 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module); |
417 } | 372 } |
418 | 373 |
419 // interfaces have no static initializer | 374 // DMD gives abstract classes a full ClassInfo, so we do it as well |
420 // same goes for abstract classes | 375 |
421 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { | 376 // interface vtables |
422 // interface vtables | 377 unsigned idx = 0; |
423 unsigned idx = 0; | 378 |
424 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) | 379 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) |
425 { | 380 { |
426 IrInterface* iri = *i; | 381 IrInterface* iri = *i; |
427 ClassDeclaration* id = iri->decl; | 382 ClassDeclaration* id = iri->decl; |
428 | 383 |
429 std::string nam("_D"); | 384 std::string nam("_D"); |
430 nam.append(cd->mangle()); | 385 nam.append(cd->mangle()); |
431 nam.append("11__interface"); | 386 nam.append("11__interface"); |
432 nam.append(id->mangle()); | 387 nam.append(id->mangle()); |
433 nam.append("6__vtblZ"); | 388 nam.append("6__vtblZ"); |
434 | 389 |
435 assert(iri->vtblTy); | 390 iri->vtbl = new llvm::GlobalVariable(iri->vtblInitTy.get(), true, _linkage, 0, nam, gIR->module); |
436 iri->vtbl = new llvm::GlobalVariable(iri->vtblTy->get(), true, _linkage, 0, nam, gIR->module); | 391 |
437 LLConstant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)}; | 392 // always create interfaceinfos |
438 iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2); | 393 LLConstant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)}; |
439 idx++; | 394 iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2); |
440 } | 395 idx++; |
441 | 396 } |
442 // init | 397 |
443 std::string initname("_D"); | 398 // initZ init |
444 initname.append(cd->mangle()); | 399 std::string initname("_D"); |
445 initname.append("6__initZ"); | 400 initname.append(cd->mangle()); |
446 | 401 initname.append("6__initZ"); |
447 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->ir.type->get(), true, _linkage, NULL, initname, gIR->module); | 402 |
448 cd->ir.irStruct->init = initvar; | 403 // initZ global |
449 } | 404 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(irstruct->initOpaque.get(), true, _linkage, NULL, initname, gIR->module); |
450 | 405 irstruct->init = initvar; |
451 gIR->classes.pop_back(); | 406 |
452 gIR->structs.pop_back(); | 407 gIR->structs.pop_back(); |
453 | 408 |
409 // request const init | |
454 gIR->constInitList.push_back(cd); | 410 gIR->constInitList.push_back(cd); |
411 | |
412 // define ? (set initializers) | |
455 if (needs_definition) | 413 if (needs_definition) |
456 gIR->defineList.push_back(cd); | 414 gIR->defineList.push_back(cd); |
457 | 415 |
458 // classinfo | 416 // classinfo |
459 DtoDeclareClassInfo(cd); | 417 DtoDeclareClassInfo(cd); |
460 | 418 |
461 // typeinfo | 419 // do typeinfo ? |
462 if (needs_definition) | 420 if (needs_definition) |
463 DtoTypeInfoOf(cd->type, false); | 421 DtoTypeInfoOf(cd->type, false); |
464 } | 422 } |
465 | 423 |
466 ////////////////////////////////////////////////////////////////////////////////////////// | 424 ////////////////////////////////////////////////////////////////////////////////////////// |
467 | 425 |
468 void DtoConstInitClass(ClassDeclaration* cd) | 426 void addZeros(std::vector<llvm::Constant*>& inits, size_t pos, size_t offset); // irstruct.cpp |
427 | |
428 ////////////////////////////////////////////////////////////////////////////// | |
429 | |
430 // assigns constant initializers to fields introduced by cd | |
431 static void init_field_inits(ClassDeclaration* cd) | |
432 { | |
433 size_t n = cd->fields.dim; | |
434 for (size_t i=0; i<n; i++) | |
435 { | |
436 VarDeclaration* v = (VarDeclaration*)cd->fields.data[i]; | |
437 IrField* f = v->ir.irField; | |
438 assert(!f->constInit); | |
439 f->constInit = DtoConstFieldInitializer(v->loc, v->type, v->init); | |
440 } | |
441 } | |
442 | |
443 ////////////////////////////////////////////////////////////////////////////// | |
444 | |
445 // adds data fields and interface vtables to the constant initializer of class cd | |
446 static size_t init_class_initializer(std::vector<LLConstant*>& inits, ClassDeclaration* target, ClassDeclaration* cd, size_t offsetbegin) | |
447 { | |
448 // first do baseclasses | |
449 if (cd->baseClass) | |
450 { | |
451 offsetbegin = init_class_initializer(inits, target, cd->baseClass, offsetbegin); | |
452 } | |
453 | |
454 Logger::println("adding data of %s to %s", cd->toChars(), target->toChars()); | |
455 LOG_SCOPE; | |
456 | |
457 // add default fields | |
458 VarDeclaration** fields = (VarDeclaration**)cd->fields.data; | |
459 size_t nfields = cd->fields.dim; | |
460 | |
461 std::vector<VarDeclaration*> defVars; | |
462 defVars.reserve(nfields); | |
463 | |
464 size_t lastoffset = offsetbegin; // vtbl,monitor | |
465 size_t lastsize = 0; | |
466 | |
467 // find fields that contribute to default | |
468 for (size_t i=0; i<nfields; i++) | |
469 { | |
470 VarDeclaration* var = fields[i]; | |
471 // only add vars that don't overlap | |
472 size_t offset = var->offset; | |
473 size_t size = var->type->size(); | |
474 if (offset >= lastoffset+lastsize) | |
475 { | |
476 Logger::println(" added"); | |
477 lastoffset = offset; | |
478 lastsize = size; | |
479 defVars.push_back(var); | |
480 } | |
481 } | |
482 | |
483 // go through the default vars and build the default constant initializer | |
484 // adding zeros along the way to live up to alignment expectations | |
485 size_t nvars = defVars.size(); | |
486 for (size_t i=0; i<nvars; i++) | |
487 { | |
488 VarDeclaration* var = defVars[i]; | |
489 | |
490 Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset); | |
491 | |
492 // get offset and size | |
493 size_t offset = var->offset; | |
494 size_t size = var->type->size(); | |
495 | |
496 // is there space in between last last offset and this one? | |
497 // if so, fill it with zeros | |
498 if (offset > lastoffset+lastsize) | |
499 { | |
500 size_t pos = lastoffset + lastsize; | |
501 addZeros(inits, pos, offset); | |
502 } | |
503 | |
504 // add the field | |
505 assert(var->ir.irField->constInit); | |
506 inits.push_back(var->ir.irField->constInit); | |
507 | |
508 lastoffset = offset; | |
509 lastsize = var->type->size(); | |
510 } | |
511 | |
512 // if it's a class, and it implements interfaces, add the vtables | |
513 IrStruct* irstruct = cd->ir.irStruct; | |
514 | |
515 size_t nvtbls = cd->vtblInterfaces->dim; | |
516 for(size_t i=0; i<nvtbls; i++) | |
517 { | |
518 BaseClass* bc = (BaseClass*)cd->vtblInterfaces->data[i]; | |
519 IrStruct::InterfaceMap::iterator iter = irstruct->interfaceMap.find(bc->base); | |
520 assert(iter != irstruct->interfaceMap.end()); | |
521 | |
522 IrInterface* iri = iter->second; | |
523 if (iri->vtbl) | |
524 inits.push_back(iri->vtbl); | |
525 else // abstract impl | |
526 inits.push_back(getNullPtr(getVoidPtrType())); | |
527 | |
528 lastoffset += PTRSIZE; | |
529 lastsize = PTRSIZE; | |
530 } | |
531 | |
532 // return next offset | |
533 return lastoffset + lastsize; | |
534 } | |
535 | |
536 ////////////////////////////////////////////////////////////////////////////// | |
537 | |
538 // build the vtable initializer for class cd | |
539 static void init_class_vtbl_initializer(ClassDeclaration* cd) | |
540 { | |
541 // generate vtable initializer | |
542 std::vector<LLConstant*> sinits(cd->vtbl.dim, NULL); | |
543 | |
544 IrStruct* irstruct = cd->ir.irStruct; | |
545 | |
546 assert(cd->vtbl.dim > 1); | |
547 | |
548 // first entry always classinfo | |
549 assert(irstruct->classInfo); | |
550 sinits[0] = DtoBitCast(irstruct->classInfo, DtoType(ClassDeclaration::classinfo->type)); | |
551 | |
552 // add virtual functions | |
553 for (int k=1; k < cd->vtbl.dim; k++) | |
554 { | |
555 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; | |
556 assert(dsym); | |
557 | |
558 // Logger::println("vtbl[%d] = %s", k, dsym->toChars()); | |
559 | |
560 FuncDeclaration* fd = dsym->isFuncDeclaration(); | |
561 assert(fd); | |
562 | |
563 if (fd->isAbstract()) | |
564 { | |
565 sinits[k] = getNullPtr(getVoidPtrType()); | |
566 } | |
567 else | |
568 { | |
569 DtoForceDeclareDsymbol(fd); | |
570 assert(fd->ir.irFunc->func); | |
571 sinits[k] = fd->ir.irFunc->func; | |
572 } | |
573 | |
574 // if (Logger::enabled()) | |
575 // Logger::cout() << "vtbl[" << k << "] = " << *sinits[k] << std::endl; | |
576 } | |
577 | |
578 irstruct->constVtbl = LLConstantStruct::get(sinits); | |
579 | |
580 // refine type | |
581 llvm::cast<llvm::OpaqueType>(irstruct->vtblInitTy.get())->refineAbstractTypeTo(irstruct->constVtbl->getType()); | |
582 | |
583 if (Logger::enabled()) | |
584 Logger::cout() << "vtbl initializer: " << *irstruct->constVtbl << std::endl; | |
585 } | |
586 | |
587 ////////////////////////////////////////////////////////////////////////////// | |
588 | |
589 static void init_class_interface_vtbl_initializers(ClassDeclaration* cd) | |
590 { | |
591 IrStruct* irstruct = cd->ir.irStruct; | |
592 | |
593 // don't do anything if list is empty | |
594 if (irstruct->interfaceVec.empty()) | |
595 return; | |
596 | |
597 std::vector<LLConstant*> inits; | |
598 std::vector<LLConstant*> infoInits(3); | |
599 | |
600 // go through each interface | |
601 size_t ninter = irstruct->interfaceVec.size(); | |
602 for (size_t i=0; i<ninter; i++) | |
603 { | |
604 IrInterface* iri = irstruct->interfaceVec[i]; | |
605 Logger::println("interface %s", iri->decl->toChars()); | |
606 | |
607 // build vtable intializer for this interface implementation | |
608 Array& arr = iri->base->vtbl; | |
609 size_t narr = arr.dim; | |
610 | |
611 if (narr > 0) | |
612 { | |
613 inits.resize(narr, NULL); | |
614 | |
615 // first is always the interface info | |
616 assert(iri->info); | |
617 inits[0] = iri->info; | |
618 | |
619 // build vtable | |
620 for (size_t j=1; j < narr; j++) | |
621 { | |
622 Dsymbol* dsym = (Dsymbol*)arr.data[j]; | |
623 if (!dsym) | |
624 { | |
625 inits[j] = getNullPtr(getVoidPtrType()); | |
626 continue; | |
627 } | |
628 | |
629 //Logger::println("ivtbl[%d] = %s", j, dsym->toChars()); | |
630 | |
631 // must all be functions | |
632 FuncDeclaration* fd = dsym->isFuncDeclaration(); | |
633 assert(fd); | |
634 | |
635 if (fd->isAbstract()) | |
636 inits[j] = getNullPtr(getVoidPtrType()); | |
637 else | |
638 { | |
639 DtoForceDeclareDsymbol(fd); | |
640 | |
641 assert(fd->ir.irFunc->func); | |
642 inits[j] = fd->ir.irFunc->func; | |
643 } | |
644 | |
645 //if (Logger::enabled()) | |
646 // Logger::cout() << "ivtbl[" << j << "] = " << *inits[j] << std::endl; | |
647 } | |
648 | |
649 // build the constant | |
650 iri->vtblInit = LLConstantStruct::get(inits); | |
651 } | |
652 | |
653 // build the interface info for ClassInfo | |
654 // generate interface info initializer | |
655 | |
656 DtoForceDeclareDsymbol(iri->decl); | |
657 | |
658 // classinfo | |
659 IrStruct* iris = iri->decl->ir.irStruct; | |
660 assert(iris); | |
661 assert(iris->classInfo); | |
662 infoInits[0] = DtoBitCast(iris->classInfo, DtoType(ClassDeclaration::classinfo->type)); | |
663 | |
664 // vtbl | |
665 LLConstant* c; | |
666 if (iri->vtbl) | |
667 c = llvm::ConstantExpr::getBitCast(iri->vtbl, getPtrToType(getVoidPtrType())); | |
668 else | |
669 c = getNullPtr(getPtrToType(getVoidPtrType())); | |
670 infoInits[1] = DtoConstSlice(DtoConstSize_t(narr), c); | |
671 | |
672 // offset | |
673 size_t ioff; | |
674 if (iri->index == 0) | |
675 ioff = 0; | |
676 else | |
677 ioff = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(iri->index); | |
678 | |
679 Logger::println("DMD interface offset: %d, LLVM interface offset: %lu", iri->base->offset, ioff); | |
680 assert(iri->base->offset == ioff); | |
681 infoInits[2] = DtoConstUint(ioff); | |
682 | |
683 // create interface info initializer constant | |
684 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(infoInits)); | |
685 } | |
686 } | |
687 | |
688 ////////////////////////////////////////////////////////////////////////////// | |
689 | |
690 static void DtoConstInitInterface(InterfaceDeclaration* cd) | |
469 { | 691 { |
470 if (cd->ir.initialized) return; | 692 if (cd->ir.initialized) return; |
471 cd->ir.initialized = true; | 693 cd->ir.initialized = true; |
472 | 694 |
473 Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | 695 Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); |
474 LOG_SCOPE; | 696 LOG_SCOPE; |
475 | 697 |
698 init_class_interface_vtbl_initializers(cd); | |
699 } | |
700 | |
701 ////////////////////////////////////////////////////////////////////////////// | |
702 | |
703 void DtoConstInitClass(ClassDeclaration* cd) | |
704 { | |
705 if (InterfaceDeclaration* it = cd->isInterfaceDeclaration()) | |
706 { | |
707 DtoConstInitInterface(it); | |
708 return; | |
709 } | |
710 | |
711 if (cd->ir.initialized) return; | |
712 cd->ir.initialized = true; | |
713 | |
714 Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | |
715 LOG_SCOPE; | |
716 | |
717 assert(!cd->isInterfaceDeclaration()); | |
718 | |
719 // make sure the baseclass is const initialized | |
720 if (cd->baseClass) | |
721 DtoForceConstInitDsymbol(cd->baseClass); | |
722 | |
723 // get IrStruct | |
476 IrStruct* irstruct = cd->ir.irStruct; | 724 IrStruct* irstruct = cd->ir.irStruct; |
477 gIR->structs.push_back(irstruct); | 725 gIR->structs.push_back(irstruct); |
478 gIR->classes.push_back(cd); | 726 |
727 // get types | |
728 TypeClass* tc = (TypeClass*)cd->type; | |
729 const llvm::StructType* structtype = isaStruct(tc->ir.type->get()); | |
730 assert(structtype); | |
731 const llvm::ArrayType* vtbltype = isaArray(irstruct->vtblTy.get()); | |
732 assert(vtbltype); | |
733 | |
734 // make sure each field knows its default initializer | |
735 init_field_inits(cd); | |
736 | |
737 // build initializer list | |
738 std::vector<LLConstant*> inits; | |
739 inits.reserve(irstruct->varDecls.size()); | |
740 | |
741 // vtable is always first | |
742 assert(irstruct->vtbl != 0); | |
743 inits.push_back(irstruct->vtbl); | |
744 | |
745 // then comes monitor | |
746 inits.push_back(LLConstant::getNullValue(getVoidPtrType())); | |
747 | |
748 // recursively do data and interface vtables | |
749 init_class_initializer(inits, cd, cd, 2 * PTRSIZE); | |
750 | |
751 // build vtable initializer | |
752 init_class_vtbl_initializer(cd); | |
753 | |
754 // build interface vtables | |
755 init_class_interface_vtbl_initializers(cd); | |
756 | |
757 // build constant from inits | |
758 irstruct->constInit = LLConstantStruct::get(inits); // classes are never packed | |
759 | |
760 // refine __initZ global type to the one of the initializer | |
761 llvm::cast<llvm::OpaqueType>(irstruct->initOpaque.get())->refineAbstractTypeTo(irstruct->constInit->getType()); | |
762 | |
763 if (Logger::enabled()) | |
764 { | |
765 Logger::cout() << "class " << cd->toChars() << std::endl; | |
766 Logger::cout() << "type " << *cd->type->ir.type->get() << std::endl; | |
767 Logger::cout() << "initializer " << *irstruct->constInit << std::endl; | |
768 } | |
769 | |
770 gIR->structs.pop_back(); | |
771 } | |
772 | |
773 ////////////////////////////////////////////////////////////////////////////////////////// | |
774 | |
775 static void DefineInterfaceInfos(IrStruct* irstruct) | |
776 { | |
777 // always do interface info array when possible | |
778 std::vector<LLConstant*> infoInits; | |
779 infoInits.reserve(irstruct->interfaceVec.size()); | |
780 | |
781 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) | |
782 { | |
783 IrInterface* iri = *i; | |
784 assert(iri->infoInit); | |
785 infoInits.push_back(iri->infoInit); | |
786 } | |
787 | |
788 // set initializer | |
789 if (!infoInits.empty()) | |
790 { | |
791 const LLArrayType* arrty = LLArrayType::get(infoInits[0]->getType(), infoInits.size()); | |
792 LLConstant* arrInit = llvm::ConstantArray::get(arrty, infoInits); | |
793 irstruct->interfaceInfos->setInitializer(arrInit); | |
794 } | |
795 else | |
796 { | |
797 assert(irstruct->interfaceInfos == NULL); | |
798 } | |
799 } | |
800 | |
801 ////////////////////////////////////////////////////////////////////////////////////////// | |
802 | |
803 static void DtoDefineInterface(InterfaceDeclaration* cd) | |
804 { | |
805 if (cd->ir.defined) return; | |
806 cd->ir.defined = true; | |
807 | |
808 Logger::println("DtoDefineClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | |
809 LOG_SCOPE; | |
810 | |
811 // defined interface infos | |
812 DefineInterfaceInfos(cd->ir.irStruct); | |
813 | |
814 // define the classinfo | |
815 if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) | |
816 { | |
817 DtoDefineClassInfo(cd); | |
818 } | |
819 } | |
820 | |
821 ////////////////////////////////////////////////////////////////////////////////////////// | |
822 | |
823 // FIXME: clean this up | |
824 | |
825 void DtoDefineClass(ClassDeclaration* cd) | |
826 { | |
827 if (InterfaceDeclaration* id = cd->isInterfaceDeclaration()) | |
828 { | |
829 DtoDefineInterface(id); | |
830 return; | |
831 } | |
832 | |
833 if (cd->ir.defined) return; | |
834 cd->ir.defined = true; | |
835 | |
836 Logger::println("DtoDefineClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | |
837 LOG_SCOPE; | |
479 | 838 |
480 // get the struct (class) type | 839 // get the struct (class) type |
481 assert(cd->type->ty == Tclass); | 840 assert(cd->type->ty == Tclass); |
482 TypeClass* ts = (TypeClass*)cd->type; | 841 TypeClass* ts = (TypeClass*)cd->type; |
483 const llvm::StructType* structtype = isaStruct(ts->ir.type->get()); | 842 |
484 #if OPAQUE_VTBLS | 843 IrStruct* irstruct = cd->ir.irStruct; |
485 const llvm::ArrayType* vtbltype = isaArray(ts->ir.vtblType->get()); | 844 |
486 #else | 845 assert(cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)); |
487 const llvm::StructType* vtbltype = isaStruct(ts->ir.vtblType->get()); | 846 |
488 #endif | 847 // sanity check |
489 | 848 assert(irstruct->init); |
490 // make sure each offset knows its default initializer | 849 assert(irstruct->constInit); |
491 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) | 850 assert(irstruct->vtbl); |
492 { | 851 assert(irstruct->constVtbl); |
493 IrStruct::Offset* so = &i->second; | 852 |
494 LLConstant* finit = DtoConstFieldInitializer(so->var->loc, so->var->type, so->var->init); | 853 if (Logger::enabled()) |
495 so->init = finit; | 854 { |
496 so->var->ir.irField->constInit = finit; | 855 Logger::cout() << "initZ: " << *irstruct->init << std::endl; |
497 } | 856 Logger::cout() << "cinitZ: " << *irstruct->constInit << std::endl; |
498 | 857 Logger::cout() << "vtblZ: " << *irstruct->vtbl << std::endl; |
499 // fill out fieldtypes/inits | 858 Logger::cout() << "cvtblZ: " << *irstruct->constVtbl << std::endl; |
500 std::vector<LLConstant*> fieldinits; | 859 } |
501 | 860 |
502 // first field is always the vtable | 861 // set initializers |
503 if (cd->isAbstract() || cd->isInterfaceDeclaration()) | 862 irstruct->init->setInitializer(irstruct->constInit); |
504 { | 863 irstruct->vtbl->setInitializer(irstruct->constVtbl); |
505 const LLType* ptrTy = getPtrToType(ts->ir.vtblType->get()); | 864 |
506 fieldinits.push_back(llvm::Constant::getNullValue(ptrTy)); | 865 // initialize interface vtables |
507 } | 866 size_t n = irstruct->interfaceVec.size(); |
508 else | 867 for (size_t i=0; i<n; i++) |
509 { | 868 { |
510 assert(cd->ir.irStruct->vtbl != 0); | 869 IrInterface* iri = irstruct->interfaceVec[i]; |
511 fieldinits.push_back(cd->ir.irStruct->vtbl); | 870 Logger::println("interface %s", iri->base->base->toChars()); |
512 } | 871 assert(iri->vtblInit); |
513 | 872 |
514 // then comes monitor | 873 // refine the init type |
515 fieldinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty))); | 874 llvm::cast<llvm::OpaqueType>(iri->vtblInitTy.get())->refineAbstractTypeTo(iri->vtblInit->getType()); |
516 | 875 |
517 // go through the field inits and build the default initializer | 876 // apply initializer |
518 size_t nfi = irstruct->defaultFields.size(); | 877 assert(iri->vtbl); |
519 for (size_t i=0; i<nfi; ++i) { | 878 iri->vtbl->setInitializer(iri->vtblInit); |
520 LLConstant* c; | 879 } |
521 if (irstruct->defaultFields[i]) { | 880 |
522 c = irstruct->defaultFields[i]->ir.irField->constInit; | 881 DefineInterfaceInfos(irstruct); |
523 assert(c); | 882 |
524 } | 883 // generate classinfo |
525 else { | 884 DtoDefineClassInfo(cd); |
526 const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i+2)); | |
527 assert(arrty); | |
528 std::vector<LLConstant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(LLType::Int8Ty, 0, false)); | |
529 c = llvm::ConstantArray::get(arrty, vals); | |
530 } | |
531 fieldinits.push_back(c); | |
532 } | |
533 | |
534 // last comes interface vtables | |
535 const llvm::StructType* infoTy = DtoInterfaceInfoType(); | |
536 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) | |
537 { | |
538 IrInterface* iri = *i; | |
539 iri->infoTy = infoTy; | |
540 | |
541 if (cd->isAbstract() || cd->isInterfaceDeclaration()) | |
542 { | |
543 fieldinits.push_back(llvm::Constant::getNullValue(structtype->getElementType(iri->index))); | |
544 } | |
545 else | |
546 { | |
547 assert(iri->vtbl); | |
548 fieldinits.push_back(iri->vtbl); | |
549 } | |
550 } | |
551 | |
552 // generate initializer | |
553 #if 0 | |
554 //Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n'; | |
555 assert(fieldinits.size() == structtype->getNumElements()); | |
556 for(size_t i=0; i<structtype->getNumElements(); ++i) { | |
557 Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n'; | |
558 Logger::cout() << "i#" << i << " = " << *fieldinits[i] << '\n'; | |
559 assert(fieldinits[i]->getType() == structtype->getElementType(i)); | |
560 } | |
561 #endif | |
562 | |
563 #if 0 | |
564 for(size_t i=0; i<fieldinits.size(); ++i) { | |
565 Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n'; | |
566 } | |
567 #endif | |
568 | |
569 LLConstant* _init = llvm::ConstantStruct::get(structtype, fieldinits); | |
570 assert(_init); | |
571 cd->ir.irStruct->constInit = _init; | |
572 | |
573 // abstract classes have no static vtable | |
574 // neither do interfaces (on their own, the implementing class supplies the vtable) | |
575 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) | |
576 { | |
577 // generate vtable initializer | |
578 std::vector<LLConstant*> sinits; | |
579 | |
580 for (int k=0; k < cd->vtbl.dim; k++) | |
581 { | |
582 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; | |
583 assert(dsym); | |
584 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; | |
585 | |
586 #if OPAQUE_VTBLS | |
587 const LLType* targetTy = getVoidPtrType(); | |
588 #else | |
589 const LLType* targetTy = vtbltype->getElementType(k); | |
590 #endif | |
591 | |
592 LLConstant* c = NULL; | |
593 // virtual method | |
594 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { | |
595 DtoForceDeclareDsymbol(fd); | |
596 assert(fd->ir.irFunc->func); | |
597 c = llvm::cast<llvm::Constant>(fd->ir.irFunc->func); | |
598 } | |
599 // classinfo | |
600 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { | |
601 assert(cd->ir.irStruct->classInfo); | |
602 c = cd->ir.irStruct->classInfo; | |
603 } | |
604 assert(c != NULL); | |
605 | |
606 // cast if necessary (overridden method) | |
607 if (c->getType() != targetTy) | |
608 c = llvm::ConstantExpr::getBitCast(c, targetTy); | |
609 sinits.push_back(c); | |
610 } | |
611 #if OPAQUE_VTBLS | |
612 const llvm::ArrayType* svtbl_ty = isaArray(ts->ir.vtblType->get()); | |
613 cd->ir.irStruct->constVtbl = llvm::ConstantArray::get(svtbl_ty, sinits); | |
614 #else | |
615 const llvm::StructType* svtbl_ty = isaStruct(ts->ir.vtblType->get()); | |
616 LLConstant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); | |
617 cd->ir.irStruct->constVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); | |
618 #endif | |
619 | |
620 // create interface vtable const initalizers | |
621 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) | |
622 { | |
623 IrInterface* iri = *i; | |
624 BaseClass* b = iri->base; | |
625 | |
626 ClassDeclaration* id = iri->decl; | |
627 assert(id->type->ty == Tclass); | |
628 TypeClass* its = (TypeClass*)id->type; | |
629 | |
630 #if OPAQUE_VTBLS | |
631 const llvm::ArrayType* ivtbl_ty = isaArray(its->ir.vtblType->get()); | |
632 #else | |
633 const llvm::StructType* ivtbl_ty = isaStruct(its->ir.vtblType->get()); | |
634 #endif | |
635 | |
636 // generate interface info initializer | |
637 std::vector<LLConstant*> infoInits; | |
638 | |
639 // classinfo | |
640 assert(id->ir.irStruct->classInfo); | |
641 LLConstant* c = id->ir.irStruct->classInfo; | |
642 infoInits.push_back(c); | |
643 | |
644 // vtbl | |
645 const LLType* byteptrptrty = getPtrToType(getPtrToType(LLType::Int8Ty)); | |
646 c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty); | |
647 c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c); | |
648 infoInits.push_back(c); | |
649 | |
650 // offset | |
651 assert(iri->index >= 0); | |
652 size_t ioff = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(iri->index); | |
653 infoInits.push_back(DtoConstUint(ioff)); | |
654 | |
655 // create interface info initializer constant | |
656 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); | |
657 | |
658 // generate vtable initializer | |
659 std::vector<LLConstant*> iinits; | |
660 | |
661 // add interface info | |
662 #if OPAQUE_VTBLS | |
663 const LLType* targetTy = getVoidPtrType(); | |
664 iinits.push_back(llvm::ConstantExpr::getBitCast(iri->info, targetTy)); | |
665 #else | |
666 iinits.push_back(iri->info); | |
667 #endif | |
668 | |
669 for (int k=1; k < b->vtbl.dim; k++) | |
670 { | |
671 // Logger::println("interface vtbl const init nr. %d", k); | |
672 Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; | |
673 | |
674 // error on unimplemented functions, error was already generated earlier | |
675 if(!dsym) | |
676 fatal(); | |
677 | |
678 FuncDeclaration* fd = dsym->isFuncDeclaration(); | |
679 assert(fd); | |
680 DtoForceDeclareDsymbol(fd); | |
681 assert(fd->ir.irFunc->func); | |
682 LLConstant* c = llvm::cast<llvm::Constant>(fd->ir.irFunc->func); | |
683 | |
684 #if !OPAQUE_VTBLS | |
685 const LLType* targetTy = iri->vtblTy->getContainedType(k); | |
686 #endif | |
687 | |
688 // we have to bitcast, as the type created in ResolveClass expects a different this type | |
689 c = llvm::ConstantExpr::getBitCast(c, targetTy); | |
690 iinits.push_back(c); | |
691 // if (Logger::enabled()) | |
692 // Logger::cout() << "c: " << *c << '\n'; | |
693 } | |
694 | |
695 #if OPAQUE_VTBLS | |
696 // if (Logger::enabled()) | |
697 // Logger::cout() << "n: " << iinits.size() << " ivtbl_ty: " << *ivtbl_ty << '\n'; | |
698 LLConstant* civtblInit = llvm::ConstantArray::get(ivtbl_ty, iinits); | |
699 iri->vtblInit = llvm::cast<llvm::ConstantArray>(civtblInit); | |
700 #else | |
701 LLConstant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); | |
702 iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit); | |
703 #endif | |
704 } | |
705 } | |
706 // we always generate interfaceinfos as best we can | |
707 else | |
708 { | |
709 // TODO: this is duplicated code from right above... I'm just too lazy to generalise it right now :/ | |
710 // create interface vtable const initalizers | |
711 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) | |
712 { | |
713 IrInterface* iri = *i; | |
714 BaseClass* b = iri->base; | |
715 | |
716 ClassDeclaration* id = iri->decl; | |
717 assert(id->type->ty == Tclass); | |
718 TypeClass* its = (TypeClass*)id->type; | |
719 | |
720 // generate interface info initializer | |
721 std::vector<LLConstant*> infoInits; | |
722 | |
723 // classinfo | |
724 assert(id->ir.irStruct->classInfo); | |
725 LLConstant* c = id->ir.irStruct->classInfo; | |
726 infoInits.push_back(c); | |
727 | |
728 // vtbl | |
729 const LLType* byteptrptrty = getPtrToType(getPtrToType(LLType::Int8Ty)); | |
730 c = DtoConstSlice(DtoConstSize_t(0), getNullPtr(byteptrptrty)); | |
731 infoInits.push_back(c); | |
732 | |
733 // offset | |
734 assert(iri->index >= 0); | |
735 size_t ioff = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(iri->index); | |
736 infoInits.push_back(DtoConstUint(ioff)); | |
737 | |
738 // create interface info initializer constant | |
739 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); | |
740 } | |
741 } | |
742 | |
743 gIR->classes.pop_back(); | |
744 gIR->structs.pop_back(); | |
745 } | |
746 | |
747 ////////////////////////////////////////////////////////////////////////////////////////// | |
748 | |
749 void DtoDefineClass(ClassDeclaration* cd) | |
750 { | |
751 if (cd->ir.defined) return; | |
752 cd->ir.defined = true; | |
753 | |
754 Logger::println("DtoDefineClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | |
755 LOG_SCOPE; | |
756 | |
757 // get the struct (class) type | |
758 assert(cd->type->ty == Tclass); | |
759 TypeClass* ts = (TypeClass*)cd->type; | |
760 | |
761 if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) { | |
762 | |
763 // interfaces don't have static initializer/vtable | |
764 // neither do abstract classes | |
765 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) | |
766 { | |
767 cd->ir.irStruct->init->setInitializer(cd->ir.irStruct->constInit); | |
768 cd->ir.irStruct->vtbl->setInitializer(cd->ir.irStruct->constVtbl); | |
769 | |
770 // initialize interface vtables | |
771 IrStruct* irstruct = cd->ir.irStruct; | |
772 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) | |
773 { | |
774 IrInterface* iri = *i; | |
775 iri->vtbl->setInitializer(iri->vtblInit); | |
776 } | |
777 } | |
778 | |
779 // always do interface info array when possible | |
780 IrStruct* irstruct = cd->ir.irStruct; | |
781 std::vector<LLConstant*> infoInits; | |
782 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) | |
783 { | |
784 IrInterface* iri = *i; | |
785 infoInits.push_back(iri->infoInit); | |
786 } | |
787 // set initializer | |
788 if (!infoInits.empty()) | |
789 { | |
790 LLConstant* arrInit = llvm::ConstantArray::get(irstruct->interfaceInfosTy, infoInits); | |
791 irstruct->interfaceInfos->setInitializer(arrInit); | |
792 } | |
793 else | |
794 { | |
795 assert(irstruct->interfaceInfos == NULL); | |
796 } | |
797 | |
798 // generate classinfo | |
799 DtoDefineClassInfo(cd); | |
800 } | |
801 } | 885 } |
802 | 886 |
803 ////////////////////////////////////////////////////////////////////////////////////////// | 887 ////////////////////////////////////////////////////////////////////////////////////////// |
804 | 888 |
805 DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp) | 889 DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp) |
823 } | 907 } |
824 // default allocator | 908 // default allocator |
825 else | 909 else |
826 { | 910 { |
827 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_allocclass"); | 911 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_allocclass"); |
828 mem = gIR->CreateCallOrInvoke(fn, tc->sym->ir.irStruct->classInfo, ".newclass_gc_alloc")->get(); | 912 LLConstant* ci = DtoBitCast(tc->sym->ir.irStruct->classInfo, DtoType(ClassDeclaration::classinfo->type)); |
913 mem = gIR->CreateCallOrInvoke(fn, ci, ".newclass_gc_alloc")->get(); | |
829 mem = DtoBitCast(mem, DtoType(tc), ".newclass_gc"); | 914 mem = DtoBitCast(mem, DtoType(tc), ".newclass_gc"); |
830 } | 915 } |
831 | 916 |
832 // init | 917 // init |
833 DtoInitClass(tc, mem); | 918 DtoInitClass(tc, mem); |
836 if (newexp->thisexp) | 921 if (newexp->thisexp) |
837 { | 922 { |
838 Logger::println("Resolving outer class"); | 923 Logger::println("Resolving outer class"); |
839 LOG_SCOPE; | 924 LOG_SCOPE; |
840 DValue* thisval = newexp->thisexp->toElem(gIR); | 925 DValue* thisval = newexp->thisexp->toElem(gIR); |
841 size_t idx = 2 + tc->sym->vthis->ir.irField->index; | 926 size_t idx = tc->sym->vthis->ir.irField->index; |
842 LLValue* src = thisval->getRVal(); | 927 LLValue* src = thisval->getRVal(); |
843 LLValue* dst = DtoGEPi(mem,0,idx,"tmp"); | 928 LLValue* dst = DtoGEPi(mem,0,idx,"tmp"); |
844 if (Logger::enabled()) | 929 if (Logger::enabled()) |
845 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; | 930 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; |
846 DtoStore(src, dst); | 931 DtoStore(src, dst); |
853 | 938 |
854 // get context | 939 // get context |
855 LLValue* nest = DtoNestedContext(loc, tc->sym); | 940 LLValue* nest = DtoNestedContext(loc, tc->sym); |
856 | 941 |
857 // store into right location | 942 // store into right location |
858 size_t idx = 2 + tc->sym->vthis->ir.irField->index; | 943 size_t idx = tc->sym->vthis->ir.irField->index; |
859 LLValue* gep = DtoGEPi(mem,0,idx,"tmp"); | 944 LLValue* gep = DtoGEPi(mem,0,idx,"tmp"); |
860 DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep); | 945 DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep); |
861 } | 946 } |
862 | 947 |
863 // call constructor | 948 // call constructor |
875 | 960 |
876 ////////////////////////////////////////////////////////////////////////////////////////// | 961 ////////////////////////////////////////////////////////////////////////////////////////// |
877 | 962 |
878 void DtoInitClass(TypeClass* tc, LLValue* dst) | 963 void DtoInitClass(TypeClass* tc, LLValue* dst) |
879 { | 964 { |
965 DtoForceConstInitDsymbol(tc->sym); | |
966 | |
880 size_t presz = 2*getABITypeSize(DtoSize_t()); | 967 size_t presz = 2*getABITypeSize(DtoSize_t()); |
881 uint64_t n = getABITypeSize(tc->ir.type->get()) - presz; | 968 uint64_t n = getABITypeSize(tc->ir.type->get()) - presz; |
882 | 969 |
883 // set vtable field seperately, this might give better optimization | 970 // set vtable field seperately, this might give better optimization |
884 assert(tc->sym->ir.irStruct->vtbl); | 971 assert(tc->sym->ir.irStruct->vtbl); |
885 DtoStore(tc->sym->ir.irStruct->vtbl, DtoGEPi(dst,0,0,"vtbl")); | 972 LLValue* tmp = DtoGEPi(dst,0,0,"vtbl"); |
973 LLValue* val = DtoBitCast(tc->sym->ir.irStruct->vtbl, tmp->getType()->getContainedType(0)); | |
974 DtoStore(val, tmp); | |
886 | 975 |
887 // monitor always defaults to zero | 976 // monitor always defaults to zero |
888 LLValue* tmp = DtoGEPi(dst,0,1,"monitor"); | 977 tmp = DtoGEPi(dst,0,1,"monitor"); |
889 DtoStore(llvm::Constant::getNullValue(tmp->getType()->getContainedType(0)), tmp); | 978 val = llvm::Constant::getNullValue(tmp->getType()->getContainedType(0)); |
979 DtoStore(val, tmp); | |
890 | 980 |
891 // done? | 981 // done? |
892 if (n == 0) | 982 if (n == 0) |
893 return; | 983 return; |
894 | 984 |
895 // copy the rest from the static initializer | 985 // copy the rest from the static initializer |
896 assert(tc->sym->ir.irStruct->init); | 986 assert(tc->sym->ir.irStruct->init); |
897 assert(dst->getType() == tc->sym->ir.irStruct->init->getType()); | |
898 | 987 |
899 LLValue* dstarr = DtoGEPi(dst,0,2,"tmp"); | 988 LLValue* dstarr = DtoGEPi(dst,0,2,"tmp"); |
900 LLValue* srcarr = DtoGEPi(tc->sym->ir.irStruct->init,0,2,"tmp"); | 989 LLValue* srcarr = DtoGEPi(tc->sym->ir.irStruct->init,0,2,"tmp"); |
901 | 990 |
902 DtoMemCpy(dstarr, srcarr, DtoConstSize_t(n)); | 991 DtoMemCpy(dstarr, srcarr, DtoConstSize_t(n)); |
921 { | 1010 { |
922 Logger::println("DtoCastClass(%s, %s)", val->getType()->toChars(), _to->toChars()); | 1011 Logger::println("DtoCastClass(%s, %s)", val->getType()->toChars(), _to->toChars()); |
923 LOG_SCOPE; | 1012 LOG_SCOPE; |
924 | 1013 |
925 Type* to = _to->toBasetype(); | 1014 Type* to = _to->toBasetype(); |
1015 | |
1016 // class -> pointer | |
926 if (to->ty == Tpointer) { | 1017 if (to->ty == Tpointer) { |
927 Logger::println("to pointer"); | 1018 Logger::println("to pointer"); |
928 const LLType* tolltype = DtoType(_to); | 1019 const LLType* tolltype = DtoType(_to); |
929 LLValue* rval = DtoBitCast(val->getRVal(), tolltype); | 1020 LLValue* rval = DtoBitCast(val->getRVal(), tolltype); |
930 return new DImValue(_to, rval); | 1021 return new DImValue(_to, rval); |
931 } | 1022 } |
1023 // class -> bool | |
932 else if (to->ty == Tbool) { | 1024 else if (to->ty == Tbool) { |
933 Logger::println("to bool"); | 1025 Logger::println("to bool"); |
934 LLValue* llval = val->getRVal(); | 1026 LLValue* llval = val->getRVal(); |
935 LLValue* zero = LLConstant::getNullValue(llval->getType()); | 1027 LLValue* zero = LLConstant::getNullValue(llval->getType()); |
936 return new DImValue(_to, gIR->ir->CreateICmpNE(llval, zero, "tmp")); | 1028 return new DImValue(_to, gIR->ir->CreateICmpNE(llval, zero, "tmp")); |
937 } | 1029 } |
938 | 1030 |
1031 // must be class/interface | |
939 assert(to->ty == Tclass); | 1032 assert(to->ty == Tclass); |
940 TypeClass* tc = (TypeClass*)to; | 1033 TypeClass* tc = (TypeClass*)to; |
941 | 1034 |
1035 // from type | |
942 Type* from = val->getType()->toBasetype(); | 1036 Type* from = val->getType()->toBasetype(); |
943 TypeClass* fc = (TypeClass*)from; | 1037 TypeClass* fc = (TypeClass*)from; |
944 | 1038 |
945 if (tc->sym->isInterfaceDeclaration()) { | 1039 // x -> interface |
1040 if (InterfaceDeclaration* it = tc->sym->isInterfaceDeclaration()) { | |
946 Logger::println("to interface"); | 1041 Logger::println("to interface"); |
1042 // interface -> interface | |
947 if (fc->sym->isInterfaceDeclaration()) { | 1043 if (fc->sym->isInterfaceDeclaration()) { |
948 Logger::println("from interface"); | 1044 Logger::println("from interface"); |
949 return DtoDynamicCastInterface(val, _to); | 1045 return DtoDynamicCastInterface(val, _to); |
950 } | 1046 } |
1047 // class -> interface - static cast | |
1048 else if (it->isBaseOf(fc->sym,NULL)) { | |
1049 Logger::println("static down cast)"); | |
1050 // get the from class | |
1051 ClassDeclaration* cd = fc->sym->isClassDeclaration(); | |
1052 IrStruct* irstruct = cd->ir.irStruct; | |
1053 // find interface impl | |
1054 IrStruct::InterfaceMapIter iriter = irstruct->interfaceMap.find(it); | |
1055 assert(iriter != irstruct->interfaceMap.end()); | |
1056 IrInterface* iri = iriter->second; | |
1057 // offset pointer | |
1058 LLValue* v = val->getRVal(); | |
1059 v = DtoGEPi(v, 0, iri->index); | |
1060 if (Logger::enabled()) | |
1061 { | |
1062 Logger::cout() << "V = " << *v << std::endl; | |
1063 Logger::cout() << "T = " << *DtoType(_to) << std::endl; | |
1064 } | |
1065 v = DtoBitCast(v, DtoType(_to)); | |
1066 // return r-value | |
1067 return new DImValue(_to, v); | |
1068 } | |
1069 // class -> interface | |
951 else { | 1070 else { |
952 Logger::println("from object"); | 1071 Logger::println("from object"); |
953 return DtoDynamicCastObject(val, _to); | 1072 return DtoDynamicCastObject(val, _to); |
954 } | 1073 } |
955 } | 1074 } |
1075 // x -> class | |
956 else { | 1076 else { |
957 Logger::println("to class"); | 1077 Logger::println("to class"); |
958 int poffset; | 1078 int poffset; |
1079 // interface -> class | |
959 if (fc->sym->isInterfaceDeclaration()) { | 1080 if (fc->sym->isInterfaceDeclaration()) { |
960 Logger::println("interface cast"); | 1081 Logger::println("interface cast"); |
961 return DtoCastInterfaceToObject(val, _to); | 1082 return DtoCastInterfaceToObject(val, _to); |
962 } | 1083 } |
963 else if (!tc->sym->isInterfaceDeclaration() && tc->sym->isBaseOf(fc->sym,NULL)) { | 1084 // class -> class - static down cast |
1085 else if (tc->sym->isBaseOf(fc->sym,NULL)) { | |
964 Logger::println("static down cast)"); | 1086 Logger::println("static down cast)"); |
965 const LLType* tolltype = DtoType(_to); | 1087 const LLType* tolltype = DtoType(_to); |
966 LLValue* rval = DtoBitCast(val->getRVal(), tolltype); | 1088 LLValue* rval = DtoBitCast(val->getRVal(), tolltype); |
967 return new DImValue(_to, rval); | 1089 return new DImValue(_to, rval); |
968 } | 1090 } |
1091 // class -> class - dynamic up cast | |
969 else { | 1092 else { |
970 Logger::println("dynamic up cast"); | 1093 Logger::println("dynamic up cast"); |
971 return DtoDynamicCastObject(val, _to); | 1094 return DtoDynamicCastObject(val, _to); |
972 } | 1095 } |
973 } | 1096 } |
1098 return (unsigned)-1; | 1221 return (unsigned)-1; |
1099 } | 1222 } |
1100 | 1223 |
1101 ////////////////////////////////////////////////////////////////////////////////////////// | 1224 ////////////////////////////////////////////////////////////////////////////////////////// |
1102 | 1225 |
1103 void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result) | |
1104 { | |
1105 unsigned idx = 0; | |
1106 unsigned r = LLVM_ClassOffsetToIndex(this, os, idx); | |
1107 assert(r != (unsigned)-1 && "Offset not found in any aggregate field"); | |
1108 // vtable is 0, monitor is 1 | |
1109 r += 2; | |
1110 // the final index was not pushed | |
1111 result.push_back(r); | |
1112 } | |
1113 | |
1114 ////////////////////////////////////////////////////////////////////////////////////////// | |
1115 | |
1116 LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd) | 1226 LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd) |
1117 { | 1227 { |
1118 Logger::println("indexing class field %s:", vd->toPrettyChars()); | 1228 Logger::println("indexing class field %s:", vd->toPrettyChars()); |
1119 LOG_SCOPE; | 1229 LOG_SCOPE; |
1120 | 1230 |
1123 | 1233 |
1124 // vd must be a field | 1234 // vd must be a field |
1125 IrField* field = vd->ir.irField; | 1235 IrField* field = vd->ir.irField; |
1126 assert(field); | 1236 assert(field); |
1127 | 1237 |
1128 unsigned idx = field->index + 2; // vtbl & monitor | 1238 // get the start pointer |
1129 unsigned off = field->indexOffset; | |
1130 | |
1131 const LLType* st = DtoType(cd->type); | 1239 const LLType* st = DtoType(cd->type); |
1240 // cast to the struct type | |
1132 src = DtoBitCast(src, st); | 1241 src = DtoBitCast(src, st); |
1133 | 1242 |
1134 LLValue* val = DtoGEPi(src, 0,idx); | 1243 // gep to the index |
1244 if (Logger::enabled()) | |
1245 { | |
1246 Logger::cout() << "src2: " << *src << '\n'; | |
1247 Logger::cout() << "index: " << field->index << '\n'; | |
1248 Logger::cout() << "srctype: " << *src->getType() << '\n'; | |
1249 } | |
1250 LLValue* val = DtoGEPi(src, 0, field->index); | |
1251 | |
1252 // do we need to offset further? (union area) | |
1253 if (field->unionOffset) | |
1254 { | |
1255 // cast to void* | |
1256 val = DtoBitCast(val, getVoidPtrType()); | |
1257 // offset | |
1258 val = DtoGEPi1(val, field->unionOffset); | |
1259 } | |
1260 | |
1261 // cast it to the right type | |
1135 val = DtoBitCast(val, getPtrToType(DtoType(vd->type))); | 1262 val = DtoBitCast(val, getPtrToType(DtoType(vd->type))); |
1136 | |
1137 if (off) | |
1138 val = DtoGEPi1(val, off); | |
1139 | 1263 |
1140 if (Logger::enabled()) | 1264 if (Logger::enabled()) |
1141 Logger::cout() << "value: " << *val << '\n'; | 1265 Logger::cout() << "value: " << *val << '\n'; |
1142 | 1266 |
1143 return val; | 1267 return val; |
1153 | 1277 |
1154 LLValue* vthis = inst->getRVal(); | 1278 LLValue* vthis = inst->getRVal(); |
1155 if (Logger::enabled()) | 1279 if (Logger::enabled()) |
1156 Logger::cout() << "vthis: " << *vthis << '\n'; | 1280 Logger::cout() << "vthis: " << *vthis << '\n'; |
1157 | 1281 |
1158 LLValue* funcval; | 1282 LLValue* funcval = vthis; |
1159 funcval = DtoGEPi(vthis, 0, 0, "tmp"); | 1283 if (!fdecl->isMember2()->isInterfaceDeclaration()) |
1284 funcval = DtoGEPi(funcval, 0, 0, "tmp"); | |
1160 funcval = DtoLoad(funcval); | 1285 funcval = DtoLoad(funcval); |
1161 funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toPrettyChars()); | 1286 funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toPrettyChars()); |
1162 funcval = DtoLoad(funcval); | 1287 funcval = DtoLoad(funcval); |
1163 | 1288 |
1164 if (Logger::enabled()) | 1289 if (Logger::enabled()) |
1165 Logger::cout() << "funcval: " << *funcval << '\n'; | 1290 Logger::cout() << "funcval: " << *funcval << '\n'; |
1166 | 1291 |
1167 #if OPAQUE_VTBLS | |
1168 funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type))); | 1292 funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type))); |
1169 if (Logger::enabled()) | 1293 if (Logger::enabled()) |
1170 Logger::cout() << "funcval casted: " << *funcval << '\n'; | 1294 Logger::cout() << "funcval casted: " << *funcval << '\n'; |
1171 #endif | |
1172 | 1295 |
1173 return funcval; | 1296 return funcval; |
1174 } | 1297 } |
1175 | 1298 |
1176 ////////////////////////////////////////////////////////////////////////////////////////// | 1299 ////////////////////////////////////////////////////////////////////////////////////////// |
1177 | 1300 |
1178 void DtoDeclareClassInfo(ClassDeclaration* cd) | 1301 void DtoDeclareClassInfo(ClassDeclaration* cd) |
1179 { | 1302 { |
1180 if (cd->ir.irStruct->classDeclared) return; | 1303 IrStruct* irstruct = cd->ir.irStruct; |
1181 cd->ir.irStruct->classDeclared = true; | 1304 |
1305 if (irstruct->classInfoDeclared) return; | |
1306 irstruct->classInfoDeclared = true; | |
1182 | 1307 |
1183 Logger::println("DtoDeclareClassInfo(%s)", cd->toChars()); | 1308 Logger::println("DtoDeclareClassInfo(%s)", cd->toChars()); |
1184 LOG_SCOPE; | 1309 LOG_SCOPE; |
1185 | 1310 |
1186 ClassDeclaration* cinfo = ClassDeclaration::classinfo; | 1311 ClassDeclaration* cinfo = ClassDeclaration::classinfo; |
1191 if (!cd->isInterfaceDeclaration()) | 1316 if (!cd->isInterfaceDeclaration()) |
1192 gname.append("7__ClassZ"); | 1317 gname.append("7__ClassZ"); |
1193 else | 1318 else |
1194 gname.append("11__InterfaceZ"); | 1319 gname.append("11__InterfaceZ"); |
1195 | 1320 |
1196 const LLType* st = cinfo->type->ir.type->get(); | 1321 irstruct->classInfo = new llvm::GlobalVariable(irstruct->classInfoOpaque.get(), false, DtoLinkage(cd), NULL, gname, gIR->module); |
1197 | |
1198 cd->ir.irStruct->classInfo = new llvm::GlobalVariable(st, false, DtoLinkage(cd), NULL, gname, gIR->module); | |
1199 } | 1322 } |
1200 | 1323 |
1201 static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd) | 1324 static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd) |
1202 { | 1325 { |
1203 std::vector<const LLType*> types; | 1326 std::vector<const LLType*> types; |
1204 std::vector<LLConstant*> inits; | 1327 std::vector<LLConstant*> inits; |
1205 | 1328 |
1206 types.push_back(DtoSize_t()); | 1329 types.push_back(DtoSize_t()); |
1207 | 1330 |
1208 assert(vd->ir.irField); | 1331 assert(vd->ir.irField); |
1209 assert(vd->ir.irField->index >= 0); | 1332 size_t offset = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(vd->ir.irField->index); |
1210 size_t offset = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(vd->ir.irField->index+2); | 1333 offset += vd->ir.irField->unionOffset; |
1211 inits.push_back(DtoConstSize_t(offset)); | 1334 inits.push_back(DtoConstSize_t(offset)); |
1212 | 1335 |
1213 LLConstant* c = DtoTypeInfoOf(vd->type, true); | 1336 LLConstant* c = DtoTypeInfoOf(vd->type, true); |
1214 const LLType* tiTy = c->getType(); | 1337 const LLType* tiTy = c->getType(); |
1215 //Logger::cout() << "tiTy = " << *tiTy << '\n'; | 1338 //Logger::cout() << "tiTy = " << *tiTy << '\n'; |
1225 { | 1348 { |
1226 const llvm::StructType* initTy = isaStruct(init->getType()); | 1349 const llvm::StructType* initTy = isaStruct(init->getType()); |
1227 assert(initTy); | 1350 assert(initTy); |
1228 | 1351 |
1229 std::vector<LLConstant*> arrayInits; | 1352 std::vector<LLConstant*> arrayInits; |
1230 for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass) | 1353 |
1231 { | 1354 VarDeclaration** fields = &cd->ir.irStruct->varDecls[0]; |
1232 if (cd2->members) | 1355 size_t nvars = cd->ir.irStruct->varDecls.size(); |
1233 { | 1356 |
1234 for (size_t i = 0; i < cd2->members->dim; i++) | 1357 for (size_t i=0; i<nvars; i++) |
1235 { | 1358 { |
1236 Dsymbol *sm = (Dsymbol *)cd2->members->data[i]; | 1359 LLConstant* c = build_offti_entry(cd, fields[i]); |
1237 if (VarDeclaration* vd = sm->isVarDeclaration()) // is this enough? | 1360 assert(c); |
1238 { | 1361 arrayInits.push_back(c); |
1239 if (!vd->isDataseg()) // static members dont have an offset! | |
1240 { | |
1241 LLConstant* c = build_offti_entry(cd, vd); | |
1242 assert(c); | |
1243 arrayInits.push_back(c); | |
1244 } | |
1245 } | |
1246 } | |
1247 } | |
1248 } | 1362 } |
1249 | 1363 |
1250 size_t ninits = arrayInits.size(); | 1364 size_t ninits = arrayInits.size(); |
1251 LLConstant* size = DtoConstSize_t(ninits); | 1365 LLConstant* size = DtoConstSize_t(ninits); |
1252 LLConstant* ptr; | 1366 LLConstant* ptr; |
1334 // void *deallocator; | 1448 // void *deallocator; |
1335 // OffsetTypeInfo[] offTi; | 1449 // OffsetTypeInfo[] offTi; |
1336 // void *defaultConstructor; | 1450 // void *defaultConstructor; |
1337 // } | 1451 // } |
1338 | 1452 |
1339 if (cd->ir.irStruct->classDefined) return; | 1453 IrStruct* ir = cd->ir.irStruct; |
1340 cd->ir.irStruct->classDefined = true; | 1454 |
1455 if (ir->classInfoDefined) return; | |
1456 ir->classInfoDefined = true; | |
1341 | 1457 |
1342 Logger::println("DtoDefineClassInfo(%s)", cd->toChars()); | 1458 Logger::println("DtoDefineClassInfo(%s)", cd->toChars()); |
1343 LOG_SCOPE; | 1459 LOG_SCOPE; |
1344 | 1460 |
1345 assert(cd->type->ty == Tclass); | 1461 assert(cd->type->ty == Tclass); |
1346 assert(cd->ir.irStruct->classInfo); | 1462 assert(ir->classInfo); |
1347 | 1463 |
1348 TypeClass* cdty = (TypeClass*)cd->type; | 1464 TypeClass* cdty = (TypeClass*)cd->type; |
1349 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { | 1465 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
1350 assert(cd->ir.irStruct->init); | 1466 assert(ir->init); |
1351 assert(cd->ir.irStruct->constInit); | 1467 assert(ir->constInit); |
1352 assert(cd->ir.irStruct->vtbl); | 1468 assert(ir->vtbl); |
1353 assert(cd->ir.irStruct->constVtbl); | 1469 assert(ir->constVtbl); |
1354 } | 1470 } |
1355 | 1471 |
1356 // holds the list of initializers for llvm | 1472 // holds the list of initializers for llvm |
1357 std::vector<LLConstant*> inits; | 1473 std::vector<LLConstant*> inits; |
1358 | 1474 |
1379 const LLType* byteptrty = getPtrToType(LLType::Int8Ty); | 1495 const LLType* byteptrty = getPtrToType(LLType::Int8Ty); |
1380 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { | 1496 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1381 c = defc->getOperand(2); | 1497 c = defc->getOperand(2); |
1382 } | 1498 } |
1383 else { | 1499 else { |
1384 c = llvm::ConstantExpr::getBitCast(cd->ir.irStruct->init, byteptrty); | 1500 c = llvm::ConstantExpr::getBitCast(ir->init, byteptrty); |
1385 size_t initsz = getABITypeSize(cd->ir.irStruct->constInit->getType()); | 1501 //Logger::cout() << *ir->constInit->getType() << std::endl; |
1502 size_t initsz = getABITypeSize(ir->constInit->getType()); | |
1386 c = DtoConstSlice(DtoConstSize_t(initsz), c); | 1503 c = DtoConstSlice(DtoConstSize_t(initsz), c); |
1387 } | 1504 } |
1388 inits.push_back(c); | 1505 inits.push_back(c); |
1389 | 1506 |
1390 // class name | 1507 // class name |
1403 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { | 1520 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1404 c = defc->getOperand(4); | 1521 c = defc->getOperand(4); |
1405 } | 1522 } |
1406 else { | 1523 else { |
1407 const LLType* byteptrptrty = getPtrToType(byteptrty); | 1524 const LLType* byteptrptrty = getPtrToType(byteptrty); |
1408 assert(!cd->ir.irStruct->vtbl->getType()->isAbstract()); | |
1409 c = llvm::ConstantExpr::getBitCast(cd->ir.irStruct->vtbl, byteptrptrty); | 1525 c = llvm::ConstantExpr::getBitCast(cd->ir.irStruct->vtbl, byteptrptrty); |
1410 assert(!cd->ir.irStruct->constVtbl->getType()->isAbstract()); | 1526 |
1411 size_t vtblsz = 0; | 1527 assert(ir->constVtbl); |
1412 llvm::ConstantArray* constVtblArray = llvm::dyn_cast<llvm::ConstantArray>(cd->ir.irStruct->constVtbl); | 1528 size_t vtblsz = ir->constVtbl->getNumOperands(); |
1413 if(constVtblArray) { | |
1414 vtblsz = constVtblArray->getType()->getNumElements(); | |
1415 } | |
1416 c = DtoConstSlice(DtoConstSize_t(vtblsz), c); | 1529 c = DtoConstSlice(DtoConstSize_t(vtblsz), c); |
1417 } | 1530 } |
1418 inits.push_back(c); | 1531 inits.push_back(c); |
1419 | 1532 |
1420 // interfaces array | 1533 // interfaces array |
1421 IrStruct* irstruct = cd->ir.irStruct; | 1534 IrStruct* irstruct = cd->ir.irStruct; |
1422 if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) { | 1535 if (!irstruct->interfaceInfos) { |
1423 c = defc->getOperand(5); | 1536 c = defc->getOperand(5); |
1424 } | 1537 } |
1425 else { | 1538 else { |
1426 const LLType* t = defc->getOperand(5)->getType()->getContainedType(1); | 1539 const LLType* t = defc->getOperand(5)->getType()->getContainedType(1); |
1427 c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t); | 1540 c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t); |
1428 size_t iisz = irstruct->interfaceInfosTy->getNumElements(); | 1541 size_t iisz = irstruct->interfaceVec.size(); |
1429 c = DtoConstSlice(DtoConstSize_t(iisz), c); | 1542 c = DtoConstSlice(DtoConstSize_t(iisz), c); |
1430 } | 1543 } |
1431 inits.push_back(c); | 1544 inits.push_back(c); |
1432 | 1545 |
1433 // base classinfo | 1546 // base classinfo |
1519 { | 1632 { |
1520 Logger::cout() << "inits[" << i << "]: " << *inits[i] << '\n'; | 1633 Logger::cout() << "inits[" << i << "]: " << *inits[i] << '\n'; |
1521 }*/ | 1634 }*/ |
1522 | 1635 |
1523 // build the initializer | 1636 // build the initializer |
1524 const llvm::StructType* st = isaStruct(defc->getType()); | 1637 LLConstant* finalinit = llvm::ConstantStruct::get(inits); |
1525 LLConstant* finalinit = llvm::ConstantStruct::get(st, inits); | |
1526 //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n'; | 1638 //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n'; |
1527 | 1639 ir->constClassInfo = finalinit; |
1528 cd->ir.irStruct->constClassInfo = finalinit; | 1640 |
1529 cd->ir.irStruct->classInfo->setInitializer(finalinit); | 1641 // refine the type |
1530 } | 1642 llvm::cast<llvm::OpaqueType>(ir->classInfoOpaque.get())->refineAbstractTypeTo(finalinit->getType()); |
1643 | |
1644 // apply initializer | |
1645 ir->classInfo->setInitializer(finalinit); | |
1646 } |