[cfe-commits] r69787 - in /cfe/trunk/lib/CodeGen: CGObjCGNU.cpp CGObjCMac.cpp CGObjCRuntime.h

Daniel Dunbar daniel at zuster.org
Wed Apr 22 00:32:20 PDT 2009


Author: ddunbar
Date: Wed Apr 22 02:32:20 2009
New Revision: 69787

URL: http://llvm.org/viewvc/llvm-project?rev=69787&view=rev
Log:
Merge ivar access amongst the three runtimes.
 - For now, this means we are always doing the address computations by
   hand instead of constructing a proper GEP. Right now, however, this
   is less important than having fewer entry points to dealing with
   Objective-C interface layout.

Modified:
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CGObjCRuntime.h

Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=69787&r1=69786&r2=69787&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Wed Apr 22 02:32:20 2009
@@ -1082,32 +1082,14 @@
                                        const ObjCIvarDecl *Ivar,
                                        unsigned CVRQualifiers) {
   const ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl();
-  const FieldDecl *Field = ID->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
-  if (Ivar->isBitField()) 
-    return CGF.EmitLValueForBitfield(BaseValue, const_cast<FieldDecl *>(Field), 
-                                 CVRQualifiers);
-  // TODO:  Add a special case for isa (index 0)
-  unsigned Index = CGM.getTypes().getLLVMFieldNo(Field);
-  llvm::Value *V = CGF.Builder.CreateStructGEP(BaseValue, Index, "tmp");
-  LValue LV = LValue::MakeAddr(V, 
-                Ivar->getType().getCVRQualifiers()|CVRQualifiers);
-  LValue::SetObjCIvar(LV, true);
-  return LV;
+  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
+                                  EmitIvarOffset(CGF, ID, Ivar));
 }
 
 llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
                          const ObjCInterfaceDecl *Interface,
                          const ObjCIvarDecl *Ivar) {
-  const llvm::Type *InterfaceLTy =
-    CGM.getTypes().ConvertType(
-                            CGM.getContext().getObjCInterfaceType(Interface));
-  const llvm::StructLayout *Layout =
-    CGM.getTargetData().getStructLayout(cast<llvm::StructType>(InterfaceLTy));
-  const FieldDecl *Field = 
-    Interface->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
-  uint64_t Offset =
-    Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
-  
+  uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar);
   return llvm::ConstantInt::get(
                             CGM.getTypes().ConvertType(CGM.getContext().LongTy),
                             Offset);

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=69787&r1=69786&r2=69787&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Wed Apr 22 02:32:20 2009
@@ -29,6 +29,78 @@
 using namespace clang;
 using namespace CodeGen;
 
+// Common CGObjCRuntime functions, these don't belong here, but they
+// don't belong in CGObjCRuntime either so we will live with it for
+// now.
+
+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 *InterfaceTy = 
+    cast<llvm::StructType>(CGM.getTypes().ConvertType(T));
+  const llvm::StructLayout *Layout = 
+    CGM.getTargetData().getStructLayout(InterfaceTy);
+  const FieldDecl *Field = 
+    OID->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
+  if (!Field->isBitField())
+    return Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
+  
+  // 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) / 8;
+}
+
+LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
+                                               const ObjCInterfaceDecl *OID,
+                                               llvm::Value *BaseValue,
+                                               const ObjCIvarDecl *Ivar,
+                                               unsigned CVRQualifiers,
+                                               llvm::Value *Offset) {
+  // 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 FieldDecl *Field = 
+    OID->lookupFieldDeclForIvar(CGF.CGM.getContext(), Ivar);
+  
+  // (char *) BaseValue
+  llvm::Type *I8Ptr = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+  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);
+  
+  if (Ivar->isBitField()) {
+    QualType FieldTy = Field->getType();
+    CodeGenTypes::BitFieldInfo bitFieldInfo =
+                                 CGF.CGM.getTypes().getBitFieldInfo(Field);
+    return LValue::MakeBitfield(V, bitFieldInfo.Begin % 8, bitFieldInfo.Size,
+                                FieldTy->isSignedIntegerType(),
+                                FieldTy.getCVRQualifiers()|CVRQualifiers);
+  }
+
+  LValue LV = LValue::MakeAddr(V, 
+              Ivar->getType().getCVRQualifiers()|CVRQualifiers,
+              CGF.CGM.getContext().getObjCGCAttrKind(Ivar->getType()));
+  LValue::SetObjCIvar(LV, true);
+  return LV;
+}
+
+///
+
 namespace {
 
   typedef std::vector<llvm::Constant*> ConstantVector;
@@ -731,10 +803,6 @@
   /// defined. The return value has type ProtocolPtrTy.
   llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
 
-  /// GetIvarBaseOffset - returns ivars byte offset.
-  uint64_t GetIvarBaseOffset(const llvm::StructLayout *Layout,
-                             const FieldDecl *Field);
-  
   /// GetFieldBaseOffset - return's field byte offset.
   uint64_t GetFieldBaseOffset(const ObjCInterfaceDecl *OI,
                               const llvm::StructLayout *Layout,
@@ -2015,7 +2083,6 @@
   
   ObjCInterfaceDecl *OID = 
     const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
-  const llvm::StructLayout *Layout = GetInterfaceDeclStructLayout(OID);
   
   llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
   GetNamedIvarList(OID, OIvars);
@@ -2026,7 +2093,7 @@
     Ivar[0] = GetMethodVarName(Field->getIdentifier());
     Ivar[1] = GetMethodVarType(Field);
     Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, 
-                                     GetIvarBaseOffset(Layout, Field));
+                                     ComputeIvarBaseOffset(CGM, OID, IVD));
     Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
   }
 
