]> granicus.if.org Git - clang/commitdiff
Coalesce the ivar offset calculation further.
authorDaniel Dunbar <daniel@zuster.org>
Sun, 3 May 2009 08:55:17 +0000 (08:55 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Sun, 3 May 2009 08:55:17 +0000 (08:55 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70683 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGObjCGNU.cpp
lib/CodeGen/CGObjCMac.cpp
lib/CodeGen/CGObjCRuntime.h

index d3b020d57e5cd7670bf2d74f7d3f156a495bf3a9..218365e316fe7b316a3533e64687d653a33ae47b 100644 (file)
@@ -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.
index 61f5e796f0fbd5b38a5e65cb928a30d2d791fc46..a62b4c499b5430ed0117f37d3991adadbcec5274 100644 (file)
@@ -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);
 
index c275a4d72019b280131360e75fc9ba124c06d0ac..19a1d8c16d03e988de6e1c6633f46745844cebbc 100644 (file)
@@ -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!