From: Daniel Dunbar Date: Sun, 3 May 2009 08:55:17 +0000 (+0000) Subject: Coalesce the ivar offset calculation further. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1d7e539bbee1981faddf45284c492deab4ca2e01;p=clang Coalesce the ivar offset calculation further. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70683 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index d3b020d57e..218365e316 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -745,7 +745,8 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { // Get the size of instances. For runtimes that support late-bound instances // this should probably be something different (size just of instance // varaibles in this class, not superclasses?). - const llvm::Type *ObjTy = GetConcreteClassStruct(CGM, ClassDecl); + const llvm::Type *ObjTy = + CGObjCRuntime::GetConcreteClassStruct(CGM, ClassDecl); int instanceSize = CGM.getTargetData().getTypePaddedSize(ObjTy); // Collect information about instance variables. diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 61f5e796f0..a62b4c499b 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -69,19 +69,19 @@ static const FieldDecl *LookupFieldDeclForIvar(ASTContext &Context, return LookupFieldDeclForIvar(Context, Super, OIVD, Found); } -uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, - const ObjCInterfaceDecl *OID, - const ObjCIvarDecl *Ivar) { +static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, + const ObjCInterfaceDecl *OID, + const ObjCIvarDecl *Ivar) { assert(!OID->isForwardDecl() && "Invalid interface decl!"); 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::StructType *STy = + CGObjCRuntime::GetConcreteClassStruct(CGM, Container); const llvm::StructLayout *Layout = CGM.getTargetData().getStructLayout(STy); if (!Field->isBitField()) - return Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field)); + 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); @@ -91,7 +91,13 @@ uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, const llvm::Type *Ty = CGM.getTypes().ConvertTypeForMemRecursive(Field->getType()); Offset *= CGM.getTypes().getTargetData().getTypePaddedSizeInBits(Ty); - return (Offset + BFI.Begin) / 8; + return Offset + BFI.Begin; +} + +uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, + const ObjCInterfaceDecl *OID, + const ObjCIvarDecl *Ivar) { + return LookupFieldBitOffset(CGM, OID, Ivar) / 8; } LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, @@ -100,43 +106,28 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers, llvm::Value *Offset) { - // Force generation of the codegen information for this structure. - // - // FIXME: Remove once we don't use the bit-field lookup map. - (void) GetConcreteClassStruct(CGF.CGM, OID); - - // FIXME: For now, we use an implementation based on just computing - // the offset and calculating things directly. For optimization - // 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, Container); - - // (char *) BaseValue + // We need to compute the bit offset for the bit-field, the offset + // is to the byte. + uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, Ivar) % 8; + + // Compute (type*) ( (char *) BaseValue + Offset) llvm::Type *I8Ptr = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + QualType IvarTy = Ivar->getType(); + const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr); - // (char*)BaseValue + Offset_symbol V = CGF.Builder.CreateGEP(V, Offset, "add.ptr"); - // (type *)((char*)BaseValue + Offset_symbol) - const llvm::Type *IvarTy = - CGF.CGM.getTypes().ConvertTypeForMem(Ivar->getType()); - llvm::Type *ptrIvarTy = llvm::PointerType::getUnqual(IvarTy); - V = CGF.Builder.CreateBitCast(V, ptrIvarTy); + V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); if (Ivar->isBitField()) { - QualType IvarTy = Ivar->getType(); - CodeGenTypes::BitFieldInfo bitFieldInfo = - CGF.CGM.getTypes().getBitFieldInfo(Field); - return LValue::MakeBitfield(V, bitFieldInfo.Begin % 8, bitFieldInfo.Size, + uint64_t BitFieldSize = + Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); + return LValue::MakeBitfield(V, BitOffset, BitFieldSize, IvarTy->isSignedIntegerType(), IvarTy.getCVRQualifiers()|CVRQualifiers); } - LValue LV = LValue::MakeAddr(V, - Ivar->getType().getCVRQualifiers()|CVRQualifiers, - CGF.CGM.getContext().getObjCGCAttrKind(Ivar->getType())); + LValue LV = LValue::MakeAddr(V, IvarTy.getCVRQualifiers()|CVRQualifiers, + CGF.CGM.getContext().getObjCGCAttrKind(IvarTy)); LValue::SetObjCIvar(LV, true); return LV; } @@ -1865,7 +1856,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getNameAsString(), Interface->protocol_begin(), Interface->protocol_end()); - const llvm::Type *InterfaceTy = GetConcreteClassStruct(CGM, Interface); + const llvm::Type *InterfaceTy = + CGObjCRuntime::GetConcreteClassStruct(CGM, Interface); unsigned Flags = eClassFlags_Factory; unsigned Size = CGM.getTargetData().getTypePaddedSize(InterfaceTy); diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index c275a4d720..19a1d8c16d 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -61,16 +61,18 @@ namespace CodeGen { /// Implements runtime-specific code generation functions. class CGObjCRuntime { -protected: +public: // Utility functions for unified ivar access. These need to // eventually be folded into other places (the structure layout // code). /// Return the (fixed) LLVM struct type for the interface. This is /// only very meaningful for runtimes which use a non-fragile ABI. + static const llvm::StructType * GetConcreteClassStruct(CodeGen::CodeGenModule &CGM, const ObjCInterfaceDecl *OID); +protected: /// Compute an offset to the given ivar, suitable for passing to /// EmitValueForIvarAtOffset. Note that the correct handling of /// bit-fields is carefully coordinated by these two, use caution!