Mercurial > projects > ldc
comparison gen/classes.cpp @ 142:a123dca8349b trunk
[svn r146] fixed some potential problems with mismatch in order of interfaces in class data layout
author | lindquist |
---|---|
date | Wed, 23 Jan 2008 15:48:19 +0100 |
parents | aeddd4d533b3 |
children | 0636f6269dfd |
comparison
equal
deleted
inserted
replaced
141:8f43f5c43c95 | 142:a123dca8349b |
---|---|
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 | 29 |
30 // base *classes* might add more interfaces? | |
31 DtoResolveClass(bc->base); | |
32 LLVM_AddBaseClassInterfaces(target, &bc->base->baseclasses); | |
33 | |
30 // resolve interfaces while we're at it | 34 // resolve interfaces while we're at it |
31 if (bc->base->isInterfaceDeclaration()) | 35 if (bc->base->isInterfaceDeclaration()) |
32 { | 36 { |
33 Logger::println("adding interface '%s'", bc->base->toPrettyChars()); | 37 // don't add twice |
34 IrInterface* iri = new IrInterface(bc, NULL); | 38 if (target->irStruct->interfaceMap.find(bc->base) == target->irStruct->interfaceMap.end()) |
35 target->irStruct->interfaces.insert(std::make_pair(bc->base, iri)); | 39 { |
36 if (!target->isAbstract()) { | 40 Logger::println("adding interface '%s'", bc->base->toPrettyChars()); |
41 IrInterface* iri = new IrInterface(bc, NULL); | |
42 | |
43 // add to map | |
44 target->irStruct->interfaceMap.insert(std::make_pair(bc->base, iri)); | |
45 // add to ordered list | |
46 target->irStruct->interfaceVec.push_back(iri); | |
47 | |
37 // Fill in vtbl[] | 48 // Fill in vtbl[] |
38 bc->fillVtbl(target, &bc->vtbl, 0); | 49 if (!target->isAbstract()) { |
50 bc->fillVtbl(target, &bc->vtbl, 0); | |
51 } | |
39 } | 52 } |
40 DtoResolveClass(bc->base); | 53 } |
41 } | |
42 | |
43 // base *classes* might add more interfaces? | |
44 LLVM_AddBaseClassInterfaces(target, &bc->base->baseclasses); | |
45 } | 54 } |
46 } | 55 } |
47 | 56 |
48 ////////////////////////////////////////////////////////////////////////////////////////// | 57 ////////////////////////////////////////////////////////////////////////////////////////// |
49 | 58 |
213 // populate interface map | 222 // populate interface map |
214 { | 223 { |
215 Logger::println("Adding interfaces to '%s'", cd->toPrettyChars()); | 224 Logger::println("Adding interfaces to '%s'", cd->toPrettyChars()); |
216 LOG_SCOPE; | 225 LOG_SCOPE; |
217 LLVM_AddBaseClassInterfaces(cd, &cd->baseclasses); | 226 LLVM_AddBaseClassInterfaces(cd, &cd->baseclasses); |
218 Logger::println("%d interfaces added", cd->irStruct->interfaces.size()); | 227 Logger::println("%d interfaces added", cd->irStruct->interfaceVec.size()); |
228 assert(cd->irStruct->interfaceVec.size() == cd->irStruct->interfaceMap.size()); | |
219 } | 229 } |
220 | 230 |
221 // add interface vtables at the end | 231 // add interface vtables at the end |
222 int interIdx = (int)fieldtypes.size(); | 232 int interIdx = (int)fieldtypes.size(); |
223 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 233 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) |
224 { | 234 { |
225 ClassDeclaration* id = i->first; | 235 IrInterface* iri = *i; |
226 IrInterface* iri = i->second; | 236 ClassDeclaration* id = iri->decl; |
227 | 237 |
228 // set vtbl type | 238 // set vtbl type |
229 TypeClass* itc = (TypeClass*)id->type; | 239 TypeClass* itc = (TypeClass*)id->type; |
230 const llvm::Type* ivtblTy = getPtrToType(itc->llvmVtblType->get()); | 240 const llvm::Type* ivtblTy = getPtrToType(itc->llvmVtblType->get()); |
231 fieldtypes.push_back(ivtblTy); | 241 fieldtypes.push_back(ivtblTy); |
234 iri->vtblTy = isaStruct(itc->llvmVtblType->get()); | 244 iri->vtblTy = isaStruct(itc->llvmVtblType->get()); |
235 | 245 |
236 // set index | 246 // set index |
237 iri->index = interIdx++; | 247 iri->index = interIdx++; |
238 } | 248 } |
239 Logger::println("%d interface vtables added", cd->irStruct->interfaces.size()); | 249 Logger::println("%d interface vtables added", cd->irStruct->interfaceVec.size()); |
250 assert(cd->irStruct->interfaceVec.size() == cd->irStruct->interfaceMap.size()); | |
240 | 251 |
241 // create type | 252 // create type |
242 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); | 253 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); |
243 | 254 |
244 // refine abstract types for stuff like: class C {C next;} | 255 // refine abstract types for stuff like: class C {C next;} |
355 | 366 |
356 // get interface info type | 367 // get interface info type |
357 const llvm::StructType* infoTy = DtoInterfaceInfoType(); | 368 const llvm::StructType* infoTy = DtoInterfaceInfoType(); |
358 | 369 |
359 // interface info array | 370 // interface info array |
360 if (!cd->irStruct->interfaces.empty()) { | 371 if (!cd->irStruct->interfaceVec.empty()) { |
361 // symbol name | 372 // symbol name |
362 std::string nam = "_D"; | 373 std::string nam = "_D"; |
363 nam.append(cd->mangle()); | 374 nam.append(cd->mangle()); |
364 nam.append("16__interfaceInfosZ"); | 375 nam.append("16__interfaceInfosZ"); |
365 // resolve array type | 376 // resolve array type |
366 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->irStruct->interfaces.size()); | 377 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->irStruct->interfaceVec.size()); |
367 // declare global | 378 // declare global |
368 irstruct->interfaceInfosTy = arrTy; | 379 irstruct->interfaceInfosTy = arrTy; |
369 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module); | 380 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module); |
370 } | 381 } |
371 | 382 |
372 // interfaces have no static initializer | 383 // interfaces have no static initializer |
373 // same goes for abstract classes | 384 // same goes for abstract classes |
374 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { | 385 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
375 // interface vtables | 386 // interface vtables |
376 unsigned idx = 0; | 387 unsigned idx = 0; |
377 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 388 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) |
378 { | 389 { |
379 ClassDeclaration* id = i->first; | 390 IrInterface* iri = *i; |
380 IrInterface* iri = i->second; | 391 ClassDeclaration* id = iri->decl; |
381 | 392 |
382 std::string nam("_D"); | 393 std::string nam("_D"); |
383 nam.append(cd->mangle()); | 394 nam.append(cd->mangle()); |
384 nam.append("11__interface"); | 395 nam.append("11__interface"); |
385 nam.append(id->mangle()); | 396 nam.append(id->mangle()); |
488 fieldinits.push_back(c); | 499 fieldinits.push_back(c); |
489 } | 500 } |
490 | 501 |
491 // last comes interface vtables | 502 // last comes interface vtables |
492 const llvm::StructType* infoTy = DtoInterfaceInfoType(); | 503 const llvm::StructType* infoTy = DtoInterfaceInfoType(); |
493 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 504 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) |
494 { | 505 { |
495 IrInterface* iri = i->second; | 506 IrInterface* iri = *i; |
496 iri->infoTy = infoTy; | 507 iri->infoTy = infoTy; |
508 | |
497 if (cd->isAbstract()) | 509 if (cd->isAbstract()) |
498 { | 510 { |
499 fieldinits.push_back(llvm::Constant::getNullValue(structtype->getElementType(iri->index))); | 511 fieldinits.push_back(llvm::Constant::getNullValue(structtype->getElementType(iri->index))); |
500 } | 512 } |
501 else | 513 else |
570 | 582 |
571 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); | 583 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); |
572 cd->irStruct->constVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); | 584 cd->irStruct->constVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); |
573 | 585 |
574 // create interface vtable const initalizers | 586 // create interface vtable const initalizers |
575 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 587 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) |
576 { | 588 { |
577 ClassDeclaration* id = i->first; | 589 IrInterface* iri = *i; |
590 BaseClass* b = iri->base; | |
591 | |
592 ClassDeclaration* id = iri->decl; | |
578 assert(id->type->ty == Tclass); | 593 assert(id->type->ty == Tclass); |
579 TypeClass* its = (TypeClass*)id->type; | 594 TypeClass* its = (TypeClass*)id->type; |
580 | |
581 IrInterface* iri = i->second; | |
582 BaseClass* b = iri->base; | |
583 | 595 |
584 const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get()); | 596 const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get()); |
585 | 597 |
586 // generate interface info initializer | 598 // generate interface info initializer |
587 std::vector<llvm::Constant*> infoInits; | 599 std::vector<llvm::Constant*> infoInits; |
705 cd->irStruct->vtbl->setInitializer(cd->irStruct->constVtbl); | 717 cd->irStruct->vtbl->setInitializer(cd->irStruct->constVtbl); |
706 | 718 |
707 // initialize interface vtables | 719 // initialize interface vtables |
708 IrStruct* irstruct = cd->irStruct; | 720 IrStruct* irstruct = cd->irStruct; |
709 std::vector<llvm::Constant*> infoInits; | 721 std::vector<llvm::Constant*> infoInits; |
710 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 722 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) |
711 { | 723 { |
712 IrInterface* iri = i->second; | 724 IrInterface* iri = *i; |
713 iri->vtbl->setInitializer(iri->vtblInit); | 725 iri->vtbl->setInitializer(iri->vtblInit); |
714 infoInits.push_back(iri->infoInit); | 726 infoInits.push_back(iri->infoInit); |
715 } | 727 } |
716 // initialize interface info array | 728 // initialize interface info array |
717 if (!infoInits.empty()) | 729 if (!infoInits.empty()) |
756 { | 768 { |
757 Logger::println("Resolving outer class"); | 769 Logger::println("Resolving outer class"); |
758 LOG_SCOPE; | 770 LOG_SCOPE; |
759 DValue* thisval = newexp->thisexp->toElem(gIR); | 771 DValue* thisval = newexp->thisexp->toElem(gIR); |
760 size_t idx = 2; | 772 size_t idx = 2; |
761 idx += tc->sym->irStruct->interfaces.size(); | 773 //idx += tc->sym->irStruct->interfaces.size(); |
762 llvm::Value* dst = thisval->getRVal(); | 774 llvm::Value* dst = thisval->getRVal(); |
763 llvm::Value* src = DtoGEPi(mem,0,idx,"tmp"); | 775 llvm::Value* src = DtoGEPi(mem,0,idx,"tmp"); |
764 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; | 776 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; |
765 DtoStore(dst, src); | 777 DtoStore(dst, src); |
766 } | 778 } |
768 else if (tc->sym->isNested()) | 780 else if (tc->sym->isNested()) |
769 { | 781 { |
770 Logger::println("Resolving nested context"); | 782 Logger::println("Resolving nested context"); |
771 LOG_SCOPE; | 783 LOG_SCOPE; |
772 size_t idx = 2; | 784 size_t idx = 2; |
773 idx += tc->sym->irStruct->interfaces.size(); | 785 //idx += tc->sym->irStruct->interfaces.size(); |
774 llvm::Value* nest = gIR->func()->decl->irFunc->nestedVar; | 786 llvm::Value* nest = gIR->func()->decl->irFunc->nestedVar; |
775 if (!nest) | 787 if (!nest) |
776 nest = gIR->func()->decl->irFunc->thisVar; | 788 nest = gIR->func()->decl->irFunc->thisVar; |
777 assert(nest); | 789 assert(nest); |
778 llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp"); | 790 llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp"); |
1062 unsigned r = LLVM_ClassOffsetToIndex(this, os, idx); | 1074 unsigned r = LLVM_ClassOffsetToIndex(this, os, idx); |
1063 assert(r != (unsigned)-1 && "Offset not found in any aggregate field"); | 1075 assert(r != (unsigned)-1 && "Offset not found in any aggregate field"); |
1064 // vtable is 0, monitor is 1 | 1076 // vtable is 0, monitor is 1 |
1065 r += 2; | 1077 r += 2; |
1066 // interface offset further | 1078 // interface offset further |
1067 r += vtblInterfaces->dim; | 1079 //r += vtblInterfaces->dim; |
1068 // the final index was not pushed | 1080 // the final index was not pushed |
1069 result.push_back(r); | 1081 result.push_back(r); |
1070 } | 1082 } |
1071 | 1083 |
1072 ////////////////////////////////////////////////////////////////////////////////////////// | 1084 ////////////////////////////////////////////////////////////////////////////////////////// |