Mercurial > projects > ldc
comparison gen/classes.cpp @ 133:44a95ac7368a trunk
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
In particular, assertions has been fixed to include file/line info, and much more!
author | lindquist |
---|---|
date | Mon, 14 Jan 2008 05:11:54 +0100 |
parents | 1700239cab2e |
children | 0e28624814e8 |
comparison
equal
deleted
inserted
replaced
132:1700239cab2e | 133:44a95ac7368a |
---|---|
54 void DtoResolveClass(ClassDeclaration* cd) | 54 void DtoResolveClass(ClassDeclaration* cd) |
55 { | 55 { |
56 if (cd->llvmResolved) return; | 56 if (cd->llvmResolved) return; |
57 cd->llvmResolved = true; | 57 cd->llvmResolved = true; |
58 | 58 |
59 // first resolve the base class | 59 Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); |
60 LOG_SCOPE; | |
61 | |
62 // get the TypeClass | |
63 assert(cd->type->ty == Tclass); | |
64 TypeClass* ts = (TypeClass*)cd->type; | |
65 | |
66 // make sure the IRStruct is created | |
67 IRStruct* irstruct = cd->llvmIRStruct; | |
68 if (!irstruct) { | |
69 irstruct = new IRStruct(ts); | |
70 cd->llvmIRStruct = irstruct; | |
71 } | |
72 | |
73 // resolve the base class | |
60 if (cd->baseClass) { | 74 if (cd->baseClass) { |
61 DtoResolveClass(cd->baseClass); | 75 DtoResolveClass(cd->baseClass); |
62 } | 76 } |
63 | 77 |
64 // resolve interfaces | 78 // resolve interfaces |
70 // Fill in vtbl[] | 84 // Fill in vtbl[] |
71 b->fillVtbl(cd, &b->vtbl, 1); | 85 b->fillVtbl(cd, &b->vtbl, 1); |
72 } | 86 } |
73 } | 87 } |
74 | 88 |
75 Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | |
76 LOG_SCOPE; | |
77 | |
78 assert(cd->type->ty == Tclass); | |
79 TypeClass* ts = (TypeClass*)cd->type; | |
80 | |
81 assert(!cd->llvmIRStruct); | |
82 IRStruct* irstruct = new IRStruct(ts); | |
83 cd->llvmIRStruct = irstruct; | |
84 | |
85 gIR->structs.push_back(irstruct); | 89 gIR->structs.push_back(irstruct); |
86 gIR->classes.push_back(cd); | 90 gIR->classes.push_back(cd); |
87 | 91 |
88 // add vtable | 92 // add vtable |
89 ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); | 93 ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); |
90 const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get()); | 94 const llvm::Type* vtabty = getPtrToType(ts->llvmVtblType->get()); |
91 | 95 |
92 std::vector<const llvm::Type*> fieldtypes; | 96 std::vector<const llvm::Type*> fieldtypes; |
93 fieldtypes.push_back(vtabty); | 97 fieldtypes.push_back(vtabty); |
94 | 98 |
95 // add monitor | 99 // add monitor |
96 fieldtypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); | 100 fieldtypes.push_back(getPtrToType(llvm::Type::Int8Ty)); |
97 | 101 |
98 // add interface vtables | 102 // add interface vtables |
99 if (cd->vtblInterfaces) | 103 if (cd->vtblInterfaces) |
100 for (size_t i = 0; i < cd->vtblInterfaces->dim; i++) | 104 for (size_t i = 0; i < cd->vtblInterfaces->dim; i++) |
101 { | 105 { |
102 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; | 106 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; |
103 ClassDeclaration *id = b->base; | 107 ClassDeclaration *id = b->base; |
104 assert(id->type->ty == Tclass); | 108 assert(id->type->ty == Tclass); |
105 TypeClass* itc = (TypeClass*)id->type; | 109 TypeClass* itc = (TypeClass*)id->type; |
106 const llvm::Type* ivtblTy = llvm::PointerType::get(itc->llvmVtblType->get()); | 110 const llvm::Type* ivtblTy = getPtrToType(itc->llvmVtblType->get()); |
107 fieldtypes.push_back(ivtblTy); | 111 fieldtypes.push_back(ivtblTy); |
108 | 112 |
109 // add this interface to the map | 113 // add this interface to the map |
110 IRInterface* iri = new IRInterface(b, isaStruct(itc->llvmVtblType->get())); | 114 IRInterface* iri = new IRInterface(b, isaStruct(itc->llvmVtblType->get())); |
111 irstruct->interfaces.insert(std::make_pair(id, iri)); | 115 irstruct->interfaces.insert(std::make_pair(id, iri)); |
140 // first iteration | 144 // first iteration |
141 if (lastoffset == (unsigned)-1) { | 145 if (lastoffset == (unsigned)-1) { |
142 lastoffset = i->first; | 146 lastoffset = i->first; |
143 fieldtype = i->second.type; | 147 fieldtype = i->second.type; |
144 fieldinit = i->second.var; | 148 fieldinit = i->second.var; |
145 prevsize = gTargetData->getTypeSize(fieldtype); | 149 prevsize = getABITypeSize(fieldtype); |
146 i->second.var->llvmFieldIndex = idx; | 150 i->second.var->llvmFieldIndex = idx; |
147 } | 151 } |
148 // colliding offset? | 152 // colliding offset? |
149 else if (lastoffset == i->first) { | 153 else if (lastoffset == i->first) { |
150 size_t s = gTargetData->getTypeSize(i->second.type); | 154 size_t s = getABITypeSize(i->second.type); |
151 if (s > prevsize) { | 155 if (s > prevsize) { |
152 fieldpad += s - prevsize; | 156 fieldpad += s - prevsize; |
153 prevsize = s; | 157 prevsize = s; |
154 } | 158 } |
155 cd->llvmHasUnions = true; | 159 cd->llvmHasUnions = true; |
156 i->second.var->llvmFieldIndex = idx; | 160 i->second.var->llvmFieldIndex = idx; |
157 } | 161 } |
158 // intersecting offset? | 162 // intersecting offset? |
159 else if (i->first < (lastoffset + prevsize)) { | 163 else if (i->first < (lastoffset + prevsize)) { |
160 size_t s = gTargetData->getTypeSize(i->second.type); | 164 size_t s = getABITypeSize(i->second.type); |
161 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size | 165 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size |
162 cd->llvmHasUnions = true; | 166 cd->llvmHasUnions = true; |
163 i->second.var->llvmFieldIndex = idx; | 167 i->second.var->llvmFieldIndex = idx; |
164 i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s; | 168 i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s; |
165 } | 169 } |
178 | 182 |
179 // start new | 183 // start new |
180 lastoffset = i->first; | 184 lastoffset = i->first; |
181 fieldtype = i->second.type; | 185 fieldtype = i->second.type; |
182 fieldinit = i->second.var; | 186 fieldinit = i->second.var; |
183 prevsize = gTargetData->getTypeSize(fieldtype); | 187 prevsize = getABITypeSize(fieldtype); |
184 i->second.var->llvmFieldIndex = idx; | 188 i->second.var->llvmFieldIndex = idx; |
185 fieldpad = 0; | 189 fieldpad = 0; |
186 } | 190 } |
187 } | 191 } |
188 fieldtypes.push_back(fieldtype); | 192 fieldtypes.push_back(fieldtype); |
210 | 214 |
211 if (!ts->llvmType) | 215 if (!ts->llvmType) |
212 ts->llvmType = new llvm::PATypeHolder(structtype); | 216 ts->llvmType = new llvm::PATypeHolder(structtype); |
213 else | 217 else |
214 *ts->llvmType = structtype; | 218 *ts->llvmType = structtype; |
219 spa = *ts->llvmType; | |
215 | 220 |
216 // name the type | 221 // name the type |
217 gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); | 222 gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); |
218 | 223 |
219 // build interface info type | 224 // build interface info type |
220 std::vector<const llvm::Type*> infoTypes; | 225 std::vector<const llvm::Type*> infoTypes; |
221 // ClassInfo classinfo | 226 // ClassInfo classinfo |
222 ClassDeclaration* cinfod = ClassDeclaration::classinfo; | 227 ClassDeclaration* cinfod = ClassDeclaration::classinfo; |
223 DtoResolveClass(cinfod); | 228 DtoResolveClass(cinfod); |
224 infoTypes.push_back(llvm::PointerType::get(cinfod->type->llvmType->get())); | 229 infoTypes.push_back(getPtrToType(cinfod->type->llvmType->get())); |
225 // void*[] vtbl | 230 // void*[] vtbl |
226 std::vector<const llvm::Type*> infoVtbltypes; | 231 std::vector<const llvm::Type*> infoVtbltypes; |
227 infoVtbltypes.push_back(DtoSize_t()); | 232 infoVtbltypes.push_back(DtoSize_t()); |
228 const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); | 233 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); |
229 infoVtbltypes.push_back(byteptrptrty); | 234 infoVtbltypes.push_back(byteptrptrty); |
230 infoTypes.push_back(llvm::StructType::get(infoVtbltypes)); | 235 infoTypes.push_back(llvm::StructType::get(infoVtbltypes)); |
231 // int offset | 236 // int offset |
232 infoTypes.push_back(llvm::Type::Int32Ty); | 237 infoTypes.push_back(llvm::Type::Int32Ty); |
233 // create type | 238 // create type |
245 | 250 |
246 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { | 251 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { |
247 DtoResolveFunction(fd); | 252 DtoResolveFunction(fd); |
248 //assert(fd->type->ty == Tfunction); | 253 //assert(fd->type->ty == Tfunction); |
249 //TypeFunction* tf = (TypeFunction*)fd->type; | 254 //TypeFunction* tf = (TypeFunction*)fd->type; |
250 //const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get()); | 255 //const llvm::Type* fpty = getPtrToType(tf->llvmType->get()); |
251 const llvm::FunctionType* vfty = DtoBaseFunctionType(fd); | 256 const llvm::FunctionType* vfty = DtoBaseFunctionType(fd); |
252 const llvm::Type* vfpty = llvm::PointerType::get(vfty); | 257 const llvm::Type* vfpty = getPtrToType(vfty); |
253 sinits_ty.push_back(vfpty); | 258 sinits_ty.push_back(vfpty); |
254 } | 259 } |
255 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { | 260 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { |
256 Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars()); | 261 Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars()); |
257 const llvm::Type* cinfoty; | 262 const llvm::Type* cinfoty; |
264 } | 269 } |
265 else { | 270 else { |
266 // this is the ClassInfo class, the type is this type | 271 // this is the ClassInfo class, the type is this type |
267 cinfoty = ts->llvmType->get(); | 272 cinfoty = ts->llvmType->get(); |
268 } | 273 } |
269 const llvm::Type* cty = llvm::PointerType::get(cinfoty); | 274 const llvm::Type* cty = getPtrToType(cinfoty); |
270 sinits_ty.push_back(cty); | 275 sinits_ty.push_back(cty); |
271 } | 276 } |
272 else | 277 else |
273 assert(0); | 278 assert(0); |
274 } | 279 } |
312 if (cd->getModule() == gIR->dmodule) { | 317 if (cd->getModule() == gIR->dmodule) { |
313 needs_definition = true; | 318 needs_definition = true; |
314 } | 319 } |
315 | 320 |
316 // interface vtables are emitted by the class implementing them | 321 // interface vtables are emitted by the class implementing them |
317 // also interfaces have no static initializer | 322 // also, interfaces have no static initializer |
318 if (!cd->isInterfaceDeclaration()) { | 323 // also, abstract classes have no vtable |
324 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { | |
319 // vtable | 325 // vtable |
320 std::string varname("_D"); | 326 std::string varname("_D"); |
321 varname.append(cd->mangle()); | 327 varname.append(cd->mangle()); |
322 varname.append("6__vtblZ"); | 328 varname.append("6__vtblZ"); |
323 | 329 |
329 // build interface info type | 335 // build interface info type |
330 std::vector<const llvm::Type*> types; | 336 std::vector<const llvm::Type*> types; |
331 // ClassInfo classinfo | 337 // ClassInfo classinfo |
332 ClassDeclaration* cd2 = ClassDeclaration::classinfo; | 338 ClassDeclaration* cd2 = ClassDeclaration::classinfo; |
333 DtoResolveClass(cd2); | 339 DtoResolveClass(cd2); |
334 types.push_back(llvm::PointerType::get(cd2->type->llvmType->get())); | 340 types.push_back(getPtrToType(cd2->type->llvmType->get())); |
335 // void*[] vtbl | 341 // void*[] vtbl |
336 std::vector<const llvm::Type*> vtbltypes; | 342 std::vector<const llvm::Type*> vtbltypes; |
337 vtbltypes.push_back(DtoSize_t()); | 343 vtbltypes.push_back(DtoSize_t()); |
338 const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); | 344 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); |
339 vtbltypes.push_back(byteptrptrty); | 345 vtbltypes.push_back(byteptrptrty); |
340 types.push_back(llvm::StructType::get(vtbltypes)); | 346 types.push_back(llvm::StructType::get(vtbltypes)); |
341 // int offset | 347 // int offset |
342 types.push_back(llvm::Type::Int32Ty); | 348 types.push_back(llvm::Type::Int32Ty); |
343 // create type | 349 // create type |
416 | 422 |
417 IRStruct* irstruct = cd->llvmIRStruct; | 423 IRStruct* irstruct = cd->llvmIRStruct; |
418 gIR->structs.push_back(irstruct); | 424 gIR->structs.push_back(irstruct); |
419 gIR->classes.push_back(cd); | 425 gIR->classes.push_back(cd); |
420 | 426 |
427 // get the struct (class) type | |
428 assert(cd->type->ty == Tclass); | |
429 TypeClass* ts = (TypeClass*)cd->type; | |
430 const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); | |
431 const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get()); | |
432 | |
421 // make sure each offset knows its default initializer | 433 // make sure each offset knows its default initializer |
422 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) | 434 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) |
423 { | 435 { |
424 IRStruct::Offset* so = &i->second; | 436 IRStruct::Offset* so = &i->second; |
425 llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init); | 437 llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init); |
429 | 441 |
430 // fill out fieldtypes/inits | 442 // fill out fieldtypes/inits |
431 std::vector<llvm::Constant*> fieldinits; | 443 std::vector<llvm::Constant*> fieldinits; |
432 | 444 |
433 // first field is always the vtable | 445 // first field is always the vtable |
434 assert(cd->llvmVtbl != 0); | 446 if (cd->isAbstract()) |
435 fieldinits.push_back(cd->llvmVtbl); | 447 { |
448 fieldinits.push_back( | |
449 llvm::ConstantPointerNull::get( | |
450 getPtrToType( | |
451 ts->llvmVtblType->get() | |
452 ) | |
453 ) | |
454 ); | |
455 } | |
456 else | |
457 { | |
458 assert(cd->llvmVtbl != 0); | |
459 fieldinits.push_back(cd->llvmVtbl); | |
460 } | |
436 | 461 |
437 // then comes monitor | 462 // then comes monitor |
438 fieldinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); | 463 fieldinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); |
439 | 464 |
440 size_t dataoffset = 2; | 465 size_t dataoffset = 2; |
441 | 466 |
442 // next comes interface vtables | 467 // next comes interface vtables |
443 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 468 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) |
444 { | 469 { |
445 IRInterface* iri = i->second; | 470 IRInterface* iri = i->second; |
446 assert(iri->vtbl); | 471 if (cd->isAbstract()) |
447 fieldinits.push_back(iri->vtbl); | 472 { |
448 ++dataoffset; | 473 fieldinits.push_back(llvm::Constant::getNullValue(iri->vtblTy)); |
474 } | |
475 else | |
476 { | |
477 assert(iri->vtbl); | |
478 fieldinits.push_back(iri->vtbl); | |
479 ++dataoffset; | |
480 } | |
449 } | 481 } |
450 | 482 |
451 /* | 483 /* |
452 // rest | 484 // rest |
453 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | 485 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { |
454 Logger::println("adding fieldinit for: %s", i->second.var->toChars()); | 486 Logger::println("adding fieldinit for: %s", i->second.var->toChars()); |
455 fieldinits.push_back(i->second.init); | 487 fieldinits.push_back(i->second.init); |
456 } | 488 } |
457 */ | 489 */ |
458 | |
459 // get the struct (class) type | |
460 assert(cd->type->ty == Tclass); | |
461 TypeClass* ts = (TypeClass*)cd->type; | |
462 const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); | |
463 const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get()); | |
464 | 490 |
465 // go through the field inits and build the default initializer | 491 // go through the field inits and build the default initializer |
466 size_t nfi = irstruct->defaultFields.size(); | 492 size_t nfi = irstruct->defaultFields.size(); |
467 for (size_t i=0; i<nfi; ++i) { | 493 for (size_t i=0; i<nfi; ++i) { |
468 llvm::Constant* c; | 494 llvm::Constant* c; |
493 | 519 |
494 llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits); | 520 llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits); |
495 assert(_init); | 521 assert(_init); |
496 cd->llvmConstInit = _init; | 522 cd->llvmConstInit = _init; |
497 | 523 |
498 // generate vtable initializer | 524 // abstract classes have no static vtable |
499 std::vector<llvm::Constant*> sinits; | 525 if (!cd->isAbstract()) |
500 | 526 { |
501 for (int k=0; k < cd->vtbl.dim; k++) | 527 // generate vtable initializer |
502 { | 528 std::vector<llvm::Constant*> sinits; |
503 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; | 529 |
504 assert(dsym); | 530 for (int k=0; k < cd->vtbl.dim; k++) |
505 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; | 531 { |
506 | 532 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; |
507 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { | 533 assert(dsym); |
508 DtoForceDeclareDsymbol(fd); | 534 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; |
509 assert(fd->llvmValue); | 535 |
510 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); | 536 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { |
511 // cast if necessary (overridden method) | 537 DtoForceDeclareDsymbol(fd); |
512 if (c->getType() != vtbltype->getElementType(k)) | 538 assert(fd->llvmValue); |
513 c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); | 539 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); |
514 sinits.push_back(c); | 540 // cast if necessary (overridden method) |
515 } | 541 if (c->getType() != vtbltype->getElementType(k)) |
516 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { | 542 c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); |
517 assert(cd->llvmClass); | 543 sinits.push_back(c); |
518 llvm::Constant* c = cd->llvmClass; | 544 } |
519 sinits.push_back(c); | 545 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { |
520 } | 546 assert(cd->llvmClass); |
521 else | 547 llvm::Constant* c = cd->llvmClass; |
522 assert(0); | 548 sinits.push_back(c); |
523 } | 549 } |
524 | 550 else |
525 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); | 551 assert(0); |
552 } | |
553 | |
554 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); | |
526 | 555 |
527 #if 0 | 556 #if 0 |
528 for (size_t i=0; i< sinits.size(); ++i) | 557 for (size_t i=0; i< sinits.size(); ++i) |
529 { | 558 { |
530 Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n'; | 559 Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n'; |
531 Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n'; | 560 Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n'; |
532 assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); | 561 assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); |
533 } | 562 } |
534 #endif | 563 #endif |
535 | 564 |
536 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); | 565 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); |
537 cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); | 566 cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); |
538 | 567 |
539 // create interface vtable const initalizers | 568 // create interface vtable const initalizers |
540 int idx = 2; | 569 int idx = 2; |
541 int idxScale = PTRSIZE; | 570 int idxScale = PTRSIZE; |
542 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 571 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) |
543 { | |
544 ClassDeclaration* id = i->first; | |
545 assert(id->type->ty == Tclass); | |
546 TypeClass* its = (TypeClass*)id->type; | |
547 | |
548 IRInterface* iri = i->second; | |
549 BaseClass* b = iri->base; | |
550 | |
551 const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get()); | |
552 | |
553 // generate interface info initializer | |
554 std::vector<llvm::Constant*> infoInits; | |
555 // classinfo | |
556 assert(id->llvmClass); | |
557 llvm::Constant* c = id->llvmClass; | |
558 infoInits.push_back(c); | |
559 // vtbl | |
560 const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); | |
561 c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty); | |
562 c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c); | |
563 infoInits.push_back(c); | |
564 // offset | |
565 infoInits.push_back(DtoConstInt(idx*idxScale)); | |
566 // create interface info initializer constant | |
567 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); | |
568 | |
569 // generate vtable initializer | |
570 std::vector<llvm::Constant*> iinits; | |
571 | |
572 // add interface info | |
573 iinits.push_back(iri->info); | |
574 | |
575 for (int k=1; k < b->vtbl.dim; k++) | |
576 { | 572 { |
577 Logger::println("interface vtbl const init nr. %d", k); | 573 ClassDeclaration* id = i->first; |
578 Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; | 574 assert(id->type->ty == Tclass); |
579 FuncDeclaration* fd = dsym->isFuncDeclaration(); | 575 TypeClass* its = (TypeClass*)id->type; |
580 assert(fd); | 576 |
581 DtoForceDeclareDsymbol(fd); | 577 IRInterface* iri = i->second; |
582 assert(fd->llvmValue); | 578 BaseClass* b = iri->base; |
583 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); | 579 |
584 // we have to bitcast, as the type created in ResolveClass expects a different this type | 580 const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get()); |
585 c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); | 581 |
586 iinits.push_back(c); | 582 // generate interface info initializer |
587 } | 583 std::vector<llvm::Constant*> infoInits; |
588 | 584 // classinfo |
589 #if 1 | 585 assert(id->llvmClass); |
590 for (size_t x=0; x< iinits.size(); ++x) | 586 llvm::Constant* c = id->llvmClass; |
591 { | 587 infoInits.push_back(c); |
592 Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n"; | 588 // vtbl |
593 Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n"; | 589 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); |
594 assert(ivtbl_ty->getElementType(x) == iinits[x]->getType()); | 590 c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty); |
595 } | 591 c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c); |
596 #endif | 592 infoInits.push_back(c); |
597 | 593 // offset |
598 llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); | 594 infoInits.push_back(DtoConstInt(idx*idxScale)); |
599 iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit); | 595 // create interface info initializer constant |
600 | 596 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); |
601 idx++; | 597 |
602 } | 598 // generate vtable initializer |
599 std::vector<llvm::Constant*> iinits; | |
600 | |
601 // add interface info | |
602 iinits.push_back(iri->info); | |
603 | |
604 for (int k=1; k < b->vtbl.dim; k++) | |
605 { | |
606 Logger::println("interface vtbl const init nr. %d", k); | |
607 Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; | |
608 FuncDeclaration* fd = dsym->isFuncDeclaration(); | |
609 assert(fd); | |
610 DtoForceDeclareDsymbol(fd); | |
611 assert(fd->llvmValue); | |
612 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); | |
613 // we have to bitcast, as the type created in ResolveClass expects a different this type | |
614 c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); | |
615 iinits.push_back(c); | |
616 } | |
617 | |
618 #if 1 | |
619 for (size_t x=0; x< iinits.size(); ++x) | |
620 { | |
621 Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n"; | |
622 Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n"; | |
623 assert(ivtbl_ty->getElementType(x) == iinits[x]->getType()); | |
624 } | |
625 #endif | |
626 | |
627 llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); | |
628 iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit); | |
629 | |
630 idx++; | |
631 } | |
632 } // !abstract | |
603 | 633 |
604 gIR->classes.pop_back(); | 634 gIR->classes.pop_back(); |
605 gIR->structs.pop_back(); | 635 gIR->structs.pop_back(); |
606 } | 636 } |
607 | 637 |
619 assert(cd->type->ty == Tclass); | 649 assert(cd->type->ty == Tclass); |
620 TypeClass* ts = (TypeClass*)cd->type; | 650 TypeClass* ts = (TypeClass*)cd->type; |
621 | 651 |
622 if (cd->getModule() == gIR->dmodule) { | 652 if (cd->getModule() == gIR->dmodule) { |
623 // interfaces don't have initializers | 653 // interfaces don't have initializers |
624 if (!cd->isInterfaceDeclaration()) { | 654 // neither do abstract classes |
655 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) | |
656 { | |
625 cd->llvmInit->setInitializer(cd->llvmConstInit); | 657 cd->llvmInit->setInitializer(cd->llvmConstInit); |
626 cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); | 658 cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); |
627 | 659 |
628 // initialize interface vtables | 660 // initialize interface vtables |
629 IRStruct* irstruct = cd->llvmIRStruct; | 661 IRStruct* irstruct = cd->llvmIRStruct; |
633 IRInterface* iri = i->second; | 665 IRInterface* iri = i->second; |
634 iri->vtbl->setInitializer(iri->vtblInit); | 666 iri->vtbl->setInitializer(iri->vtblInit); |
635 infoInits.push_back(iri->infoInit); | 667 infoInits.push_back(iri->infoInit); |
636 } | 668 } |
637 // initialize interface info array | 669 // initialize interface info array |
638 if (!infoInits.empty()) { | 670 if (!infoInits.empty()) |
671 { | |
639 llvm::Constant* arrInit = llvm::ConstantArray::get(irstruct->interfaceInfosTy, infoInits); | 672 llvm::Constant* arrInit = llvm::ConstantArray::get(irstruct->interfaceInfosTy, infoInits); |
640 irstruct->interfaceInfos->setInitializer(arrInit); | 673 irstruct->interfaceInfos->setInitializer(arrInit); |
641 } | 674 } |
642 } | 675 } |
643 | 676 |
644 // generate classinfo | 677 // generate classinfo |
645 DtoDefineClassInfo(cd); | 678 DtoDefineClassInfo(cd); |
646 } | 679 } |
680 } | |
681 | |
682 ////////////////////////////////////////////////////////////////////////////////////////// | |
683 | |
684 DValue* DtoNewClass(TypeClass* tc, NewExp* newexp) | |
685 { | |
686 // resolve type | |
687 DtoForceDeclareDsymbol(tc->sym); | |
688 | |
689 // allocate | |
690 llvm::Value* mem; | |
691 if (newexp->onstack) | |
692 { | |
693 mem = new llvm::AllocaInst(DtoType(tc)->getContainedType(0), "newclass_alloca", gIR->topallocapoint()); | |
694 } | |
695 else | |
696 { | |
697 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_newclass"); | |
698 std::vector<llvm::Value*> args; | |
699 args.push_back(tc->sym->llvmClass); | |
700 mem = gIR->ir->CreateCall(fn, args.begin(), args.end(), "newclass_gc_alloc"); | |
701 mem = DtoBitCast(mem, DtoType(tc), "newclass_gc"); | |
702 } | |
703 | |
704 // init | |
705 DtoInitClass(tc, mem); | |
706 | |
707 // init inner-class outer reference | |
708 if (newexp->thisexp) | |
709 { | |
710 Logger::println("Resolving outer class"); | |
711 LOG_SCOPE; | |
712 DValue* thisval = newexp->thisexp->toElem(gIR); | |
713 size_t idx = 2; | |
714 idx += tc->sym->llvmIRStruct->interfaces.size(); | |
715 llvm::Value* dst = thisval->getRVal(); | |
716 llvm::Value* src = DtoGEPi(mem,0,idx,"tmp"); | |
717 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; | |
718 DtoStore(dst, src); | |
719 } | |
720 // set the context for nested classes | |
721 else if (tc->sym->isNested()) | |
722 { | |
723 Logger::println("Resolving nested context"); | |
724 LOG_SCOPE; | |
725 size_t idx = 2; | |
726 idx += tc->sym->llvmIRStruct->interfaces.size(); | |
727 llvm::Value* nest = gIR->func()->decl->llvmNested; | |
728 if (!nest) | |
729 nest = gIR->func()->decl->llvmThisVar; | |
730 assert(nest); | |
731 llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp"); | |
732 nest = DtoBitCast(nest, gep->getType()->getContainedType(0)); | |
733 DtoStore(nest, gep); | |
734 } | |
735 | |
736 // call constructor | |
737 if (newexp->arguments) | |
738 return DtoCallClassCtor(tc, newexp->member, newexp->arguments, mem); | |
739 | |
740 // return default constructed class | |
741 return new DImValue(tc, mem, false); | |
742 } | |
743 | |
744 ////////////////////////////////////////////////////////////////////////////////////////// | |
745 | |
746 void DtoInitClass(TypeClass* tc, llvm::Value* dst) | |
747 { | |
748 size_t presz = 2*getABITypeSize(DtoSize_t()); | |
749 uint64_t n = getABITypeSize(tc->llvmType->get()) - presz; | |
750 | |
751 // set vtable field seperately, this might give better optimization | |
752 assert(tc->sym->llvmVtbl); | |
753 DtoStore(tc->sym->llvmVtbl, DtoGEPi(dst,0,0,"vtbl")); | |
754 | |
755 // monitor always defaults to zero | |
756 llvm::Value* tmp = DtoGEPi(dst,0,1,"monitor"); | |
757 DtoStore(llvm::Constant::getNullValue(tmp->getType()->getContainedType(0)), tmp); | |
758 | |
759 // done? | |
760 if (n == 0) | |
761 return; | |
762 | |
763 // copy the rest from the static initializer | |
764 assert(tc->sym->llvmInit); | |
765 assert(dst->getType() == tc->sym->llvmInit->getType()); | |
766 | |
767 const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); | |
768 | |
769 llvm::Value* dstarr = DtoGEPi(dst,0,2,"tmp"); | |
770 dstarr = DtoBitCast(dstarr, arrty); | |
771 | |
772 llvm::Value* srcarr = DtoGEPi(tc->sym->llvmInit,0,2,"tmp"); | |
773 srcarr = DtoBitCast(srcarr, arrty); | |
774 | |
775 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
776 std::vector<llvm::Value*> llargs; | |
777 llargs.resize(4); | |
778 llargs[0] = dstarr; | |
779 llargs[1] = srcarr; | |
780 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
781 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
782 | |
783 new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
784 } | |
785 | |
786 ////////////////////////////////////////////////////////////////////////////////////////// | |
787 | |
788 DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, llvm::Value* mem) | |
789 { | |
790 Logger::println("Calling constructor"); | |
791 LOG_SCOPE; | |
792 | |
793 assert(ctor); | |
794 DtoForceDeclareDsymbol(ctor); | |
795 llvm::Function* fn = llvm::cast<llvm::Function>(ctor->llvmValue); | |
796 TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type); | |
797 | |
798 std::vector<llvm::Value*> ctorargs; | |
799 ctorargs.push_back(mem); | |
800 for (size_t i=0; i<arguments->dim; ++i) | |
801 { | |
802 Expression* ex = (Expression*)arguments->data[i]; | |
803 Argument* fnarg = Argument::getNth(tf->parameters, i); | |
804 DValue* argval = DtoArgument(fnarg, ex); | |
805 llvm::Value* a = argval->getRVal(); | |
806 const llvm::Type* aty = fn->getFunctionType()->getParamType(i+1); | |
807 if (a->getType() != aty) | |
808 a = DtoBitCast(a, aty); | |
809 ctorargs.push_back(a); | |
810 } | |
811 llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", gIR->scopebb()); | |
812 call->setCallingConv(DtoCallingConv(LINKd)); | |
813 | |
814 return new DImValue(type, call, false); | |
647 } | 815 } |
648 | 816 |
649 ////////////////////////////////////////////////////////////////////////////////////////// | 817 ////////////////////////////////////////////////////////////////////////////////////////// |
650 | 818 |
651 void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance) | 819 void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance) |
654 for (size_t i=0; i<arr->dim; i++) | 822 for (size_t i=0; i<arr->dim; i++) |
655 { | 823 { |
656 FuncDeclaration* fd = (FuncDeclaration*)arr->data[i]; | 824 FuncDeclaration* fd = (FuncDeclaration*)arr->data[i]; |
657 assert(fd->llvmValue); | 825 assert(fd->llvmValue); |
658 new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb()); | 826 new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb()); |
659 } | |
660 } | |
661 | |
662 ////////////////////////////////////////////////////////////////////////////////////////// | |
663 | |
664 void DtoInitClass(TypeClass* tc, llvm::Value* dst) | |
665 { | |
666 assert(gIR); | |
667 | |
668 assert(tc->llvmType); | |
669 uint64_t size_t_size = gTargetData->getTypeSize(DtoSize_t()); | |
670 uint64_t n = gTargetData->getTypeSize(tc->llvmType->get()) - size_t_size; | |
671 | |
672 // set vtable field | |
673 llvm::Value* vtblvar = DtoGEPi(dst,0,0,"tmp",gIR->scopebb()); | |
674 assert(tc->sym->llvmVtbl); | |
675 new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb()); | |
676 | |
677 // copy the static initializer | |
678 if (n > 0) { | |
679 assert(tc->sym->llvmInit); | |
680 assert(dst->getType() == tc->sym->llvmInit->getType()); | |
681 | |
682 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
683 | |
684 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
685 dstarr = DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb()); | |
686 | |
687 llvm::Value* srcarr = new llvm::BitCastInst(tc->sym->llvmInit,arrty,"tmp",gIR->scopebb()); | |
688 srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb()); | |
689 | |
690 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
691 std::vector<llvm::Value*> llargs; | |
692 llargs.resize(4); | |
693 llargs[0] = dstarr; | |
694 llargs[1] = srcarr; | |
695 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
696 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
697 | |
698 new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
699 } | 827 } |
700 } | 828 } |
701 | 829 |
702 ////////////////////////////////////////////////////////////////////////////////////////// | 830 ////////////////////////////////////////////////////////////////////////////////////////// |
703 | 831 |
715 | 843 |
716 Type* from = DtoDType(val->getType()); | 844 Type* from = DtoDType(val->getType()); |
717 TypeClass* fc = (TypeClass*)from; | 845 TypeClass* fc = (TypeClass*)from; |
718 | 846 |
719 if (tc->sym->isInterfaceDeclaration()) { | 847 if (tc->sym->isInterfaceDeclaration()) { |
720 assert(!fc->sym->isInterfaceDeclaration()); | 848 if (fc->sym->isInterfaceDeclaration()) { |
721 return DtoDynamicCastObject(val, _to); | 849 return DtoDynamicCastInterface(val, _to); |
850 } | |
851 else { | |
852 return DtoDynamicCastObject(val, _to); | |
853 } | |
722 } | 854 } |
723 else { | 855 else { |
724 int poffset; | 856 int poffset; |
725 if (fc->sym->isInterfaceDeclaration()) { | 857 if (fc->sym->isInterfaceDeclaration()) { |
726 return DtoCastInterfaceToObject(val, _to); | 858 return DtoCastInterfaceToObject(val, _to); |
803 return new DImValue(to, ret); | 935 return new DImValue(to, ret); |
804 } | 936 } |
805 | 937 |
806 ////////////////////////////////////////////////////////////////////////////////////////// | 938 ////////////////////////////////////////////////////////////////////////////////////////// |
807 | 939 |
940 DValue* DtoDynamicCastInterface(DValue* val, Type* _to) | |
941 { | |
942 // call: | |
943 // Object _d_interface_cast(void* p, ClassInfo c) | |
944 | |
945 DtoForceDeclareDsymbol(ClassDeclaration::object); | |
946 DtoForceDeclareDsymbol(ClassDeclaration::classinfo); | |
947 | |
948 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast"); | |
949 const llvm::FunctionType* funcTy = func->getFunctionType(); | |
950 | |
951 std::vector<llvm::Value*> args; | |
952 | |
953 // void* p | |
954 llvm::Value* tmp = val->getRVal(); | |
955 tmp = DtoBitCast(tmp, funcTy->getParamType(0)); | |
956 args.push_back(tmp); | |
957 | |
958 // ClassInfo c | |
959 TypeClass* to = (TypeClass*)DtoDType(_to); | |
960 DtoForceDeclareDsymbol(to->sym); | |
961 assert(to->sym->llvmClass); | |
962 tmp = to->sym->llvmClass; | |
963 // unfortunately this is needed as the implementation of object differs somehow from the declaration | |
964 // this could happen in user code as well :/ | |
965 tmp = DtoBitCast(tmp, funcTy->getParamType(1)); | |
966 args.push_back(tmp); | |
967 | |
968 // call it | |
969 llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp"); | |
970 | |
971 // cast return value | |
972 ret = DtoBitCast(ret, DtoType(_to)); | |
973 | |
974 return new DImValue(_to, ret); | |
975 } | |
976 | |
977 ////////////////////////////////////////////////////////////////////////////////////////// | |
978 | |
808 static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx) | 979 static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx) |
809 { | 980 { |
810 // start at the bottom of the inheritance chain | 981 // start at the bottom of the inheritance chain |
811 if (cd->baseClass != 0) { | 982 if (cd->baseClass != 0) { |
812 unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx); | 983 unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx); |
849 LOG_SCOPE; | 1020 LOG_SCOPE; |
850 | 1021 |
851 if (idxs.empty()) | 1022 if (idxs.empty()) |
852 idxs.push_back(0); | 1023 idxs.push_back(0); |
853 | 1024 |
854 const llvm::Type* llt = llvm::PointerType::get(DtoType(t)); | 1025 const llvm::Type* llt = getPtrToType(DtoType(t)); |
855 const llvm::Type* st = DtoType(cd->type); | 1026 const llvm::Type* st = DtoType(cd->type); |
856 if (ptr->getType() != st) { | 1027 if (ptr->getType() != st) { |
857 assert(cd->llvmHasUnions); | 1028 assert(cd->llvmHasUnions); |
858 ptr = gIR->ir->CreateBitCast(ptr, st, "tmp"); | 1029 ptr = gIR->ir->CreateBitCast(ptr, st, "tmp"); |
859 } | 1030 } |
893 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); | 1064 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); |
894 std::vector<unsigned> tmp; | 1065 std::vector<unsigned> tmp; |
895 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); | 1066 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); |
896 } | 1067 } |
897 else { | 1068 else { |
898 const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type)); | 1069 const llvm::Type* sty = getPtrToType(DtoType(vd->type)); |
899 if (ptr->getType() != sty) { | 1070 if (ptr->getType() != sty) { |
900 ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp"); | 1071 ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp"); |
901 std::vector<unsigned> tmp; | 1072 std::vector<unsigned> tmp; |
902 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); | 1073 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); |
903 } | 1074 } |
908 } | 1079 } |
909 } | 1080 } |
910 | 1081 |
911 assert(0); | 1082 assert(0); |
912 | 1083 |
913 size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0)); | 1084 size_t llt_sz = getABITypeSize(llt->getContainedType(0)); |
914 assert(os % llt_sz == 0); | 1085 assert(os % llt_sz == 0); |
915 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); | 1086 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); |
916 return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb()); | 1087 return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb()); |
1088 } | |
1089 | |
1090 ////////////////////////////////////////////////////////////////////////////////////////// | |
1091 | |
1092 llvm::Value* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl) | |
1093 { | |
1094 assert(fdecl->isVirtual());//fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())); | |
1095 assert(fdecl->vtblIndex > 0); | |
1096 assert(DtoDType(inst->getType())->ty == Tclass); | |
1097 | |
1098 llvm::Value* vthis = inst->getRVal(); | |
1099 //Logger::cout() << "vthis: " << *vthis << '\n'; | |
1100 | |
1101 llvm::Value* funcval; | |
1102 funcval = DtoGEPi(vthis, 0, 0, "tmp"); | |
1103 funcval = DtoLoad(funcval); | |
1104 funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toPrettyChars()); | |
1105 funcval = DtoLoad(funcval); | |
1106 | |
1107 //assert(funcval->getType() == DtoType(fdecl->type)); | |
1108 //cc = DtoCallingConv(fdecl->linkage); | |
1109 | |
1110 return funcval; | |
917 } | 1111 } |
918 | 1112 |
919 ////////////////////////////////////////////////////////////////////////////////////////// | 1113 ////////////////////////////////////////////////////////////////////////////////////////// |
920 | 1114 |
921 void DtoDeclareClassInfo(ClassDeclaration* cd) | 1115 void DtoDeclareClassInfo(ClassDeclaration* cd) |
959 vd->type->getTypeInfo(NULL); | 1153 vd->type->getTypeInfo(NULL); |
960 assert(vd->type->vtinfo); | 1154 assert(vd->type->vtinfo); |
961 DtoForceDeclareDsymbol(vd->type->vtinfo); | 1155 DtoForceDeclareDsymbol(vd->type->vtinfo); |
962 llvm::Constant* c = isaConstant(vd->type->vtinfo->llvmValue); | 1156 llvm::Constant* c = isaConstant(vd->type->vtinfo->llvmValue); |
963 | 1157 |
964 const llvm::Type* tiTy = llvm::PointerType::get(Type::typeinfo->type->llvmType->get()); | 1158 const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get()); |
965 //Logger::cout() << "tiTy = " << *tiTy << '\n'; | 1159 //Logger::cout() << "tiTy = " << *tiTy << '\n'; |
966 | 1160 |
967 types.push_back(tiTy); | 1161 types.push_back(tiTy); |
968 inits.push_back(llvm::ConstantExpr::getBitCast(c, tiTy)); | 1162 inits.push_back(llvm::ConstantExpr::getBitCast(c, tiTy)); |
969 | 1163 |
1000 | 1194 |
1001 if (ninits > 0) { | 1195 if (ninits > 0) { |
1002 // OffsetTypeInfo type | 1196 // OffsetTypeInfo type |
1003 std::vector<const llvm::Type*> elemtypes; | 1197 std::vector<const llvm::Type*> elemtypes; |
1004 elemtypes.push_back(DtoSize_t()); | 1198 elemtypes.push_back(DtoSize_t()); |
1005 const llvm::Type* tiTy = llvm::PointerType::get(Type::typeinfo->type->llvmType->get()); | 1199 const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get()); |
1006 elemtypes.push_back(tiTy); | 1200 elemtypes.push_back(tiTy); |
1007 const llvm::StructType* sTy = llvm::StructType::get(elemtypes); | 1201 const llvm::StructType* sTy = llvm::StructType::get(elemtypes); |
1008 | 1202 |
1009 // array type | 1203 // array type |
1010 const llvm::ArrayType* arrTy = llvm::ArrayType::get(sTy, ninits); | 1204 const llvm::ArrayType* arrTy = llvm::ArrayType::get(sTy, ninits); |
1011 llvm::Constant* arrInit = llvm::ConstantArray::get(arrTy, arrayInits); | 1205 llvm::Constant* arrInit = llvm::ConstantArray::get(arrTy, arrayInits); |
1012 | 1206 |
1013 std::string name(cd->type->vtinfo->toChars()); | 1207 std::string name(cd->type->vtinfo->toChars()); |
1014 name.append("__OffsetTypeInfos"); | 1208 name.append("__OffsetTypeInfos"); |
1015 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,llvm::GlobalValue::InternalLinkage,arrInit,name,gIR->module); | 1209 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,llvm::GlobalValue::InternalLinkage,arrInit,name,gIR->module); |
1016 ptr = llvm::ConstantExpr::getBitCast(gvar, llvm::PointerType::get(sTy)); | 1210 ptr = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(sTy)); |
1017 } | 1211 } |
1018 else { | 1212 else { |
1019 ptr = llvm::ConstantPointerNull::get(isaPointer(initTy->getElementType(1))); | 1213 ptr = llvm::ConstantPointerNull::get(isaPointer(initTy->getElementType(1))); |
1020 } | 1214 } |
1021 | 1215 |
1024 | 1218 |
1025 static llvm::Constant* build_class_dtor(ClassDeclaration* cd) | 1219 static llvm::Constant* build_class_dtor(ClassDeclaration* cd) |
1026 { | 1220 { |
1027 // construct the function | 1221 // construct the function |
1028 std::vector<const llvm::Type*> paramTypes; | 1222 std::vector<const llvm::Type*> paramTypes; |
1029 paramTypes.push_back(llvm::PointerType::get(cd->type->llvmType->get())); | 1223 paramTypes.push_back(getPtrToType(cd->type->llvmType->get())); |
1030 | 1224 |
1031 const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy, paramTypes, false); | 1225 const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy, paramTypes, false); |
1032 | 1226 |
1033 if (cd->dtors.dim == 0) { | 1227 if (cd->dtors.dim == 0) { |
1034 return llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); | 1228 return llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)); |
1035 } | 1229 } |
1036 else if (cd->dtors.dim == 1) { | 1230 else if (cd->dtors.dim == 1) { |
1037 DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[0]; | 1231 DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[0]; |
1038 DtoForceDeclareDsymbol(d); | 1232 DtoForceDeclareDsymbol(d); |
1039 assert(d->llvmValue); | 1233 assert(d->llvmValue); |
1040 return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), llvm::PointerType::get(llvm::Type::Int8Ty)); | 1234 return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), getPtrToType(llvm::Type::Int8Ty)); |
1041 } | 1235 } |
1042 | 1236 |
1043 std::string gname("_D"); | 1237 std::string gname("_D"); |
1044 gname.append(cd->mangle()); | 1238 gname.append(cd->mangle()); |
1045 gname.append("12__destructorMFZv"); | 1239 gname.append("12__destructorMFZv"); |
1058 assert(d->llvmValue); | 1252 assert(d->llvmValue); |
1059 builder.CreateCall(d->llvmValue, thisptr); | 1253 builder.CreateCall(d->llvmValue, thisptr); |
1060 } | 1254 } |
1061 builder.CreateRetVoid(); | 1255 builder.CreateRetVoid(); |
1062 | 1256 |
1063 return llvm::ConstantExpr::getBitCast(func, llvm::PointerType::get(llvm::Type::Int8Ty)); | 1257 return llvm::ConstantExpr::getBitCast(func, getPtrToType(llvm::Type::Int8Ty)); |
1064 } | 1258 } |
1065 | 1259 |
1066 static uint build_classinfo_flags(ClassDeclaration* cd) | 1260 static uint build_classinfo_flags(ClassDeclaration* cd) |
1067 { | 1261 { |
1068 // adapted from original dmd code | 1262 // adapted from original dmd code |
1119 | 1313 |
1120 assert(cd->type->ty == Tclass); | 1314 assert(cd->type->ty == Tclass); |
1121 assert(cd->llvmClass); | 1315 assert(cd->llvmClass); |
1122 | 1316 |
1123 TypeClass* cdty = (TypeClass*)cd->type; | 1317 TypeClass* cdty = (TypeClass*)cd->type; |
1124 if (!cd->isInterfaceDeclaration()) { | 1318 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
1125 assert(cd->llvmInit); | 1319 assert(cd->llvmInit); |
1126 assert(cd->llvmConstInit); | 1320 assert(cd->llvmConstInit); |
1127 assert(cd->llvmVtbl); | 1321 assert(cd->llvmVtbl); |
1128 assert(cd->llvmConstVtbl); | 1322 assert(cd->llvmConstVtbl); |
1129 } | 1323 } |
1145 // monitor | 1339 // monitor |
1146 c = cinfo->llvmConstInit->getOperand(1); | 1340 c = cinfo->llvmConstInit->getOperand(1); |
1147 inits.push_back(c); | 1341 inits.push_back(c); |
1148 | 1342 |
1149 // byte[] init | 1343 // byte[] init |
1150 const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty); | 1344 const llvm::Type* byteptrty = getPtrToType(llvm::Type::Int8Ty); |
1151 if (cd->isInterfaceDeclaration()) { | 1345 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1152 c = cinfo->llvmConstInit->getOperand(2); | 1346 c = cinfo->llvmConstInit->getOperand(2); |
1153 } | 1347 } |
1154 else { | 1348 else { |
1155 c = llvm::ConstantExpr::getBitCast(cd->llvmInit, byteptrty); | 1349 c = llvm::ConstantExpr::getBitCast(cd->llvmInit, byteptrty); |
1156 assert(!cd->llvmConstInit->getType()->isAbstract()); | 1350 assert(!cd->llvmConstInit->getType()->isAbstract()); |
1157 size_t initsz = gTargetData->getTypeSize(cd->llvmConstInit->getType()); | 1351 size_t initsz = getABITypeSize(cd->llvmConstInit->getType()); |
1158 c = DtoConstSlice(DtoConstSize_t(initsz), c); | 1352 c = DtoConstSlice(DtoConstSize_t(initsz), c); |
1159 } | 1353 } |
1160 inits.push_back(c); | 1354 inits.push_back(c); |
1161 | 1355 |
1162 // class name | 1356 // class name |
1170 } | 1364 } |
1171 c = DtoConstString(name); | 1365 c = DtoConstString(name); |
1172 inits.push_back(c); | 1366 inits.push_back(c); |
1173 | 1367 |
1174 // vtbl array | 1368 // vtbl array |
1175 if (cd->isInterfaceDeclaration()) { | 1369 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1176 c = cinfo->llvmConstInit->getOperand(4); | 1370 c = cinfo->llvmConstInit->getOperand(4); |
1177 } | 1371 } |
1178 else { | 1372 else { |
1179 const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty); | 1373 const llvm::Type* byteptrptrty = getPtrToType(byteptrty); |
1180 assert(!cd->llvmVtbl->getType()->isAbstract()); | 1374 assert(!cd->llvmVtbl->getType()->isAbstract()); |
1181 c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty); | 1375 c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty); |
1182 assert(!cd->llvmConstVtbl->getType()->isAbstract()); | 1376 assert(!cd->llvmConstVtbl->getType()->isAbstract()); |
1183 size_t vtblsz = cd->llvmConstVtbl->getType()->getNumElements(); | 1377 size_t vtblsz = cd->llvmConstVtbl->getType()->getNumElements(); |
1184 c = DtoConstSlice(DtoConstSize_t(vtblsz), c); | 1378 c = DtoConstSlice(DtoConstSize_t(vtblsz), c); |
1185 } | 1379 } |
1186 inits.push_back(c); | 1380 inits.push_back(c); |
1187 | 1381 |
1188 // interfaces array | 1382 // interfaces array |
1189 IRStruct* irstruct = cd->llvmIRStruct; | 1383 IRStruct* irstruct = cd->llvmIRStruct; |
1190 if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos) { | 1384 if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) { |
1191 c = cinfo->llvmConstInit->getOperand(5); | 1385 c = cinfo->llvmConstInit->getOperand(5); |
1192 } | 1386 } |
1193 else { | 1387 else { |
1194 const llvm::Type* t = cinfo->llvmConstInit->getOperand(5)->getType()->getContainedType(1); | 1388 const llvm::Type* t = cinfo->llvmConstInit->getOperand(5)->getType()->getContainedType(1); |
1195 c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t); | 1389 c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t); |
1197 c = DtoConstSlice(DtoConstSize_t(iisz), c); | 1391 c = DtoConstSlice(DtoConstSize_t(iisz), c); |
1198 } | 1392 } |
1199 inits.push_back(c); | 1393 inits.push_back(c); |
1200 | 1394 |
1201 // base classinfo | 1395 // base classinfo |
1202 if (cd->baseClass && !cd->isInterfaceDeclaration()) { | 1396 if (cd->baseClass && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
1203 DtoDeclareClassInfo(cd->baseClass); | 1397 DtoDeclareClassInfo(cd->baseClass); |
1204 c = cd->baseClass->llvmClass; | 1398 c = cd->baseClass->llvmClass; |
1205 assert(c); | 1399 assert(c); |
1206 inits.push_back(c); | 1400 inits.push_back(c); |
1207 } | 1401 } |
1210 c = cinfo->llvmConstInit->getOperand(6); | 1404 c = cinfo->llvmConstInit->getOperand(6); |
1211 inits.push_back(c); | 1405 inits.push_back(c); |
1212 } | 1406 } |
1213 | 1407 |
1214 // destructor | 1408 // destructor |
1215 if (cd->isInterfaceDeclaration()) { | 1409 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1216 c = cinfo->llvmConstInit->getOperand(7); | 1410 c = cinfo->llvmConstInit->getOperand(7); |
1217 } | 1411 } |
1218 else { | 1412 else { |
1219 c = build_class_dtor(cd); | 1413 c = build_class_dtor(cd); |
1220 } | 1414 } |
1224 // TODO | 1418 // TODO |
1225 c = cinfo->llvmConstInit->getOperand(8); | 1419 c = cinfo->llvmConstInit->getOperand(8); |
1226 inits.push_back(c); | 1420 inits.push_back(c); |
1227 | 1421 |
1228 // uint flags | 1422 // uint flags |
1229 if (cd->isInterfaceDeclaration()) { | 1423 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1230 c = cinfo->llvmConstInit->getOperand(9); | 1424 c = cinfo->llvmConstInit->getOperand(9); |
1231 } | 1425 } |
1232 else { | 1426 else { |
1233 uint flags = build_classinfo_flags(cd); | 1427 uint flags = build_classinfo_flags(cd); |
1234 c = DtoConstUint(flags); | 1428 c = DtoConstUint(flags); |
1239 // TODO | 1433 // TODO |
1240 c = cinfo->llvmConstInit->getOperand(10); | 1434 c = cinfo->llvmConstInit->getOperand(10); |
1241 inits.push_back(c); | 1435 inits.push_back(c); |
1242 | 1436 |
1243 // offset typeinfo | 1437 // offset typeinfo |
1244 if (cd->isInterfaceDeclaration()) { | 1438 if (cd->isInterfaceDeclaration() || cd->isAbstract()) { |
1245 c = cinfo->llvmConstInit->getOperand(11); | 1439 c = cinfo->llvmConstInit->getOperand(11); |
1246 } | 1440 } |
1247 else { | 1441 else { |
1248 c = build_offti_array(cd, cinfo->llvmConstInit->getOperand(11)); | 1442 c = build_offti_array(cd, cinfo->llvmConstInit->getOperand(11)); |
1249 } | 1443 } |
1250 inits.push_back(c); | 1444 inits.push_back(c); |
1251 | 1445 |
1252 // default constructor | 1446 // default constructor |
1253 if (cd->defaultCtor && !cd->isInterfaceDeclaration()) { | 1447 if (cd->defaultCtor && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
1254 DtoForceDeclareDsymbol(cd->defaultCtor); | 1448 DtoForceDeclareDsymbol(cd->defaultCtor); |
1255 c = isaConstant(cd->defaultCtor->llvmValue); | 1449 c = isaConstant(cd->defaultCtor->llvmValue); |
1256 const llvm::Type* toTy = cinfo->llvmConstInit->getOperand(12)->getType(); | 1450 const llvm::Type* toTy = cinfo->llvmConstInit->getOperand(12)->getType(); |
1257 c = llvm::ConstantExpr::getBitCast(c, toTy); | 1451 c = llvm::ConstantExpr::getBitCast(c, toTy); |
1258 } | 1452 } |