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 //////////////////////////////////////////////////////////////////////////////////////////