From: Daniel Dunbar Date: Sun, 3 May 2009 13:15:50 +0000 (+0000) Subject: Use ASTRecordLayout for computing ivar offsets instead of shadow X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=532d4daa038d972240138e2fd6e1122517340833;p=clang Use ASTRecordLayout for computing ivar offsets instead of shadow struct. - We still need to do more lookup than necessary because ivars don't live in a reasonable DeclContext. - The only remaining client of the interface shadow struct is the ivar layout bitmap. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70756 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index f58291ee21..ac70cef499 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -744,6 +744,8 @@ const RecordDecl *ASTContext::addRecordToClass(const ObjCInterfaceDecl *D) { const ASTRecordLayout & ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl) { + assert(!D->isForwardDecl() && "Invalid interface decl!"); + // Look up this layout, if already laid out, return what we have. ObjCContainerDecl *Key = Impl ? (ObjCContainerDecl*) Impl : (ObjCContainerDecl*) D; @@ -768,6 +770,9 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, ASTRecordLayout *NewEntry = NULL; if (ObjCInterfaceDecl *SD = D->getSuperClass()) { + // FIXME: This increment of FieldCount is wrong, we don't actually + // count the super class as a member (see the field index passed + // to LayoutField below). FieldCount++; const ASTRecordLayout &SL = getASTObjCInterfaceLayout(SD); unsigned Alignment = SL.getAlignment(); diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 1ab4bf1056..a2ef680e2b 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -43,57 +43,59 @@ GetConcreteClassStruct(CodeGen::CodeGenModule &CGM, return cast(CGM.getTypes().ConvertTagDeclType(RD)); } - -/// LookupFieldDeclForIvar - looks up a field decl in the laid out -/// storage which matches this 'ivar'. +/// FindIvarInterface - Find the interface containing the ivar. /// -static const FieldDecl *LookupFieldDeclForIvar(ASTContext &Context, - const ObjCInterfaceDecl *OID, - 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()); +/// FIXME: We shouldn't need to do this, the containing context should +/// be fixed. +static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, + const ObjCInterfaceDecl *OID, + const ObjCIvarDecl *OIVD, + unsigned &Index) { + const ObjCInterfaceDecl *Super = OID->getSuperClass(); - if (Lookup.first != Lookup.second) { - Found = OID; - return cast(*Lookup.first); + // FIXME: The index here is closely tied to how + // ASTContext::getObjCLayout is implemented. This should be fixed to + // get the information from the layout directly. + Index = 0; + for (ObjCInterfaceDecl::ivar_iterator IVI = OID->ivar_begin(), + IVE = OID->ivar_end(); IVI != IVE; ++IVI, ++Index) + if (OIVD == *IVI) + return OID; + + // Also look in synthesized ivars. + for (ObjCInterfaceDecl::prop_iterator I = OID->prop_begin(Context), + E = OID->prop_end(Context); I != E; ++I) { + if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl()) { + if (OIVD == Ivar) + return OID; + ++Index; + } } - // If lookup failed, try the superclass. - // - // FIXME: This is slow, we shouldn't need to do this. - const ObjCInterfaceDecl *Super = OID->getSuperClass(); - assert(Super && "field decl not found!"); - return LookupFieldDeclForIvar(Context, Super, OIVD, Found); + // Otherwise check in the super class. + if (Super) + return FindIvarInterface(Context, Super, OIVD, Index); + + return 0; } static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, const ObjCInterfaceDecl *OID, const ObjCImplementationDecl *ID, const ObjCIvarDecl *Ivar) { - assert(!OID->isForwardDecl() && "Invalid interface decl!"); - const ObjCInterfaceDecl *Container; - const FieldDecl *Field = - LookupFieldDeclForIvar(CGM.getContext(), OID, Ivar, Container); - const llvm::StructType *STy = - GetConcreteClassStruct(CGM, Container); - const llvm::StructLayout *Layout = - CGM.getTargetData().getStructLayout(STy); - if (!Field->isBitField()) - return Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field)) * 8; - - // FIXME. Must be a better way of getting a bitfield base offset. - CodeGenTypes::BitFieldInfo BFI = CGM.getTypes().getBitFieldInfo(Field); - // FIXME: The "field no" for bitfields is something completely - // different; it is the offset in multiples of the base type size! - uint64_t Offset = CGM.getTypes().getLLVMFieldNo(Field); - const llvm::Type *Ty = - CGM.getTypes().ConvertTypeForMemRecursive(Field->getType()); - Offset *= CGM.getTypes().getTargetData().getTypePaddedSizeInBits(Ty); - return Offset + BFI.Begin; + unsigned Index; + const ObjCInterfaceDecl *Container = + FindIvarInterface(CGM.getContext(), OID, Ivar, Index); + assert(Container && "Unable to find ivar container"); + + // If we know have an implementation (and the ivar is in it) then + // look up in the implementation layout. + const ASTRecordLayout *RL; + if (ID && ID->getClassInterface() == Container) + RL = &CGM.getContext().getASTObjCImplementationLayout(ID); + else + RL = &CGM.getContext().getASTObjCInterfaceLayout(Container); + return RL->getFieldOffset(Index); } uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,