@@ -2124,32 +2191,14 @@
   return Method;
 }
 
-uint64_t CGObjCCommonMac::GetIvarBaseOffset(const llvm::StructLayout *Layout,
-                                            const FieldDecl *Field) {
-  if (!Field->isBitField())
-    return Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
-  
-  // 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) / 8;
-}
-
 /// GetFieldBaseOffset - return the field's byte offset.
 uint64_t CGObjCCommonMac::GetFieldBaseOffset(const ObjCInterfaceDecl *OI,
                                              const llvm::StructLayout *Layout,
                                              const FieldDecl *Field) {
-  // Is this a c struct?
+  // Is this a C struct?
   if (!OI)
     return Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
-  const ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field);
-  const FieldDecl *FD = OI->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
-  return GetIvarBaseOffset(Layout, FD);
+  return ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
 }
 
 llvm::GlobalVariable *
@@ -2628,27 +2677,14 @@
                                        const ObjCIvarDecl *Ivar,
                                        unsigned CVRQualifiers) {
   const ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl();
-  const FieldDecl *Field = ID->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
-  if (Ivar->isBitField())
-    return CGF.EmitLValueForBitfield(BaseValue, const_cast<FieldDecl *>(Field),
-                                     CVRQualifiers);
-  // TODO:  Add a special case for isa (index 0)
-  unsigned Index = CGM.getTypes().getLLVMFieldNo(Field);
-  llvm::Value *V = CGF.Builder.CreateStructGEP(BaseValue, Index, "tmp");
-  LValue LV = LValue::MakeAddr(V, 
-               Ivar->getType().getCVRQualifiers()|CVRQualifiers,
-               CGM.getContext().getObjCGCAttrKind(Ivar->getType()));
-  LValue::SetObjCIvar(LV, true);
-  return LV;
+  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
+                                  EmitIvarOffset(CGF, ID, Ivar));
 }
 
 llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
                                        const ObjCInterfaceDecl *Interface,
                                        const ObjCIvarDecl *Ivar) {
-  const llvm::StructLayout *Layout = GetInterfaceDeclStructLayout(Interface);
-  const FieldDecl *Field = 
-    Interface->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
-  uint64_t Offset = GetIvarBaseOffset(Layout, Field);
+  uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
   return llvm::ConstantInt::get(
                             CGM.getTypes().ConvertType(CGM.getContext().LongTy),
                             Offset);
@@ -4219,62 +4255,28 @@
   return GV;
 }
 
