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;