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.

llvm-svn: 70756
This commit is contained in:
Daniel Dunbar 2009-05-03 13:15:50 +00:00
parent e31559576f
commit 80b4eef686
2 changed files with 48 additions and 41 deletions

View File

@ -744,6 +744,8 @@ const RecordDecl *ASTContext::addRecordToClass(const ObjCInterfaceDecl *D) {
const ASTRecordLayout & const ASTRecordLayout &
ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl) { const ObjCImplementationDecl *Impl) {
assert(!D->isForwardDecl() && "Invalid interface decl!");
// Look up this layout, if already laid out, return what we have. // Look up this layout, if already laid out, return what we have.
ObjCContainerDecl *Key = ObjCContainerDecl *Key =
Impl ? (ObjCContainerDecl*) Impl : (ObjCContainerDecl*) D; Impl ? (ObjCContainerDecl*) Impl : (ObjCContainerDecl*) D;
@ -768,6 +770,9 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
ASTRecordLayout *NewEntry = NULL; ASTRecordLayout *NewEntry = NULL;
if (ObjCInterfaceDecl *SD = D->getSuperClass()) { 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++; FieldCount++;
const ASTRecordLayout &SL = getASTObjCInterfaceLayout(SD); const ASTRecordLayout &SL = getASTObjCInterfaceLayout(SD);
unsigned Alignment = SL.getAlignment(); unsigned Alignment = SL.getAlignment();

View File

@ -43,57 +43,59 @@ GetConcreteClassStruct(CodeGen::CodeGenModule &CGM,
return cast<llvm::StructType>(CGM.getTypes().ConvertTagDeclType(RD)); return cast<llvm::StructType>(CGM.getTypes().ConvertTagDeclType(RD));
} }
/// FindIvarInterface - Find the interface containing the ivar.
/// LookupFieldDeclForIvar - looks up a field decl in the laid out
/// storage which matches this 'ivar'.
/// ///
static const FieldDecl *LookupFieldDeclForIvar(ASTContext &Context, /// FIXME: We shouldn't need to do this, the containing context should
const ObjCInterfaceDecl *OID, /// be fixed.
const ObjCIvarDecl *OIVD, static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
const ObjCInterfaceDecl *&Found) { const ObjCInterfaceDecl *OID,
assert(!OID->isForwardDecl() && "Invalid interface decl!"); const ObjCIvarDecl *OIVD,
const RecordDecl *RecordForDecl = Context.addRecordToClass(OID); unsigned &Index) {
assert(RecordForDecl && "lookupFieldDeclForIvar no storage for class"); const ObjCInterfaceDecl *Super = OID->getSuperClass();
DeclContext::lookup_const_result Lookup =
RecordForDecl->lookup(Context, OIVD->getDeclName());
if (Lookup.first != Lookup.second) { // FIXME: The index here is closely tied to how
Found = OID; // ASTContext::getObjCLayout is implemented. This should be fixed to
return cast<FieldDecl>(*Lookup.first); // 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. // Otherwise check in the super class.
// if (Super)
// FIXME: This is slow, we shouldn't need to do this. return FindIvarInterface(Context, Super, OIVD, Index);
const ObjCInterfaceDecl *Super = OID->getSuperClass();
assert(Super && "field decl not found!"); return 0;
return LookupFieldDeclForIvar(Context, Super, OIVD, Found);
} }
static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
const ObjCInterfaceDecl *OID, const ObjCInterfaceDecl *OID,
const ObjCImplementationDecl *ID, const ObjCImplementationDecl *ID,
const ObjCIvarDecl *Ivar) { const ObjCIvarDecl *Ivar) {
assert(!OID->isForwardDecl() && "Invalid interface decl!"); unsigned Index;
const ObjCInterfaceDecl *Container; const ObjCInterfaceDecl *Container =
const FieldDecl *Field = FindIvarInterface(CGM.getContext(), OID, Ivar, Index);
LookupFieldDeclForIvar(CGM.getContext(), OID, Ivar, Container); assert(Container && "Unable to find ivar container");
const llvm::StructType *STy =
GetConcreteClassStruct(CGM, Container); // If we know have an implementation (and the ivar is in it) then
const llvm::StructLayout *Layout = // look up in the implementation layout.
CGM.getTargetData().getStructLayout(STy); const ASTRecordLayout *RL;
if (!Field->isBitField()) if (ID && ID->getClassInterface() == Container)
return Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field)) * 8; RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
else
// FIXME. Must be a better way of getting a bitfield base offset. RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
CodeGenTypes::BitFieldInfo BFI = CGM.getTypes().getBitFieldInfo(Field); return RL->getFieldOffset(Index);
// 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;
} }
uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,