diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-04-22 17:43:55 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-04-22 17:43:55 +0000 |
commit | a80a0f6398df06c018af779a7ca82a29172c45d1 (patch) | |
tree | 391daaf4f55231fdfa41ef8dd2eeb3df5424af90 /lib/CodeGen | |
parent | 01f4fa2928b22f88fb91035b9f000087ad25003d (diff) |
Reapply r69771, with updates & fixes:
Rework the shadow struct that is layed out for Objective-C classes.
- Superclasses are now always laid out in their shadow structure at
the first field.
- Prior to this, the entire class heirarchy was flattened into a
single structure which meant that alignment, padding, and bitfields
were incorrect (the ASTRecordLayout was correct however, which
meant our debug info didn't coincide with ivar offsets, for
example).
- This is still very suboptimal (for example, ivar are looked up
recursively, but I believe the ivar layout itself is now at least
close to correct.
- <rdar://problem/6773388> error: objc[29823]: layout bitmap sliding
backwards
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69811 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index a993963680..e93ea2f19b 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -47,26 +47,38 @@ CGObjCRuntime::GetConcreteClassStruct(CodeGen::CodeGenModule &CGM, /// static const FieldDecl *LookupFieldDeclForIvar(ASTContext &Context, const ObjCInterfaceDecl *OID, - const ObjCIvarDecl *OIVD) { + const ObjCIvarDecl *OIVD, + const ObjCInterfaceDecl *&Found) { assert(!OID->isForwardDecl() && "Invalid interface decl!"); const RecordDecl *RecordForDecl = Context.addRecordToClass(OID); assert(RecordForDecl && "lookupFieldDeclForIvar no storage for class"); DeclContext::lookup_const_result Lookup = RecordForDecl->lookup(Context, OIVD->getDeclName()); - assert((Lookup.first != Lookup.second) && "field decl not found"); - return cast<FieldDecl>(*Lookup.first); + + if (Lookup.first != Lookup.second) { + Found = OID; + return cast<FieldDecl>(*Lookup.first); + } + + // If lookup failed, try the superclass. + // + // FIXME: This is slow, we shouldn't need to do this. + const ObjCInterfaceDecl *Super = OID->getSuperClass(); + assert(OID && "field decl not found!"); + return LookupFieldDeclForIvar(Context, Super, OIVD, Found); } uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, const ObjCInterfaceDecl *OID, const ObjCIvarDecl *Ivar) { assert(!OID->isForwardDecl() && "Invalid interface decl!"); - QualType T = CGM.getContext().getObjCInterfaceType(OID); - const llvm::StructType *STy = GetConcreteClassStruct(CGM, OID); + const ObjCInterfaceDecl *Container; + const FieldDecl *Field = + LookupFieldDeclForIvar(CGM.getContext(), OID, Ivar, Container); + QualType T = CGM.getContext().getObjCInterfaceType(Container); + const llvm::StructType *STy = GetConcreteClassStruct(CGM, Container); const llvm::StructLayout *Layout = CGM.getTargetData().getStructLayout(STy); - const FieldDecl *Field = - LookupFieldDeclForIvar(CGM.getContext(), OID, Ivar); if (!Field->isBitField()) return Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field)); @@ -97,8 +109,9 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, // purposes, it would be cleaner to use a GEP on the proper type // since the structure layout is fixed; however for that we need to // be able to walk the class chain for an Ivar. + const ObjCInterfaceDecl *Container; const FieldDecl *Field = - LookupFieldDeclForIvar(CGF.CGM.getContext(), OID, Ivar); + LookupFieldDeclForIvar(CGF.CGM.getContext(), OID, Ivar, Container); // (char *) BaseValue llvm::Type *I8Ptr = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); |