Mercurial > projects > ldc
comparison gen/classes.cpp @ 193:aca17e55b7a5 trunk
[svn r209] Fixed: exotic array to pointer casts were broken.
Changed: classes now have opaque vtables.
author | lindquist |
---|---|
date | Mon, 12 May 2008 18:44:11 +0200 |
parents | 67ed21bf16af |
children | ba47ac346ddd |
comparison
equal
deleted
inserted
replaced
192:67ed21bf16af | 193:aca17e55b7a5 |
---|---|
122 // Fill in vtbl[] | 122 // Fill in vtbl[] |
123 b->fillVtbl(cd, &b->vtbl, 1); | 123 b->fillVtbl(cd, &b->vtbl, 1); |
124 } | 124 } |
125 }*/ | 125 }*/ |
126 | 126 |
127 // push state | |
127 gIR->structs.push_back(irstruct); | 128 gIR->structs.push_back(irstruct); |
128 gIR->classes.push_back(cd); | 129 gIR->classes.push_back(cd); |
130 | |
131 // vector holding the field types | |
132 std::vector<const llvm::Type*> fieldtypes; | |
129 | 133 |
130 // add vtable | 134 // add vtable |
131 ts->ir.vtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); | 135 ts->ir.vtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); |
132 const llvm::Type* vtabty = getPtrToType(ts->ir.vtblType->get()); | 136 const llvm::Type* vtabty = getPtrToType(ts->ir.vtblType->get()); |
133 | |
134 std::vector<const llvm::Type*> fieldtypes; | |
135 fieldtypes.push_back(vtabty); | 137 fieldtypes.push_back(vtabty); |
136 | 138 |
137 // add monitor | 139 // add monitor |
138 fieldtypes.push_back(getPtrToType(llvm::Type::Int8Ty)); | 140 fieldtypes.push_back(getVoidPtrType()); |
139 | 141 |
140 // add base class data fields first | 142 // add base class data fields first |
141 LLVM_AddBaseClassData(&cd->baseclasses); | 143 LLVM_AddBaseClassData(&cd->baseclasses); |
142 | 144 |
143 // then add own members | 145 // then add own members |
239 TypeClass* itc = (TypeClass*)id->type; | 241 TypeClass* itc = (TypeClass*)id->type; |
240 const llvm::Type* ivtblTy = getPtrToType(itc->ir.vtblType->get()); | 242 const llvm::Type* ivtblTy = getPtrToType(itc->ir.vtblType->get()); |
241 fieldtypes.push_back(ivtblTy); | 243 fieldtypes.push_back(ivtblTy); |
242 | 244 |
243 // fix the interface vtable type | 245 // fix the interface vtable type |
246 #if OPAQUE_VTBLS | |
247 iri->vtblTy = isaArray(itc->ir.vtblType->get()); | |
248 #else | |
244 iri->vtblTy = isaStruct(itc->ir.vtblType->get()); | 249 iri->vtblTy = isaStruct(itc->ir.vtblType->get()); |
250 #endif | |
245 | 251 |
246 // set index | 252 // set index |
247 iri->index = interIdx++; | 253 iri->index = interIdx++; |
248 } | 254 } |
249 Logger::println("%d interface vtables added", cd->ir.irStruct->interfaceVec.size()); | 255 Logger::println("%d interface vtables added", cd->ir.irStruct->interfaceVec.size()); |
271 // get interface info type | 277 // get interface info type |
272 const llvm::StructType* infoTy = DtoInterfaceInfoType(); | 278 const llvm::StructType* infoTy = DtoInterfaceInfoType(); |
273 | 279 |
274 // create vtable type | 280 // create vtable type |
275 llvm::GlobalVariable* svtblVar = 0; | 281 llvm::GlobalVariable* svtblVar = 0; |
282 #if OPAQUE_VTBLS | |
283 // void*[vtbl.dim] | |
284 const llvm::ArrayType* svtbl_ty | |
285 = llvm::ArrayType::get(getVoidPtrType(), cd->vtbl.dim); | |
286 | |
287 #else | |
276 std::vector<const llvm::Type*> sinits_ty; | 288 std::vector<const llvm::Type*> sinits_ty; |
277 | 289 |
278 for (int k=0; k < cd->vtbl.dim; k++) | 290 for (int k=0; k < cd->vtbl.dim; k++) |
279 { | 291 { |
280 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; | 292 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; |
308 } | 320 } |
309 else | 321 else |
310 assert(0); | 322 assert(0); |
311 } | 323 } |
312 | 324 |
325 // get type | |
313 assert(!sinits_ty.empty()); | 326 assert(!sinits_ty.empty()); |
314 const llvm::StructType* svtbl_ty = llvm::StructType::get(sinits_ty); | 327 const llvm::StructType* svtbl_ty = llvm::StructType::get(sinits_ty); |
315 | 328 #endif |
329 | |
330 // refine for final vtable type | |
331 llvm::cast<llvm::OpaqueType>(ts->ir.vtblType->get())->refineAbstractTypeTo(svtbl_ty); | |
332 | |
333 #if !OPAQUE_VTBLS | |
334 // name vtbl type | |
316 std::string styname(cd->mangle()); | 335 std::string styname(cd->mangle()); |
317 styname.append("__vtblType"); | 336 styname.append("__vtblType"); |
318 gIR->module->addTypeName(styname, svtbl_ty); | 337 gIR->module->addTypeName(styname, svtbl_ty); |
319 | 338 #endif |
320 // refine for final vtable type | 339 |
321 llvm::cast<llvm::OpaqueType>(ts->ir.vtblType->get())->refineAbstractTypeTo(svtbl_ty); | 340 // log |
322 | 341 Logger::cout() << "final class type: " << *ts->ir.type->get() << '\n'; |
342 | |
343 // pop state | |
323 gIR->classes.pop_back(); | 344 gIR->classes.pop_back(); |
324 gIR->structs.pop_back(); | 345 gIR->structs.pop_back(); |
325 | 346 |
347 // queue declare | |
326 gIR->declareList.push_back(cd); | 348 gIR->declareList.push_back(cd); |
327 } | 349 } |
328 | 350 |
329 ////////////////////////////////////////////////////////////////////////////////////////// | 351 ////////////////////////////////////////////////////////////////////////////////////////// |
330 | 352 |
357 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { | 379 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
358 // vtable | 380 // vtable |
359 std::string varname("_D"); | 381 std::string varname("_D"); |
360 varname.append(cd->mangle()); | 382 varname.append(cd->mangle()); |
361 varname.append("6__vtblZ"); | 383 varname.append("6__vtblZ"); |
362 | 384 cd->ir.irStruct->vtbl = new llvm::GlobalVariable(ts->ir.vtblType->get(), true, _linkage, 0, varname, gIR->module); |
363 const llvm::StructType* svtbl_ty = isaStruct(ts->ir.vtblType->get()); | |
364 cd->ir.irStruct->vtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); | |
365 } | 385 } |
366 | 386 |
367 // get interface info type | 387 // get interface info type |
368 const llvm::StructType* infoTy = DtoInterfaceInfoType(); | 388 const llvm::StructType* infoTy = DtoInterfaceInfoType(); |
369 | 389 |
443 | 463 |
444 // get the struct (class) type | 464 // get the struct (class) type |
445 assert(cd->type->ty == Tclass); | 465 assert(cd->type->ty == Tclass); |
446 TypeClass* ts = (TypeClass*)cd->type; | 466 TypeClass* ts = (TypeClass*)cd->type; |
447 const llvm::StructType* structtype = isaStruct(ts->ir.type->get()); | 467 const llvm::StructType* structtype = isaStruct(ts->ir.type->get()); |
468 #if OPAQUE_VTBLS | |
469 const llvm::ArrayType* vtbltype = isaArray(ts->ir.vtblType->get()); | |
470 #else | |
448 const llvm::StructType* vtbltype = isaStruct(ts->ir.vtblType->get()); | 471 const llvm::StructType* vtbltype = isaStruct(ts->ir.vtblType->get()); |
472 #endif | |
449 | 473 |
450 // make sure each offset knows its default initializer | 474 // make sure each offset knows its default initializer |
451 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) | 475 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) |
452 { | 476 { |
453 IrStruct::Offset* so = &i->second; | 477 IrStruct::Offset* so = &i->second; |
541 { | 565 { |
542 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; | 566 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; |
543 assert(dsym); | 567 assert(dsym); |
544 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; | 568 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; |
545 | 569 |
570 #if OPAQUE_VTBLS | |
571 const llvm::Type* targetTy = getVoidPtrType(); | |
572 #else | |
573 const llvm::Type* targetTy = vtbltype->getElementType(k); | |
574 #endif | |
575 | |
576 llvm::Constant* c = NULL; | |
577 // virtual method | |
546 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { | 578 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { |
547 DtoForceDeclareDsymbol(fd); | 579 DtoForceDeclareDsymbol(fd); |
548 assert(fd->ir.irFunc->func); | 580 assert(fd->ir.irFunc->func); |
549 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->ir.irFunc->func); | 581 c = llvm::cast<llvm::Constant>(fd->ir.irFunc->func); |
550 // cast if necessary (overridden method) | |
551 if (c->getType() != vtbltype->getElementType(k)) | |
552 c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); | |
553 sinits.push_back(c); | |
554 } | 582 } |
583 // classinfo | |
555 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { | 584 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { |
556 assert(cd->ir.irStruct->classInfo); | 585 assert(cd->ir.irStruct->classInfo); |
557 llvm::Constant* c = cd->ir.irStruct->classInfo; | 586 c = cd->ir.irStruct->classInfo; |
558 sinits.push_back(c); | |
559 } | 587 } |
560 else | 588 assert(c != NULL); |
561 assert(0); | 589 |
562 } | 590 // cast if necessary (overridden method) |
563 | 591 if (c->getType() != targetTy) |
592 c = llvm::ConstantExpr::getBitCast(c, targetTy); | |
593 sinits.push_back(c); | |
594 } | |
595 #if OPAQUE_VTBLS | |
596 const llvm::ArrayType* svtbl_ty = isaArray(ts->ir.vtblType->get()); | |
597 llvm::Constant* cvtblInit = llvm::ConstantArray::get(svtbl_ty, sinits); | |
598 cd->ir.irStruct->constVtbl = llvm::cast<llvm::ConstantArray>(cvtblInit); | |
599 #else | |
564 const llvm::StructType* svtbl_ty = isaStruct(ts->ir.vtblType->get()); | 600 const llvm::StructType* svtbl_ty = isaStruct(ts->ir.vtblType->get()); |
565 | |
566 #if 0 | |
567 for (size_t i=0; i< sinits.size(); ++i) | |
568 { | |
569 Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n'; | |
570 Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n'; | |
571 assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); | |
572 } | |
573 #endif | |
574 | |
575 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); | 601 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); |
576 cd->ir.irStruct->constVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); | 602 cd->ir.irStruct->constVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); |
603 #endif | |
577 | 604 |
578 // create interface vtable const initalizers | 605 // create interface vtable const initalizers |
579 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) | 606 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) |
580 { | 607 { |
581 IrInterface* iri = *i; | 608 IrInterface* iri = *i; |
583 | 610 |
584 ClassDeclaration* id = iri->decl; | 611 ClassDeclaration* id = iri->decl; |
585 assert(id->type->ty == Tclass); | 612 assert(id->type->ty == Tclass); |
586 TypeClass* its = (TypeClass*)id->type; | 613 TypeClass* its = (TypeClass*)id->type; |
587 | 614 |
615 #if OPAQUE_VTBLS | |
616 const llvm::ArrayType* ivtbl_ty = isaArray(its->ir.vtblType->get()); | |
617 #else | |
588 const llvm::StructType* ivtbl_ty = isaStruct(its->ir.vtblType->get()); | 618 const llvm::StructType* ivtbl_ty = isaStruct(its->ir.vtblType->get()); |
619 #endif | |
589 | 620 |
590 // generate interface info initializer | 621 // generate interface info initializer |
591 std::vector<llvm::Constant*> infoInits; | 622 std::vector<llvm::Constant*> infoInits; |
592 | 623 |
593 // classinfo | 624 // classinfo |
611 | 642 |
612 // generate vtable initializer | 643 // generate vtable initializer |
613 std::vector<llvm::Constant*> iinits; | 644 std::vector<llvm::Constant*> iinits; |
614 | 645 |
615 // add interface info | 646 // add interface info |
647 #if OPAQUE_VTBLS | |
648 const llvm::Type* targetTy = getVoidPtrType(); | |
649 iinits.push_back(llvm::ConstantExpr::getBitCast(iri->info, targetTy)); | |
650 #else | |
616 iinits.push_back(iri->info); | 651 iinits.push_back(iri->info); |
652 #endif | |
617 | 653 |
618 for (int k=1; k < b->vtbl.dim; k++) | 654 for (int k=1; k < b->vtbl.dim; k++) |
619 { | 655 { |
620 Logger::println("interface vtbl const init nr. %d", k); | 656 Logger::println("interface vtbl const init nr. %d", k); |
621 Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; | 657 Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; |
624 assert(fd); | 660 assert(fd); |
625 DtoForceDeclareDsymbol(fd); | 661 DtoForceDeclareDsymbol(fd); |
626 assert(fd->ir.irFunc->func); | 662 assert(fd->ir.irFunc->func); |
627 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->ir.irFunc->func); | 663 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->ir.irFunc->func); |
628 | 664 |
665 #if !OPAQUE_VTBLS | |
666 const llvm::Type* targetTy = iri->vtblTy->getContainedType(k); | |
667 #endif | |
668 | |
629 // we have to bitcast, as the type created in ResolveClass expects a different this type | 669 // we have to bitcast, as the type created in ResolveClass expects a different this type |
630 c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); | 670 c = llvm::ConstantExpr::getBitCast(c, targetTy); |
631 iinits.push_back(c); | 671 iinits.push_back(c); |
672 Logger::cout() << "c: " << *c << '\n'; | |
632 } | 673 } |
633 | 674 |
634 #if 0 | 675 #if OPAQUE_VTBLS |
635 for (size_t x=0; x< iinits.size(); ++x) | 676 Logger::cout() << "n: " << iinits.size() << " ivtbl_ty: " << *ivtbl_ty << '\n'; |
636 { | 677 llvm::Constant* civtblInit = llvm::ConstantArray::get(ivtbl_ty, iinits); |
637 Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n"; | 678 iri->vtblInit = llvm::cast<llvm::ConstantArray>(civtblInit); |
638 Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n"; | 679 #else |
639 assert(ivtbl_ty->getElementType(x) == iinits[x]->getType()); | |
640 } | |
641 #endif | |
642 | |
643 llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); | 680 llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); |
644 iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit); | 681 iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit); |
682 #endif | |
645 } | 683 } |
646 } | 684 } |
647 // we always generate interfaceinfos as best we can | 685 // we always generate interfaceinfos as best we can |
648 else | 686 else |
649 { | 687 { |
1169 assert(fdecl->isVirtual());//fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())); | 1207 assert(fdecl->isVirtual());//fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())); |
1170 assert(fdecl->vtblIndex > 0); | 1208 assert(fdecl->vtblIndex > 0); |
1171 assert(DtoDType(inst->getType())->ty == Tclass); | 1209 assert(DtoDType(inst->getType())->ty == Tclass); |
1172 | 1210 |
1173 llvm::Value* vthis = inst->getRVal(); | 1211 llvm::Value* vthis = inst->getRVal(); |
1174 //Logger::cout() << "vthis: " << *vthis << '\n'; | 1212 Logger::cout() << "vthis: " << *vthis << '\n'; |
1175 | 1213 |
1176 llvm::Value* funcval; | 1214 llvm::Value* funcval; |
1177 funcval = DtoGEPi(vthis, 0, 0, "tmp"); | 1215 funcval = DtoGEPi(vthis, 0, 0, "tmp"); |
1178 funcval = DtoLoad(funcval); | 1216 funcval = DtoLoad(funcval); |
1179 funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toPrettyChars()); | 1217 funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toPrettyChars()); |
1180 funcval = DtoLoad(funcval); | 1218 funcval = DtoLoad(funcval); |
1219 | |
1220 Logger::cout() << "funcval: " << *funcval << '\n'; | |
1221 | |
1222 #if OPAQUE_VTBLS | |
1223 funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type))); | |
1224 Logger::cout() << "funcval casted: " << *funcval << '\n'; | |
1225 #endif | |
1181 | 1226 |
1182 //assert(funcval->getType() == DtoType(fdecl->type)); | 1227 //assert(funcval->getType() == DtoType(fdecl->type)); |
1183 //cc = DtoCallingConv(fdecl->linkage); | 1228 //cc = DtoCallingConv(fdecl->linkage); |
1184 | 1229 |
1185 return funcval; | 1230 return funcval; |