-/// countInheritedIvars - count number of ivars in class and its super class(s)
-///
-static int countInheritedIvars(const ObjCInterfaceDecl *OI, 
-                               ASTContext &Context) {
-  int count = 0;
-  if (!OI)
-    return 0;
-  const ObjCInterfaceDecl *SuperClass = OI->getSuperClass();
-  if (SuperClass)
-    count += countInheritedIvars(SuperClass, Context);
-  for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
-       E = OI->ivar_end(); I != E; ++I)
-    ++count;
-  // look into properties.
-  for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(Context),
-       E = OI->prop_end(Context); I != E; ++I) {
-    if ((*I)->getPropertyIvarDecl())
-      ++count;
-  }
-  return count;
-}
-
 void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCInterfaceDecl *OID,
                                               uint32_t &InstanceStart,
                                               uint32_t &InstanceSize) {
-  assert(!OID->isForwardDecl() && "Invalid interface decl!");
-  const llvm::StructLayout *Layout = GetInterfaceDeclStructLayout(OID);
-    
-  int countSuperClassIvars = countInheritedIvars(OID->getSuperClass(),
-                                                 CGM.getContext());
-  const RecordDecl *RD = CGM.getContext().addRecordToClass(OID);
-  RecordDecl::field_iterator firstField = RD->field_begin(CGM.getContext());
-  RecordDecl::field_iterator lastField = RD->field_end(CGM.getContext());
-  while (countSuperClassIvars-- > 0) {
-    lastField = firstField;
-    ++firstField;
-  }
-    
-  for (RecordDecl::field_iterator e = RD->field_end(CGM.getContext()),
-         ifield = firstField; ifield != e; ++ifield)
-    lastField = ifield;
-    
-  InstanceStart = InstanceSize = 0;
-  if (lastField != RD->field_end(CGM.getContext())) {
-    FieldDecl *Field = *lastField;
-    const llvm::Type *FieldTy =
-      CGM.getTypes().ConvertTypeForMem(Field->getType());
-    unsigned Size = CGM.getTargetData().getTypePaddedSize(FieldTy);
-    InstanceSize = GetIvarBaseOffset(Layout, Field) + Size;
-    if (firstField == RD->field_end(CGM.getContext()))
-      InstanceStart = InstanceSize;
-    else {
-      Field = *firstField;
-      InstanceStart =  GetIvarBaseOffset(Layout, Field);
-    }
+  // Find first and last (non-padding) ivars in this interface.
+
+  // FIXME: Use iterator.
+  llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
+  GetNamedIvarList(OID, OIvars);
+
+  if (OIvars.empty()) {
+    InstanceStart = InstanceSize = 0;
+    return;
   }
+
+  const ObjCIvarDecl *First = OIvars.front();
+  const ObjCIvarDecl *Last = OIvars.back();
+
+  InstanceStart = ComputeIvarBaseOffset(CGM, OID, First);
+  const llvm::Type *FieldTy =
+    CGM.getTypes().ConvertTypeForMem(Last->getType());
+  unsigned Size = CGM.getTargetData().getTypePaddedSize(FieldTy);
+  InstanceSize = ComputeIvarBaseOffset(CGM, OID, Last) + Size;
 }
 
 void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
@@ -4639,7 +4641,6 @@
   assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
   
   // FIXME. Consolidate this with similar code in GenerateClass.
-  const llvm::StructLayout *Layout = GetInterfaceDeclStructLayout(OID);
   
   // Collect declared and synthesized ivars in a small vector.
   llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
@@ -4649,7 +4650,7 @@
     ObjCIvarDecl *IVD = OIvars[i];
     const FieldDecl *Field = OID->lookupFieldDeclForIvar(CGM.getContext(), IVD);
     Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD, 
-                                GetIvarBaseOffset(Layout, Field));
+                                ComputeIvarBaseOffset(CGM, OID, IVD));
     Ivar[1] = GetMethodVarName(Field->getIdentifier());
     Ivar[2] = GetMethodVarType(Field);
     const llvm::Type *FieldTy =
@@ -4922,34 +4923,8 @@
                                              const ObjCIvarDecl *Ivar,
                                              unsigned CVRQualifiers) {
   const ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl();
-  const FieldDecl *Field = ID->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
-  llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
-  
-  // (char *) BaseValue
-  llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, ObjCTypes.Int8PtrTy);
-  llvm::Value *Offset = CGF.Builder.CreateLoad(IvarOffsetGV);
-  // (char*)BaseValue + Offset_symbol
-  V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
-  // (type *)((char*)BaseValue + Offset_symbol)
-  const llvm::Type *IvarTy = 
-    CGM.getTypes().ConvertTypeForMem(Ivar->getType());
-  llvm::Type *ptrIvarTy = llvm::PointerType::getUnqual(IvarTy);
-  V = CGF.Builder.CreateBitCast(V, ptrIvarTy);
-  
-  if (Ivar->isBitField()) {
-    QualType FieldTy = Field->getType();
-    CodeGenTypes::BitFieldInfo bitFieldInfo =
-                                 CGM.getTypes().getBitFieldInfo(Field);
-    return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size,
-                                FieldTy->isSignedIntegerType(),
-                                FieldTy.getCVRQualifiers()|CVRQualifiers);
-  }
-
-  LValue LV = LValue::MakeAddr(V, 
-              Ivar->getType().getCVRQualifiers()|CVRQualifiers,
-              CGM.getContext().getObjCGCAttrKind(Ivar->getType()));
-  LValue::SetObjCIvar(LV, true);
-  return LV;
+  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
+                                  EmitIvarOffset(CGF, ID, Ivar));
 }
 
 llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(

Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=69787&r1=69786&r2=69787&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Wed Apr 22 02:32:20 2009
@@ -25,10 +25,11 @@
 
 namespace llvm {
   class Constant;
+  class Function;
+  class Module;
+  class StructLayout;
   class Type;
   class Value;
-  class Module;
-  class Function;
 }
 
 namespace clang {
@@ -36,6 +37,7 @@
   class CodeGenFunction;
 }
 
+  class FieldDecl;
   class ObjCAtTryStmt;
   class ObjCAtThrowStmt;
   class ObjCAtSynchronizedStmt;
@@ -58,6 +60,24 @@
 
 /// Implements runtime-specific code generation functions.
 class CGObjCRuntime {
+protected:
+  // Utility functions for unified ivar access. These need to
+  // eventually be folded into other places (the structure layout
+  // code).
+
+  // 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!
+  uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
+                                 const ObjCInterfaceDecl *OID,
+                                 const ObjCIvarDecl *Ivar);
+
+  LValue EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
+                                  const ObjCInterfaceDecl *OID,
+                                  llvm::Value *BaseValue,
+                                  const ObjCIvarDecl *Ivar,
+                                  unsigned CVRQualifiers,
+                                  llvm::Value *Offset);  
 
 public:
   virtual ~CGObjCRuntime();





More information about the cfe-commits mailing list