Mercurial > projects > ldc
comparison gen/classes.cpp @ 137:ce7b81fb957f trunk
[svn r141] fixed more problems with classinfo
moved more IR state out of the AST classes
author | lindquist |
---|---|
date | Fri, 18 Jan 2008 16:42:16 +0100 |
parents | 0e28624814e8 |
children | aeddd4d533b3 |
comparison
equal
deleted
inserted
replaced
136:0e28624814e8 | 137:ce7b81fb957f |
---|---|
18 | 18 |
19 #include "ir/irstruct.h" | 19 #include "ir/irstruct.h" |
20 | 20 |
21 ////////////////////////////////////////////////////////////////////////////////////////// | 21 ////////////////////////////////////////////////////////////////////////////////////////// |
22 | 22 |
23 static void LLVM_AddBaseClassData(BaseClasses* bcs) | 23 static void LLVM_AddBaseClassInterfaces(ClassDeclaration* target, BaseClasses* bcs) |
24 { | 24 { |
25 // add base class data members first | 25 // add base class data members first |
26 for (int j=0; j<bcs->dim; j++) | 26 for (int j=0; j<bcs->dim; j++) |
27 { | 27 { |
28 BaseClass* bc = (BaseClass*)(bcs->data[j]); | 28 BaseClass* bc = (BaseClass*)(bcs->data[j]); |
29 | |
30 // resolve interfaces while we're at it | |
29 if (bc->base->isInterfaceDeclaration()) | 31 if (bc->base->isInterfaceDeclaration()) |
30 continue; // interfaces only have methods | 32 { |
31 | 33 Logger::println("adding interface '%s'", bc->base->toPrettyChars()); |
34 IrInterface* iri = new IrInterface(bc, NULL); | |
35 target->irStruct->interfaces.insert(std::make_pair(bc->base, iri)); | |
36 if (!target->isAbstract()) { | |
37 // Fill in vtbl[] | |
38 bc->fillVtbl(target, &bc->vtbl, 0); | |
39 } | |
40 DtoResolveClass(bc->base); | |
41 } | |
42 | |
43 // base *classes* might add more interfaces? | |
44 LLVM_AddBaseClassInterfaces(target, &bc->base->baseclasses); | |
45 } | |
46 } | |
47 | |
48 ////////////////////////////////////////////////////////////////////////////////////////// | |
49 | |
50 static void LLVM_AddBaseClassData(BaseClasses* bcs) | |
51 { | |
52 // add base class data members first | |
53 for (int j=0; j<bcs->dim; j++) | |
54 { | |
55 BaseClass* bc = (BaseClass*)(bcs->data[j]); | |
56 | |
57 // interfaces never add data fields | |
58 if (bc->base->isInterfaceDeclaration()) | |
59 continue; | |
60 | |
61 // recursively add baseclass data | |
32 LLVM_AddBaseClassData(&bc->base->baseclasses); | 62 LLVM_AddBaseClassData(&bc->base->baseclasses); |
63 | |
64 Array* arr = &bc->base->fields; | |
65 if (arr->dim == 0) | |
66 continue; | |
33 | 67 |
34 Logger::println("Adding base class members of %s", bc->base->toChars()); | 68 Logger::println("Adding base class members of %s", bc->base->toChars()); |
35 LOG_SCOPE; | 69 LOG_SCOPE; |
36 | 70 |
37 Array* arr = &bc->base->fields; | |
38 for (int k=0; k < arr->dim; k++) { | 71 for (int k=0; k < arr->dim; k++) { |
39 VarDeclaration* v = (VarDeclaration*)(arr->data[k]); | 72 VarDeclaration* v = (VarDeclaration*)(arr->data[k]); |
40 v->toObjFile(); | 73 v->toObjFile(); |
41 } | 74 } |
42 } | 75 } |
55 // get the TypeClass | 88 // get the TypeClass |
56 assert(cd->type->ty == Tclass); | 89 assert(cd->type->ty == Tclass); |
57 TypeClass* ts = (TypeClass*)cd->type; | 90 TypeClass* ts = (TypeClass*)cd->type; |
58 | 91 |
59 // make sure the IrStruct is created | 92 // make sure the IrStruct is created |
60 IrStruct* irstruct = cd->llvmIrStruct; | 93 IrStruct* irstruct = cd->irStruct; |
61 if (!irstruct) { | 94 if (!irstruct) { |
62 irstruct = new IrStruct(ts); | 95 irstruct = new IrStruct(ts); |
63 cd->llvmIrStruct = irstruct; | 96 cd->irStruct = irstruct; |
64 } | 97 } |
65 | 98 |
66 // resolve the base class | 99 // resolve the base class |
67 if (cd->baseClass) { | 100 if (cd->baseClass) { |
68 DtoResolveClass(cd->baseClass); | 101 DtoResolveClass(cd->baseClass); |
69 } | 102 } |
70 | 103 |
71 // resolve interface vtables | 104 // resolve interface vtables |
72 if (cd->vtblInterfaces) { | 105 /*if (cd->vtblInterfaces) { |
106 Logger::println("Vtbl interfaces for '%s'", cd->toPrettyChars()); | |
107 LOG_SCOPE; | |
73 for (int i=0; i < cd->vtblInterfaces->dim; i++) { | 108 for (int i=0; i < cd->vtblInterfaces->dim; i++) { |
74 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; | 109 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; |
75 ClassDeclaration *id = b->base; | 110 ClassDeclaration *id = b->base; |
111 Logger::println("Vtbl interface: '%s'", id->toPrettyChars()); | |
76 DtoResolveClass(id); | 112 DtoResolveClass(id); |
77 // Fill in vtbl[] | 113 // Fill in vtbl[] |
78 b->fillVtbl(cd, &b->vtbl, 1); | 114 b->fillVtbl(cd, &b->vtbl, 1); |
79 } | 115 } |
80 } | 116 }*/ |
81 | 117 |
82 gIR->structs.push_back(irstruct); | 118 gIR->structs.push_back(irstruct); |
83 gIR->classes.push_back(cd); | 119 gIR->classes.push_back(cd); |
84 | 120 |
85 // add vtable | 121 // add vtable |
90 fieldtypes.push_back(vtabty); | 126 fieldtypes.push_back(vtabty); |
91 | 127 |
92 // add monitor | 128 // add monitor |
93 fieldtypes.push_back(getPtrToType(llvm::Type::Int8Ty)); | 129 fieldtypes.push_back(getPtrToType(llvm::Type::Int8Ty)); |
94 | 130 |
95 // add interface vtables | 131 // add base class data fields first |
96 if (cd->vtblInterfaces) | |
97 for (size_t i = 0; i < cd->vtblInterfaces->dim; i++) | |
98 { | |
99 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; | |
100 ClassDeclaration *id = b->base; | |
101 assert(id->type->ty == Tclass); | |
102 TypeClass* itc = (TypeClass*)id->type; | |
103 const llvm::Type* ivtblTy = getPtrToType(itc->llvmVtblType->get()); | |
104 fieldtypes.push_back(ivtblTy); | |
105 | |
106 // add this interface to the map | |
107 IrInterface* iri = new IrInterface(b, isaStruct(itc->llvmVtblType->get())); | |
108 irstruct->interfaces.insert(std::make_pair(id, iri)); | |
109 } | |
110 | |
111 // base classes first | |
112 LLVM_AddBaseClassData(&cd->baseclasses); | 132 LLVM_AddBaseClassData(&cd->baseclasses); |
113 | 133 |
114 // then add own members | 134 // then add own members |
115 for (int k=0; k < cd->members->dim; k++) { | 135 for (int k=0; k < cd->members->dim; k++) { |
116 Dsymbol* dsym = (Dsymbol*)(cd->members->data[k]); | 136 Dsymbol* dsym = (Dsymbol*)(cd->members->data[k]); |
147 size_t s = getABITypeSize(i->second.type); | 167 size_t s = getABITypeSize(i->second.type); |
148 if (s > prevsize) { | 168 if (s > prevsize) { |
149 fieldpad += s - prevsize; | 169 fieldpad += s - prevsize; |
150 prevsize = s; | 170 prevsize = s; |
151 } | 171 } |
152 cd->llvmHasUnions = true; | 172 cd->irStruct->hasUnions = true; |
153 i->second.var->irField->index = idx; | 173 i->second.var->irField->index = idx; |
154 } | 174 } |
155 // intersecting offset? | 175 // intersecting offset? |
156 else if (i->first < (lastoffset + prevsize)) { | 176 else if (i->first < (lastoffset + prevsize)) { |
157 size_t s = getABITypeSize(i->second.type); | 177 size_t s = getABITypeSize(i->second.type); |
158 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size | 178 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size |
159 cd->llvmHasUnions = true; | 179 cd->irStruct->hasUnions = true; |
160 i->second.var->irField->index = idx; | 180 i->second.var->irField->index = idx; |
161 i->second.var->irField->indexOffset = (i->first - lastoffset) / s; | 181 i->second.var->irField->indexOffset = (i->first - lastoffset) / s; |
162 } | 182 } |
163 // fresh offset | 183 // fresh offset |
164 else { | 184 else { |
188 fieldtypes.push_back(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad)); | 208 fieldtypes.push_back(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad)); |
189 irstruct->defaultFields.push_back(NULL); | 209 irstruct->defaultFields.push_back(NULL); |
190 } | 210 } |
191 } | 211 } |
192 | 212 |
193 /* | 213 // populate interface map |
194 // add field types | 214 { |
195 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | 215 Logger::println("Adding interfaces to '%s'", cd->toPrettyChars()); |
196 fieldtypes.push_back(i->second.type); | 216 LOG_SCOPE; |
197 } | 217 LLVM_AddBaseClassInterfaces(cd, &cd->baseclasses); |
198 */ | 218 Logger::println("%d interfaces added", cd->irStruct->interfaces.size()); |
199 | 219 } |
220 | |
221 // add interface vtables at the end | |
222 int interIdx = (int)fieldtypes.size(); | |
223 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | |
224 { | |
225 ClassDeclaration* id = i->first; | |
226 IrInterface* iri = i->second; | |
227 | |
228 // set vtbl type | |
229 TypeClass* itc = (TypeClass*)id->type; | |
230 const llvm::Type* ivtblTy = getPtrToType(itc->llvmVtblType->get()); | |
231 fieldtypes.push_back(ivtblTy); | |
232 | |
233 // fix the interface vtable type | |
234 iri->vtblTy = isaStruct(itc->llvmVtblType->get()); | |
235 | |
236 // set index | |
237 iri->index = interIdx++; | |
238 } | |
239 Logger::println("%d interface vtables added", cd->irStruct->interfaces.size()); | |
240 | |
241 // create type | |
200 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); | 242 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); |
243 | |
201 // refine abstract types for stuff like: class C {C next;} | 244 // refine abstract types for stuff like: class C {C next;} |
202 assert(irstruct->recty != 0); | 245 assert(irstruct->recty != 0); |
203 | |
204 llvm::PATypeHolder& spa = irstruct->recty; | 246 llvm::PATypeHolder& spa = irstruct->recty; |
205 llvm::cast<llvm::OpaqueType>(spa.get())->refineAbstractTypeTo(structtype); | 247 llvm::cast<llvm::OpaqueType>(spa.get())->refineAbstractTypeTo(structtype); |
206 structtype = isaStruct(spa.get()); | 248 structtype = isaStruct(spa.get()); |
207 | 249 |
250 // make it official | |
208 if (!ts->llvmType) | 251 if (!ts->llvmType) |
209 ts->llvmType = new llvm::PATypeHolder(structtype); | 252 ts->llvmType = new llvm::PATypeHolder(structtype); |
210 else | 253 else |
211 *ts->llvmType = structtype; | 254 *ts->llvmType = structtype; |
212 spa = *ts->llvmType; | 255 spa = *ts->llvmType; |
213 | 256 |
214 // name the type | 257 // name the type |
215 gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); | 258 gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); |
216 | 259 |
217 // build interface info type | 260 // get interface info type |
218 std::vector<const llvm::Type*> infoTypes; | 261 const llvm::StructType* infoTy = DtoInterfaceInfoType(); |
219 // ClassInfo classinfo | |
220 ClassDeclaration* cinfod = ClassDeclaration::classinfo; | |
221 DtoResolveClass(cinfod); | |
222 infoTypes.push_back(getPtrToType(cinfod->type->llvmType->get())); | |
223 // void*[] vtbl | |
224 std::vector<const llvm::Type*> infoVtbltypes; | |
225 infoVtbltypes.push_back(DtoSize_t()); | |
226 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); | |
227 infoVtbltypes.push_back(byteptrptrty); | |
228 infoTypes.push_back(llvm::StructType::get(infoVtbltypes)); | |
229 // int offset | |
230 infoTypes.push_back(llvm::Type::Int32Ty); | |
231 // create type | |
232 const llvm::StructType* infoTy = llvm::StructType::get(infoTypes); | |
233 | 262 |
234 // create vtable type | 263 // create vtable type |
235 llvm::GlobalVariable* svtblVar = 0; | 264 llvm::GlobalVariable* svtblVar = 0; |
236 std::vector<const llvm::Type*> sinits_ty; | 265 std::vector<const llvm::Type*> sinits_ty; |
237 | 266 |
254 Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars()); | 283 Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars()); |
255 const llvm::Type* cinfoty; | 284 const llvm::Type* cinfoty; |
256 if (cd->isInterfaceDeclaration()) { | 285 if (cd->isInterfaceDeclaration()) { |
257 cinfoty = infoTy; | 286 cinfoty = infoTy; |
258 } | 287 } |
259 else if (cd != cinfod) { | 288 else if (cd != ClassDeclaration::classinfo) { |
260 DtoResolveClass(cinfod); | 289 cinfoty = ClassDeclaration::classinfo->type->llvmType->get(); |
261 cinfoty = cinfod->type->llvmType->get(); | |
262 } | 290 } |
263 else { | 291 else { |
264 // this is the ClassInfo class, the type is this type | 292 // this is the ClassInfo class, the type is this type |
265 cinfoty = ts->llvmType->get(); | 293 cinfoty = ts->llvmType->get(); |
266 } | 294 } |
298 LOG_SCOPE; | 326 LOG_SCOPE; |
299 | 327 |
300 assert(cd->type->ty == Tclass); | 328 assert(cd->type->ty == Tclass); |
301 TypeClass* ts = (TypeClass*)cd->type; | 329 TypeClass* ts = (TypeClass*)cd->type; |
302 | 330 |
303 assert(cd->llvmIrStruct); | 331 assert(cd->irStruct); |
304 IrStruct* irstruct = cd->llvmIrStruct; | 332 IrStruct* irstruct = cd->irStruct; |
305 | 333 |
306 gIR->structs.push_back(irstruct); | 334 gIR->structs.push_back(irstruct); |
307 gIR->classes.push_back(cd); | 335 gIR->classes.push_back(cd); |
308 | 336 |
309 bool needs_definition = false; | 337 bool needs_definition = false; |
320 std::string varname("_D"); | 348 std::string varname("_D"); |
321 varname.append(cd->mangle()); | 349 varname.append(cd->mangle()); |
322 varname.append("6__vtblZ"); | 350 varname.append("6__vtblZ"); |
323 | 351 |
324 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); | 352 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); |
325 cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); | 353 cd->irStruct->vtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); |
326 } | 354 } |
327 | 355 |
328 // get interface info type | 356 // get interface info type |
329 const llvm::StructType* infoTy = DtoInterfaceInfoType(); | 357 const llvm::StructType* infoTy = DtoInterfaceInfoType(); |
330 | 358 |
331 // interface info array | 359 // interface info array |
332 if (cd->vtblInterfaces->dim > 0) { | 360 if (!cd->irStruct->interfaces.empty()) { |
333 // symbol name | 361 // symbol name |
334 std::string nam = "_D"; | 362 std::string nam = "_D"; |
335 nam.append(cd->mangle()); | 363 nam.append(cd->mangle()); |
336 nam.append("16__interfaceInfosZ"); | 364 nam.append("16__interfaceInfosZ"); |
337 // resolve array type | 365 // resolve array type |
338 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->vtblInterfaces->dim); | 366 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->irStruct->interfaces.size()); |
339 // declare global | 367 // declare global |
340 irstruct->interfaceInfosTy = arrTy; | 368 irstruct->interfaceInfosTy = arrTy; |
341 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module); | 369 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module); |
342 } | 370 } |
343 | 371 |
368 std::string initname("_D"); | 396 std::string initname("_D"); |
369 initname.append(cd->mangle()); | 397 initname.append(cd->mangle()); |
370 initname.append("6__initZ"); | 398 initname.append("6__initZ"); |
371 | 399 |
372 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module); | 400 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module); |
373 cd->llvmInit = initvar; | 401 cd->irStruct->init = initvar; |
374 } | 402 } |
375 | 403 |
376 gIR->classes.pop_back(); | 404 gIR->classes.pop_back(); |
377 gIR->structs.pop_back(); | 405 gIR->structs.pop_back(); |
378 | 406 |
399 return; // nothing to do | 427 return; // nothing to do |
400 | 428 |
401 Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | 429 Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); |
402 LOG_SCOPE; | 430 LOG_SCOPE; |
403 | 431 |
404 IrStruct* irstruct = cd->llvmIrStruct; | 432 IrStruct* irstruct = cd->irStruct; |
405 gIR->structs.push_back(irstruct); | 433 gIR->structs.push_back(irstruct); |
406 gIR->classes.push_back(cd); | 434 gIR->classes.push_back(cd); |
407 | 435 |
408 // get the struct (class) type | 436 // get the struct (class) type |
409 assert(cd->type->ty == Tclass); | 437 assert(cd->type->ty == Tclass); |
434 ) | 462 ) |
435 ); | 463 ); |
436 } | 464 } |
437 else | 465 else |
438 { | 466 { |
439 assert(cd->llvmVtbl != 0); | 467 assert(cd->irStruct->vtbl != 0); |
440 fieldinits.push_back(cd->llvmVtbl); | 468 fieldinits.push_back(cd->irStruct->vtbl); |
441 } | 469 } |
442 | 470 |
443 // then comes monitor | 471 // then comes monitor |
444 fieldinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); | 472 fieldinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); |
445 | 473 |
446 size_t dataoffset = 2; | 474 // go through the field inits and build the default initializer |
447 | 475 size_t nfi = irstruct->defaultFields.size(); |
448 // next comes interface vtables | 476 for (size_t i=0; i<nfi; ++i) { |
477 llvm::Constant* c; | |
478 if (irstruct->defaultFields[i]) { | |
479 c = irstruct->defaultFields[i]->irField->constInit; | |
480 assert(c); | |
481 } | |
482 else { | |
483 const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i+2)); | |
484 assert(arrty); | |
485 std::vector<llvm::Constant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); | |
486 c = llvm::ConstantArray::get(arrty, vals); | |
487 } | |
488 fieldinits.push_back(c); | |
489 } | |
490 | |
491 // last comes interface vtables | |
449 const llvm::StructType* infoTy = DtoInterfaceInfoType(); | 492 const llvm::StructType* infoTy = DtoInterfaceInfoType(); |
450 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 493 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) |
451 { | 494 { |
452 IrInterface* iri = i->second; | 495 IrInterface* iri = i->second; |
453 iri->infoTy = infoTy; | 496 iri->infoTy = infoTy; |
454 if (cd->isAbstract()) | 497 if (cd->isAbstract()) |
455 { | 498 { |
456 fieldinits.push_back(llvm::Constant::getNullValue(iri->vtblTy)); | 499 fieldinits.push_back(llvm::Constant::getNullValue(structtype->getElementType(iri->index))); |
457 } | 500 } |
458 else | 501 else |
459 { | 502 { |
460 assert(iri->vtbl); | 503 assert(iri->vtbl); |
461 fieldinits.push_back(iri->vtbl); | 504 fieldinits.push_back(iri->vtbl); |
462 ++dataoffset; | 505 } |
463 } | |
464 } | |
465 | |
466 /* | |
467 // rest | |
468 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | |
469 Logger::println("adding fieldinit for: %s", i->second.var->toChars()); | |
470 fieldinits.push_back(i->second.init); | |
471 } | |
472 */ | |
473 | |
474 // go through the field inits and build the default initializer | |
475 size_t nfi = irstruct->defaultFields.size(); | |
476 for (size_t i=0; i<nfi; ++i) { | |
477 llvm::Constant* c; | |
478 if (irstruct->defaultFields[i] != NULL) { | |
479 c = irstruct->defaultFields[i]->irField->constInit; | |
480 assert(c); | |
481 } | |
482 else { | |
483 const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i+dataoffset)); | |
484 std::vector<llvm::Constant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); | |
485 c = llvm::ConstantArray::get(arrty, vals); | |
486 } | |
487 fieldinits.push_back(c); | |
488 } | 506 } |
489 | 507 |
490 // generate initializer | 508 // generate initializer |
491 #if 0 | 509 #if 0 |
492 Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n'; | 510 //Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n'; |
493 | 511 assert(fieldinits.size() == structtype->getNumElements()); |
494 for(size_t i=0; i<structtype->getNumElements(); ++i) { | 512 for(size_t i=0; i<structtype->getNumElements(); ++i) { |
495 Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n'; | 513 Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n'; |
496 } | 514 Logger::cout() << "i#" << i << " = " << *fieldinits[i] << '\n'; |
497 | 515 assert(fieldinits[i]->getType() == structtype->getElementType(i)); |
516 } | |
517 #endif | |
518 | |
519 #if 0 | |
498 for(size_t i=0; i<fieldinits.size(); ++i) { | 520 for(size_t i=0; i<fieldinits.size(); ++i) { |
499 Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n'; | 521 Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n'; |
500 } | 522 } |
501 #endif | 523 #endif |
502 | 524 |
503 llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits); | 525 llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits); |
504 assert(_init); | 526 assert(_init); |
505 cd->llvmConstInit = _init; | 527 cd->irStruct->constInit = _init; |
506 | 528 |
507 // abstract classes have no static vtable | 529 // abstract classes have no static vtable |
508 if (!cd->isAbstract()) | 530 // neither do interfaces (on their own, the implementing class supplies the vtable) |
531 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) | |
509 { | 532 { |
510 // generate vtable initializer | 533 // generate vtable initializer |
511 std::vector<llvm::Constant*> sinits; | 534 std::vector<llvm::Constant*> sinits; |
512 | 535 |
513 for (int k=0; k < cd->vtbl.dim; k++) | 536 for (int k=0; k < cd->vtbl.dim; k++) |
524 if (c->getType() != vtbltype->getElementType(k)) | 547 if (c->getType() != vtbltype->getElementType(k)) |
525 c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); | 548 c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); |
526 sinits.push_back(c); | 549 sinits.push_back(c); |
527 } | 550 } |
528 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { | 551 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { |
529 assert(cd->llvmClass); | 552 assert(cd->irStruct->classInfo); |
530 llvm::Constant* c = cd->llvmClass; | 553 llvm::Constant* c = cd->irStruct->classInfo; |
531 sinits.push_back(c); | 554 sinits.push_back(c); |
532 } | 555 } |
533 else | 556 else |
534 assert(0); | 557 assert(0); |
535 } | 558 } |
544 assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); | 567 assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); |
545 } | 568 } |
546 #endif | 569 #endif |
547 | 570 |
548 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); | 571 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); |
549 cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); | 572 cd->irStruct->constVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); |
550 | 573 |
551 // create interface vtable const initalizers | 574 // create interface vtable const initalizers |
552 int idx = 2; | |
553 int idxScale = PTRSIZE; | |
554 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 575 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) |
555 { | 576 { |
556 ClassDeclaration* id = i->first; | 577 ClassDeclaration* id = i->first; |
557 assert(id->type->ty == Tclass); | 578 assert(id->type->ty == Tclass); |
558 TypeClass* its = (TypeClass*)id->type; | 579 TypeClass* its = (TypeClass*)id->type; |
564 | 585 |
565 // generate interface info initializer | 586 // generate interface info initializer |
566 std::vector<llvm::Constant*> infoInits; | 587 std::vector<llvm::Constant*> infoInits; |
567 | 588 |
568 // classinfo | 589 // classinfo |
569 assert(id->llvmClass); | 590 assert(id->irStruct->classInfo); |
570 llvm::Constant* c = id->llvmClass; | 591 llvm::Constant* c = id->irStruct->classInfo; |
571 infoInits.push_back(c); | 592 infoInits.push_back(c); |
572 | 593 |
573 // vtbl | 594 // vtbl |
574 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); | 595 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); |
575 c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty); | 596 c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty); |
576 c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c); | 597 c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c); |
577 infoInits.push_back(c); | 598 infoInits.push_back(c); |
578 | 599 |
579 // offset | 600 // offset |
580 infoInits.push_back(DtoConstInt(idx*idxScale)); | 601 // generate target independent offset with constGEP |
602 /*llvm::Value* cidx = DtoConstInt(iri->index); | |
603 Logger::cout() << "offset to interface in class type: " << *cd->type->llvmType->get() << '\n'; | |
604 size_t ioff = gTargetData->getIndexedOffset(cd->type->llvmType->get(), &cidx, 1); | |
605 infoInits.push_back(DtoConstUint(ioff));*/ | |
606 assert(iri->index >= 0); | |
607 size_t ioff = gTargetData->getStructLayout(isaStruct(cd->type->llvmType->get()))->getElementOffset(iri->index); | |
608 infoInits.push_back(DtoConstUint(ioff)); | |
581 | 609 |
582 // create interface info initializer constant | 610 // create interface info initializer constant |
583 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); | 611 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); |
584 | 612 |
585 // generate vtable initializer | 613 // generate vtable initializer |
590 | 618 |
591 for (int k=1; k < b->vtbl.dim; k++) | 619 for (int k=1; k < b->vtbl.dim; k++) |
592 { | 620 { |
593 Logger::println("interface vtbl const init nr. %d", k); | 621 Logger::println("interface vtbl const init nr. %d", k); |
594 Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; | 622 Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; |
623 assert(dsym); | |
595 FuncDeclaration* fd = dsym->isFuncDeclaration(); | 624 FuncDeclaration* fd = dsym->isFuncDeclaration(); |
596 assert(fd); | 625 assert(fd); |
597 DtoForceDeclareDsymbol(fd); | 626 DtoForceDeclareDsymbol(fd); |
598 assert(fd->irFunc->func); | 627 assert(fd->irFunc->func); |
599 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->irFunc->func); | 628 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->irFunc->func); |
601 // we have to bitcast, as the type created in ResolveClass expects a different this type | 630 // we have to bitcast, as the type created in ResolveClass expects a different this type |
602 c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); | 631 c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); |
603 iinits.push_back(c); | 632 iinits.push_back(c); |
604 } | 633 } |
605 | 634 |
606 #if 1 | 635 #if 0 |
607 for (size_t x=0; x< iinits.size(); ++x) | 636 for (size_t x=0; x< iinits.size(); ++x) |
608 { | 637 { |
609 Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n"; | 638 Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n"; |
610 Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n"; | 639 Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n"; |
611 assert(ivtbl_ty->getElementType(x) == iinits[x]->getType()); | 640 assert(ivtbl_ty->getElementType(x) == iinits[x]->getType()); |
612 } | 641 } |
613 #endif | 642 #endif |
614 | 643 |
615 llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); | 644 llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); |
616 iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit); | 645 iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit); |
617 | |
618 idx++; | |
619 } | 646 } |
620 } | 647 } |
621 // we always generate interfaceinfos as best we can | 648 // we always generate interfaceinfos as best we can |
622 else | 649 /*else |
623 { | 650 { |
624 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 651 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) |
625 { | 652 { |
626 ClassDeclaration* id = i->first; | 653 ClassDeclaration* id = i->first; |
627 assert(id->type->ty == Tclass); | 654 assert(id->type->ty == Tclass); |
632 | 659 |
633 // generate interface info initializer | 660 // generate interface info initializer |
634 std::vector<llvm::Constant*> infoInits; | 661 std::vector<llvm::Constant*> infoInits; |
635 | 662 |
636 // classinfo | 663 // classinfo |
637 assert(id->llvmClass); | 664 assert(id->irStruct->classInfo); |
638 llvm::Constant* c = id->llvmClass; | 665 llvm::Constant* c = id->irStruct->classInfo; |
639 infoInits.push_back(c); | 666 infoInits.push_back(c); |
640 | 667 |
641 // vtbl | 668 // vtbl |
642 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); | 669 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); |
643 c = DtoConstSlice(DtoConstSize_t(0), getNullPtr(byteptrptrty)); | 670 c = DtoConstSlice(DtoConstSize_t(0), getNullPtr(byteptrptrty)); |
647 infoInits.push_back(DtoConstInt(0)); | 674 infoInits.push_back(DtoConstInt(0)); |
648 | 675 |
649 // create interface info initializer constant | 676 // create interface info initializer constant |
650 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); | 677 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); |
651 } | 678 } |
652 } | 679 }*/ |
653 | 680 |
654 gIR->classes.pop_back(); | 681 gIR->classes.pop_back(); |
655 gIR->structs.pop_back(); | 682 gIR->structs.pop_back(); |
656 } | 683 } |
657 | 684 |
672 if (cd->getModule() == gIR->dmodule) { | 699 if (cd->getModule() == gIR->dmodule) { |
673 // interfaces don't have initializers | 700 // interfaces don't have initializers |
674 // neither do abstract classes | 701 // neither do abstract classes |
675 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) | 702 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) |
676 { | 703 { |
677 cd->llvmInit->setInitializer(cd->llvmConstInit); | 704 cd->irStruct->init->setInitializer(cd->irStruct->constInit); |
678 cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); | 705 cd->irStruct->vtbl->setInitializer(cd->irStruct->constVtbl); |
679 | 706 |
680 // initialize interface vtables | 707 // initialize interface vtables |
681 IrStruct* irstruct = cd->llvmIrStruct; | 708 IrStruct* irstruct = cd->irStruct; |
682 std::vector<llvm::Constant*> infoInits; | 709 std::vector<llvm::Constant*> infoInits; |
683 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 710 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) |
684 { | 711 { |
685 IrInterface* iri = i->second; | 712 IrInterface* iri = i->second; |
686 iri->vtbl->setInitializer(iri->vtblInit); | 713 iri->vtbl->setInitializer(iri->vtblInit); |
714 } | 741 } |
715 else | 742 else |
716 { | 743 { |
717 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_newclass"); | 744 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_newclass"); |
718 std::vector<llvm::Value*> args; | 745 std::vector<llvm::Value*> args; |
719 args.push_back(tc->sym->llvmClass); | 746 args.push_back(tc->sym->irStruct->classInfo); |
720 mem = gIR->ir->CreateCall(fn, args.begin(), args.end(), "newclass_gc_alloc"); | 747 mem = gIR->ir->CreateCall(fn, args.begin(), args.end(), "newclass_gc_alloc"); |
721 mem = DtoBitCast(mem, DtoType(tc), "newclass_gc"); | 748 mem = DtoBitCast(mem, DtoType(tc), "newclass_gc"); |
722 } | 749 } |
723 | 750 |
724 // init | 751 // init |
729 { | 756 { |
730 Logger::println("Resolving outer class"); | 757 Logger::println("Resolving outer class"); |
731 LOG_SCOPE; | 758 LOG_SCOPE; |
732 DValue* thisval = newexp->thisexp->toElem(gIR); | 759 DValue* thisval = newexp->thisexp->toElem(gIR); |
733 size_t idx = 2; | 760 size_t idx = 2; |
734 idx += tc->sym->llvmIrStruct->interfaces.size(); | 761 idx += tc->sym->irStruct->interfaces.size(); |
735 llvm::Value* dst = thisval->getRVal(); | 762 llvm::Value* dst = thisval->getRVal(); |
736 llvm::Value* src = DtoGEPi(mem,0,idx,"tmp"); | 763 llvm::Value* src = DtoGEPi(mem,0,idx,"tmp"); |
737 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; | 764 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; |
738 DtoStore(dst, src); | 765 DtoStore(dst, src); |
739 } | 766 } |
741 else if (tc->sym->isNested()) | 768 else if (tc->sym->isNested()) |
742 { | 769 { |
743 Logger::println("Resolving nested context"); | 770 Logger::println("Resolving nested context"); |
744 LOG_SCOPE; | 771 LOG_SCOPE; |
745 size_t idx = 2; | 772 size_t idx = 2; |
746 idx += tc->sym->llvmIrStruct->interfaces.size(); | 773 idx += tc->sym->irStruct->interfaces.size(); |
747 llvm::Value* nest = gIR->func()->decl->irFunc->nestedVar; | 774 llvm::Value* nest = gIR->func()->decl->irFunc->nestedVar; |
748 if (!nest) | 775 if (!nest) |
749 nest = gIR->func()->decl->irFunc->thisVar; | 776 nest = gIR->func()->decl->irFunc->thisVar; |
750 assert(nest); | 777 assert(nest); |
751 llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp"); | 778 llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp"); |
767 { | 794 { |
768 size_t presz = 2*getABITypeSize(DtoSize_t()); | 795 size_t presz = 2*getABITypeSize(DtoSize_t()); |
769 uint64_t n = getABITypeSize(tc->llvmType->get()) - presz; | 796 uint64_t n = getABITypeSize(tc->llvmType->get()) - presz; |
770 | 797 |
771 // set vtable field seperately, this might give better optimization | 798 // set vtable field seperately, this might give better optimization |
772 assert(tc->sym->llvmVtbl); | 799 assert(tc->sym->irStruct->vtbl); |
773 DtoStore(tc->sym->llvmVtbl, DtoGEPi(dst,0,0,"vtbl")); | 800 DtoStore(tc->sym->irStruct->vtbl, DtoGEPi(dst,0,0,"vtbl")); |
774 | 801 |
775 // monitor always defaults to zero | 802 // monitor always defaults to zero |
776 llvm::Value* tmp = DtoGEPi(dst,0,1,"monitor"); | 803 llvm::Value* tmp = DtoGEPi(dst,0,1,"monitor"); |
777 DtoStore(llvm::Constant::getNullValue(tmp->getType()->getContainedType(0)), tmp); | 804 DtoStore(llvm::Constant::getNullValue(tmp->getType()->getContainedType(0)), tmp); |
778 | 805 |
779 // done? | 806 // done? |
780 if (n == 0) | 807 if (n == 0) |
781 return; | 808 return; |
782 | 809 |
783 // copy the rest from the static initializer | 810 // copy the rest from the static initializer |
784 assert(tc->sym->llvmInit); | 811 assert(tc->sym->irStruct->init); |
785 assert(dst->getType() == tc->sym->llvmInit->getType()); | 812 assert(dst->getType() == tc->sym->irStruct->init->getType()); |
786 | 813 |
787 const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); | 814 const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); |
788 | 815 |
789 llvm::Value* dstarr = DtoGEPi(dst,0,2,"tmp"); | 816 llvm::Value* dstarr = DtoGEPi(dst,0,2,"tmp"); |
790 dstarr = DtoBitCast(dstarr, arrty); | 817 dstarr = DtoBitCast(dstarr, arrty); |
791 | 818 |
792 llvm::Value* srcarr = DtoGEPi(tc->sym->llvmInit,0,2,"tmp"); | 819 llvm::Value* srcarr = DtoGEPi(tc->sym->irStruct->init,0,2,"tmp"); |
793 srcarr = DtoBitCast(srcarr, arrty); | 820 srcarr = DtoBitCast(srcarr, arrty); |
794 | 821 |
795 llvm::Function* fn = LLVM_DeclareMemCpy32(); | 822 llvm::Function* fn = LLVM_DeclareMemCpy32(); |
796 std::vector<llvm::Value*> llargs; | 823 std::vector<llvm::Value*> llargs; |
797 llargs.resize(4); | 824 llargs.resize(4); |
910 assert(funcTy->getParamType(0) == tmp->getType()); | 937 assert(funcTy->getParamType(0) == tmp->getType()); |
911 | 938 |
912 // ClassInfo c | 939 // ClassInfo c |
913 TypeClass* to = (TypeClass*)DtoDType(_to); | 940 TypeClass* to = (TypeClass*)DtoDType(_to); |
914 DtoForceDeclareDsymbol(to->sym); | 941 DtoForceDeclareDsymbol(to->sym); |
915 assert(to->sym->llvmClass); | 942 assert(to->sym->irStruct->classInfo); |
916 tmp = to->sym->llvmClass; | 943 tmp = to->sym->irStruct->classInfo; |
917 // unfortunately this is needed as the implementation of object differs somehow from the declaration | 944 // unfortunately this is needed as the implementation of object differs somehow from the declaration |
918 // this could happen in user code as well :/ | 945 // this could happen in user code as well :/ |
919 tmp = DtoBitCast(tmp, funcTy->getParamType(1)); | 946 tmp = DtoBitCast(tmp, funcTy->getParamType(1)); |
920 args.push_back(tmp); | 947 args.push_back(tmp); |
921 assert(funcTy->getParamType(1) == tmp->getType()); | 948 assert(funcTy->getParamType(1) == tmp->getType()); |
976 args.push_back(tmp); | 1003 args.push_back(tmp); |
977 | 1004 |
978 // ClassInfo c | 1005 // ClassInfo c |
979 TypeClass* to = (TypeClass*)DtoDType(_to); | 1006 TypeClass* to = (TypeClass*)DtoDType(_to); |
980 DtoForceDeclareDsymbol(to->sym); | 1007 DtoForceDeclareDsymbol(to->sym); |
981 assert(to->sym->llvmClass); | 1008 assert(to->sym->irStruct->classInfo); |
982 tmp = to->sym->llvmClass; | 1009 tmp = to->sym->irStruct->classInfo; |
983 // unfortunately this is needed as the implementation of object differs somehow from the declaration | 1010 // unfortunately this is needed as the implementation of object differs somehow from the declaration |
984 // this could happen in user code as well :/ | 1011 // this could happen in user code as well :/ |
985 tmp = DtoBitCast(tmp, funcTy->getParamType(1)); | 1012 tmp = DtoBitCast(tmp, funcTy->getParamType(1)); |
986 args.push_back(tmp); | 1013 args.push_back(tmp); |
987 | 1014 |
1043 idxs.push_back(0); | 1070 idxs.push_back(0); |
1044 | 1071 |
1045 const llvm::Type* llt = getPtrToType(DtoType(t)); | 1072 const llvm::Type* llt = getPtrToType(DtoType(t)); |
1046 const llvm::Type* st = DtoType(cd->type); | 1073 const llvm::Type* st = DtoType(cd->type); |
1047 if (ptr->getType() != st) { | 1074 if (ptr->getType() != st) { |
1048 assert(cd->llvmHasUnions); | 1075 assert(cd->irStruct->hasUnions); |
1049 ptr = gIR->ir->CreateBitCast(ptr, st, "tmp"); | 1076 ptr = gIR->ir->CreateBitCast(ptr, st, "tmp"); |
1050 } | 1077 } |
1051 | 1078 |
1052 unsigned dataoffset = 2 + cd->vtblInterfaces->dim; | 1079 unsigned dataoffset = 2; |
1053 | 1080 |
1054 IrStruct* irstruct = cd->llvmIrStruct; | 1081 IrStruct* irstruct = cd->irStruct; |
1055 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | 1082 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { |
1056 //for (unsigned i=0; i<cd->fields.dim; ++i) { | 1083 //for (unsigned i=0; i<cd->fields.dim; ++i) { |
1057 //VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i]; | 1084 //VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i]; |
1058 VarDeclaration* vd = i->second.var; | 1085 VarDeclaration* vd = i->second.var; |
1059 assert(vd); | 1086 assert(vd); |
1132 | 1159 |
1133 ////////////////////////////////////////////////////////////////////////////////////////// | 1160 ////////////////////////////////////////////////////////////////////////////////////////// |
1134 | 1161 |
1135 void DtoDeclareClassInfo(ClassDeclaration* cd) | 1162 void DtoDeclareClassInfo(ClassDeclaration* cd) |
1136 { | 1163 { |
1137 if (cd->llvmClassDeclared) return; | 1164 if (cd->irStruct->classDeclared) return; |
1138 cd->llvmClassDeclared = true; | 1165 cd->irStruct->classDeclared = true; |
1139 | 1166 |
1140 Logger::println("DtoDeclareClassInfo(%s)", cd->toChars()); | 1167 Logger::println("DtoDeclareClassInfo(%s)", cd->toChars()); |
1141 LOG_SCOPE; | 1168 LOG_SCOPE; |
1142 | 1169 |
1143 ClassDeclaration* cinfo = ClassDeclaration::classinfo; | 1170 ClassDeclaration* cinfo = ClassDeclaration::classinfo; |
1150 else | 1177 else |
1151 gname.append("11__InterfaceZ"); | 1178 gname.append("11__InterfaceZ"); |
1152 | 1179 |
1153 const llvm::Type* st = cinfo->type->llvmType->get(); | 1180 const llvm::Type* st = cinfo->type->llvmType->get(); |
1154 | 1181 |
1155 cd->llvmClass = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module); | 1182 cd->irStruct->classInfo = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module); |
1156 } | 1183 } |
1157 | 1184 |
1158 static llvm::Constant* build_offti_entry(VarDeclaration* vd) | 1185 static llvm::Constant* build_offti_entry(VarDeclaration* vd) |
1159 { | 1186 { |
1160 std::vector<const llvm::Type*> types; | 1187 std::vector<const llvm::Type*> types; |
1323 // void *deallocator; | 1350 // void *deallocator; |
1324 // OffsetTypeInfo[] offTi; | 1351 // OffsetTypeInfo[] offTi; |
1325 // void *defaultConstructor; | 1352 // void *defaultConstructor; |
1326 // } | 1353 // } |
1327 | 1354 |
1328 if (cd->llvmClassDefined) return; | 1355 if (cd->irStruct->classDefined) return; |
1329 cd->llvmClassDefined = true; | 1356 cd->irStruct->classDefined = true; |
1330 | 1357 |
1331 Logger::println("DtoDefineClassInfo(%s)", cd->toChars()); | 1358 Logger::println("DtoDefineClassInfo(%s)", cd->toChars()); |
1332 LOG_SCOPE; | 1359 LOG_SCOPE; |
1333 | 1360 |
1334 assert(cd->type->ty == Tclass); | 1361 assert(cd->type->ty == Tclass); |
1335 assert(cd->llvmClass); | 1362 assert(cd->irStruct->classInfo); |
1336 | 1363 |
1337 TypeClass* cdty = (TypeClass*)cd->type; | 1364 TypeClass* cdty = (TypeClass*)cd->type; |
1338 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { | 1365 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
1339 assert(cd->llvmInit); | 1366 assert(cd->irStruct->init); |
1340 assert(cd->llvmConstInit); | 1367 assert(cd->irStruct->constInit); |
1341 assert(cd->llvmVtbl); | 1368 assert(cd->irStruct->vtbl); |
1342 assert(cd->llvmConstVtbl); | 1369 assert(cd->irStruct->constVtbl); |
1343 } | 1370 } |
1344 | 1371 |
1345 // holds the list of initializers for llvm | 1372 // holds the list of initializers for llvm |
1346 std::vector<llvm::Constant*> inits; | 1373 std::vector<llvm::Constant*> inits; |
1347 | 1374 |
1348 ClassDeclaration* cinfo = ClassDeclaration::classinfo; | 1375 ClassDeclaration* cinfo = ClassDeclaration::classinfo; |
1349 DtoForceConstInitDsymbol(cinfo); | 1376 DtoForceConstInitDsymbol(cinfo); |
1350 assert(cinfo->llvmConstInit); | 1377 assert(cinfo->irStruct->constInit); |
1351 | 1378 |
1352 llvm::Constant* c; | 1379 llvm::Constant* c; |
1353 | 1380 |
1354 // own vtable | 1381 // own vtable |
1355 c = cinfo->llvmConstInit->getOperand(0); | 1382 c = cinfo->irStruct->constInit->getOperand(0); |
1356 assert(c); | 1383 assert(c); |
1357 inits.push_back(c); | 1384 inits.push_back(c); |
1358 | 1385 |
1359 // monitor | 1386 // monitor |
1360 c = cinfo->llvmConstInit->getOperand(1); | 1387 c = cinfo->irStruct->constInit->getOperand(1); |
1361 inits.push_back(c); | 1388 inits.push_back(c); |
1362 | 1389 |
1363 // byte[] init | 1390 // byte[] init |
1364 const llvm::Type* byteptrty = getPtrToType(llvm::Type::Int8Ty); | 1391 const llvm::Type* byteptrty = getPtrToType(llvm::Type::Int8Ty); |
1365 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { | 1392 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1366 c = cinfo->llvmConstInit->getOperand(2); | 1393 c = cinfo->irStruct->constInit->getOperand(2); |
1367 } | 1394 } |
1368 else { | 1395 else { |
1369 c = llvm::ConstantExpr::getBitCast(cd->llvmInit, byteptrty); | 1396 c = llvm::ConstantExpr::getBitCast(cd->irStruct->init, byteptrty); |
1370 assert(!cd->llvmConstInit->getType()->isAbstract()); | 1397 assert(!cd->irStruct->constInit->getType()->isAbstract()); |
1371 size_t initsz = getABITypeSize(cd->llvmConstInit->getType()); | 1398 size_t initsz = getABITypeSize(cd->irStruct->constInit->getType()); |
1372 c = DtoConstSlice(DtoConstSize_t(initsz), c); | 1399 c = DtoConstSlice(DtoConstSize_t(initsz), c); |
1373 } | 1400 } |
1374 inits.push_back(c); | 1401 inits.push_back(c); |
1375 | 1402 |
1376 // class name | 1403 // class name |
1385 c = DtoConstString(name); | 1412 c = DtoConstString(name); |
1386 inits.push_back(c); | 1413 inits.push_back(c); |
1387 | 1414 |
1388 // vtbl array | 1415 // vtbl array |
1389 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { | 1416 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1390 c = cinfo->llvmConstInit->getOperand(4); | 1417 c = cinfo->irStruct->constInit->getOperand(4); |
1391 } | 1418 } |
1392 else { | 1419 else { |
1393 const llvm::Type* byteptrptrty = getPtrToType(byteptrty); | 1420 const llvm::Type* byteptrptrty = getPtrToType(byteptrty); |
1394 assert(!cd->llvmVtbl->getType()->isAbstract()); | 1421 assert(!cd->irStruct->vtbl->getType()->isAbstract()); |
1395 c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty); | 1422 c = llvm::ConstantExpr::getBitCast(cd->irStruct->vtbl, byteptrptrty); |
1396 assert(!cd->llvmConstVtbl->getType()->isAbstract()); | 1423 assert(!cd->irStruct->constVtbl->getType()->isAbstract()); |
1397 size_t vtblsz = cd->llvmConstVtbl->getType()->getNumElements(); | 1424 size_t vtblsz = cd->irStruct->constVtbl->getType()->getNumElements(); |
1398 c = DtoConstSlice(DtoConstSize_t(vtblsz), c); | 1425 c = DtoConstSlice(DtoConstSize_t(vtblsz), c); |
1399 } | 1426 } |
1400 inits.push_back(c); | 1427 inits.push_back(c); |
1401 | 1428 |
1402 // interfaces array | 1429 // interfaces array |
1403 IrStruct* irstruct = cd->llvmIrStruct; | 1430 IrStruct* irstruct = cd->irStruct; |
1404 if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) { | 1431 if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) { |
1405 c = cinfo->llvmConstInit->getOperand(5); | 1432 c = cinfo->irStruct->constInit->getOperand(5); |
1406 } | 1433 } |
1407 else { | 1434 else { |
1408 const llvm::Type* t = cinfo->llvmConstInit->getOperand(5)->getType()->getContainedType(1); | 1435 const llvm::Type* t = cinfo->irStruct->constInit->getOperand(5)->getType()->getContainedType(1); |
1409 c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t); | 1436 c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t); |
1410 size_t iisz = irstruct->interfaceInfosTy->getNumElements(); | 1437 size_t iisz = irstruct->interfaceInfosTy->getNumElements(); |
1411 c = DtoConstSlice(DtoConstSize_t(iisz), c); | 1438 c = DtoConstSlice(DtoConstSize_t(iisz), c); |
1412 } | 1439 } |
1413 inits.push_back(c); | 1440 inits.push_back(c); |
1414 | 1441 |
1415 // base classinfo | 1442 // base classinfo |
1416 if (cd->baseClass && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { | 1443 if (cd->baseClass && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
1417 DtoDeclareClassInfo(cd->baseClass); | 1444 DtoDeclareClassInfo(cd->baseClass); |
1418 c = cd->baseClass->llvmClass; | 1445 c = cd->baseClass->irStruct->classInfo; |
1419 assert(c); | 1446 assert(c); |
1420 inits.push_back(c); | 1447 inits.push_back(c); |
1421 } | 1448 } |
1422 else { | 1449 else { |
1423 // null | 1450 // null |
1424 c = cinfo->llvmConstInit->getOperand(6); | 1451 c = cinfo->irStruct->constInit->getOperand(6); |
1425 inits.push_back(c); | 1452 inits.push_back(c); |
1426 } | 1453 } |
1427 | 1454 |
1428 // destructor | 1455 // destructor |
1429 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { | 1456 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1430 c = cinfo->llvmConstInit->getOperand(7); | 1457 c = cinfo->irStruct->constInit->getOperand(7); |
1431 } | 1458 } |
1432 else { | 1459 else { |
1433 c = build_class_dtor(cd); | 1460 c = build_class_dtor(cd); |
1434 } | 1461 } |
1435 inits.push_back(c); | 1462 inits.push_back(c); |
1436 | 1463 |
1437 // invariant | 1464 // invariant |
1438 // TODO | 1465 // TODO |
1439 c = cinfo->llvmConstInit->getOperand(8); | 1466 c = cinfo->irStruct->constInit->getOperand(8); |
1440 inits.push_back(c); | 1467 inits.push_back(c); |
1441 | 1468 |
1442 // uint flags | 1469 // uint flags |
1443 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { | 1470 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1444 c = cinfo->llvmConstInit->getOperand(9); | 1471 c = cinfo->irStruct->constInit->getOperand(9); |
1445 } | 1472 } |
1446 else { | 1473 else { |
1447 uint flags = build_classinfo_flags(cd); | 1474 uint flags = build_classinfo_flags(cd); |
1448 c = DtoConstUint(flags); | 1475 c = DtoConstUint(flags); |
1449 } | 1476 } |
1450 inits.push_back(c); | 1477 inits.push_back(c); |
1451 | 1478 |
1452 // allocator | 1479 // allocator |
1453 // TODO | 1480 // TODO |
1454 c = cinfo->llvmConstInit->getOperand(10); | 1481 c = cinfo->irStruct->constInit->getOperand(10); |
1455 inits.push_back(c); | 1482 inits.push_back(c); |
1456 | 1483 |
1457 // offset typeinfo | 1484 // offset typeinfo |
1458 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { | 1485 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1459 c = cinfo->llvmConstInit->getOperand(11); | 1486 c = cinfo->irStruct->constInit->getOperand(11); |
1460 } | 1487 } |
1461 else { | 1488 else { |
1462 c = build_offti_array(cd, cinfo->llvmConstInit->getOperand(11)); | 1489 c = build_offti_array(cd, cinfo->irStruct->constInit->getOperand(11)); |
1463 } | 1490 } |
1464 inits.push_back(c); | 1491 inits.push_back(c); |
1465 | 1492 |
1466 // default constructor | 1493 // default constructor |
1467 if (cd->defaultCtor && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { | 1494 if (cd->defaultCtor && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
1468 DtoForceDeclareDsymbol(cd->defaultCtor); | 1495 DtoForceDeclareDsymbol(cd->defaultCtor); |
1469 c = isaConstant(cd->defaultCtor->irFunc->func); | 1496 c = isaConstant(cd->defaultCtor->irFunc->func); |
1470 const llvm::Type* toTy = cinfo->llvmConstInit->getOperand(12)->getType(); | 1497 const llvm::Type* toTy = cinfo->irStruct->constInit->getOperand(12)->getType(); |
1471 c = llvm::ConstantExpr::getBitCast(c, toTy); | 1498 c = llvm::ConstantExpr::getBitCast(c, toTy); |
1472 } | 1499 } |
1473 else { | 1500 else { |
1474 c = cinfo->llvmConstInit->getOperand(12); | 1501 c = cinfo->irStruct->constInit->getOperand(12); |
1475 } | 1502 } |
1476 inits.push_back(c); | 1503 inits.push_back(c); |
1477 | 1504 |
1478 /*size_t n = inits.size(); | 1505 /*size_t n = inits.size(); |
1479 for (size_t i=0; i<n; ++i) | 1506 for (size_t i=0; i<n; ++i) |
1480 { | 1507 { |
1481 Logger::cout() << "inits[" << i << "]: " << *inits[i] << '\n'; | 1508 Logger::cout() << "inits[" << i << "]: " << *inits[i] << '\n'; |
1482 }*/ | 1509 }*/ |
1483 | 1510 |
1484 // build the initializer | 1511 // build the initializer |
1485 const llvm::StructType* st = isaStruct(cinfo->llvmConstInit->getType()); | 1512 const llvm::StructType* st = isaStruct(cinfo->irStruct->constInit->getType()); |
1486 llvm::Constant* finalinit = llvm::ConstantStruct::get(st, inits); | 1513 llvm::Constant* finalinit = llvm::ConstantStruct::get(st, inits); |
1487 //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n'; | 1514 //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n'; |
1488 | 1515 |
1489 cd->llvmConstClass = finalinit; | 1516 cd->irStruct->constClassInfo = finalinit; |
1490 cd->llvmClass->setInitializer(finalinit); | 1517 cd->irStruct->classInfo->setInitializer(finalinit); |
1491 } | 1518 } |