]> granicus.if.org Git - clang/commitdiff
Code gen. for ivar references; including bitfield
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 15 Dec 2008 20:35:07 +0000 (20:35 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 15 Dec 2008 20:35:07 +0000 (20:35 +0000)
ivars.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61043 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclObjC.h
lib/AST/DeclObjC.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGObjC.cpp
lib/CodeGen/CGObjCGNU.cpp
lib/CodeGen/CGObjCMac.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/CodeGenTypes.cpp
lib/CodeGen/CodeGenTypes.h

index 8f9bc2f01c64b20c0892054c68ab979ea0a02422..333dcd34010280bb4d6ff2856b919f7d277ef38c 100644 (file)
@@ -384,7 +384,8 @@ public:
    
   void addInstanceVariablesToClass(ObjCIvarDecl **ivars, unsigned numIvars,
                                    SourceLocation RBracLoc);
-  FieldDecl *lookupFieldDeclForIvar(ASTContext &Context, ObjCIvarDecl *ivar);
+  FieldDecl *lookupFieldDeclForIvar(ASTContext &Context, 
+                                    const ObjCIvarDecl *ivar);
   void addLayoutToClass(ASTContext &Context);
 
   void addMethods(ObjCMethodDecl **insMethods, unsigned numInsMembers,
index 27e6a6df65eef946d613d548cfd32fbb612550b4..50f45e85798c883bf4178ec12228514be389b6ac 100644 (file)
@@ -367,7 +367,7 @@ void ObjCInterfaceDecl::addInstanceVariablesToClass(ObjCIvarDecl **ivars,
 /// storage which matches this 'ivar'.
 ///
 FieldDecl *ObjCInterfaceDecl::lookupFieldDeclForIvar(ASTContext &Context, 
-                                                     ObjCIvarDecl *ivar) {
+                                                     const ObjCIvarDecl *ivar) {
   assert(RecordForDecl && "lookupFieldDeclForIvar no storage for class");
   DeclarationName Member = ivar->getDeclName();
   DeclContext::lookup_result Lookup = RecordForDecl->lookup(Context, Member);
@@ -392,7 +392,8 @@ void ObjCInterfaceDecl::addLayoutToClass(ASTContext &Context)
   for (unsigned int i = 0; i != RecFields.size(); i++) {
     FieldDecl *Field =  FieldDecl::Create(Context, RD, SourceLocation(), 
                                           RecFields[i]->getIdentifier(),
-                                          RecFields[i]->getType(), 0, false, 0);
+                                          RecFields[i]->getType(), 
+                                          RecFields[i]->getBitWidth(), false, 0);
     RD->addDecl(Context, Field);
   }
   RD->completeDefinition(Context);
index a7a64e3860aeb1b9a9adc270ff0b0d6419dd5659..31b63d1fbcdf2268192a26455dd63674c0d5d73a 100644 (file)
@@ -788,36 +788,41 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
   return MemExpLV;
 }
 
+LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value* BaseValue,
+                                              FieldDecl* Field,
+                                              unsigned CVRQualifiers,
+                                              unsigned idx) {
+  // FIXME: CodeGenTypes should expose a method to get the appropriate
+  // type for FieldTy (the appropriate type is ABI-dependent).
+  const llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(Field->getType());
+  const llvm::PointerType *BaseTy =
+  cast<llvm::PointerType>(BaseValue->getType());
+  unsigned AS = BaseTy->getAddressSpace();
+  BaseValue = Builder.CreateBitCast(BaseValue,
+                                    llvm::PointerType::get(FieldTy, AS),
+                                    "tmp");
+  llvm::Value *V = Builder.CreateGEP(BaseValue,
+                              llvm::ConstantInt::get(llvm::Type::Int32Ty, idx),
+                              "tmp");
+  
+  CodeGenTypes::BitFieldInfo bitFieldInfo = 
+    CGM.getTypes().getBitFieldInfo(Field);
+  return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size,
+                              Field->getType()->isSignedIntegerType(),
+                            Field->getType().getCVRQualifiers()|CVRQualifiers);
+}
+
 LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue,
                                            FieldDecl* Field,
                                            bool isUnion,
                                            unsigned CVRQualifiers)
 {
-  llvm::Value *V;
   unsigned idx = CGM.getTypes().getLLVMFieldNo(Field);
 
-  if (Field->isBitField()) {
-    // FIXME: CodeGenTypes should expose a method to get the appropriate
-    // type for FieldTy (the appropriate type is ABI-dependent).
-    const llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(Field->getType());
-    const llvm::PointerType *BaseTy =
-      cast<llvm::PointerType>(BaseValue->getType());
-    unsigned AS = BaseTy->getAddressSpace();
-    BaseValue = Builder.CreateBitCast(BaseValue,
-                                      llvm::PointerType::get(FieldTy, AS),
-                                      "tmp");
-    V = Builder.CreateGEP(BaseValue,
-                          llvm::ConstantInt::get(llvm::Type::Int32Ty, idx),
-                          "tmp");
-
-    CodeGenTypes::BitFieldInfo bitFieldInfo =
-      CGM.getTypes().getBitFieldInfo(Field);
-    return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size,
-                                Field->getType()->isSignedIntegerType(),
-                            Field->getType().getCVRQualifiers()|CVRQualifiers);
-  }
+  if (Field->isBitField())
+    return EmitLValueForBitfield(BaseValue, Field, CVRQualifiers, idx);
   
-  V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
+  llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
 
   // Match union field type.
   if (isUnion) {
@@ -944,8 +949,9 @@ llvm::Value *CodeGenFunction::EmitIvarOffset(ObjCInterfaceDecl *Interface,
     CGM.getTypes().ConvertType(getContext().getObjCInterfaceType(Interface));
   const llvm::StructLayout *Layout =
     CGM.getTargetData().getStructLayout(cast<llvm::StructType>(InterfaceLTy));
+  FieldDecl *Field = Interface->lookupFieldDeclForIvar(getContext(), Ivar);
   uint64_t Offset = 
-    Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Ivar));
+    Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
   
   return llvm::ConstantInt::get(CGM.getTypes().ConvertType(getContext().LongTy),
                                 Offset);                                                             
@@ -953,17 +959,18 @@ llvm::Value *CodeGenFunction::EmitIvarOffset(ObjCInterfaceDecl *Interface,
 
 LValue CodeGenFunction::EmitLValueForIvar(llvm::Value *BaseValue,
                                           const ObjCIvarDecl *Ivar,
+                                          const FieldDecl *Field,
                                           unsigned CVRQualifiers) {
   // See comment in EmitIvarOffset.
   if (CGM.getObjCRuntime().LateBoundIVars())
     assert(0 && "late-bound ivars are unsupported");
-
-  if (Ivar->isBitField())
-    assert(0 && "ivar bitfields are unsupported");
-  
   // TODO:  Add a special case for isa (index 0)
-  unsigned Index = CGM.getTypes().getLLVMFieldNo(Ivar);
+  unsigned Index = CGM.getTypes().getLLVMFieldNo(Field);
   
+  if (Ivar->isBitField()) {
+    return EmitLValueForBitfield(BaseValue, const_cast<FieldDecl *>(Field), 
+                                 CVRQualifiers, Index);
+  }
   llvm::Value *V = Builder.CreateStructGEP(BaseValue, Index, "tmp");
   LValue LV = LValue::MakeAddr(V, Ivar->getType().getCVRQualifiers()|CVRQualifiers);
   SetVarDeclObjCAttribute(getContext(), Ivar, Ivar->getType(), LV);
@@ -988,7 +995,8 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
     CVRQualifiers = BaseExpr->getType().getCVRQualifiers();
   }
 
-  return EmitLValueForIvar(BaseValue, E->getDecl(), CVRQualifiers);
+  return EmitLValueForIvar(BaseValue, E->getDecl(), E->getFieldDecl(), 
+                           CVRQualifiers);
 }
 
 LValue 
index 0237b96b5199a550711a306077d5e096cf10daaf..e419a7b9599f65730f49a2b823b2dd695ec8bab5 100644 (file)
@@ -190,7 +190,9 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
                                            Types.ConvertType(PD->getType())));
     EmitReturnOfRValue(RV, PD->getType());
   } else {
-    LValue LV = EmitLValueForIvar(LoadObjCSelf(), Ivar, 0);
+    FieldDecl *Field = 
+      IMP->getClassInterface()->lookupFieldDeclForIvar(getContext(), Ivar);
+    LValue LV = EmitLValueForIvar(LoadObjCSelf(), Ivar, Field, 0);
     if (hasAggregateLLVMType(Ivar->getType())) {
       EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType());
     }
index aa96bc53ea13901cc15ff496ac5722e71c68f941..08c9b938f1c0e065bc33aeea2141c645c95ba621 100644 (file)
@@ -720,8 +720,9 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
       Context.getObjCEncodingForType((*iter)->getType(), TypeStr);
       IvarTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
       // Get the offset
+      FieldDecl *Field = ClassDecl->lookupFieldDeclForIvar(Context, (*iter));
       int offset =
-        (int)Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(*iter));
+        (int)Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
       IvarOffsets.push_back(
           llvm::ConstantInt::get(llvm::Type::Int32Ty, offset));
   }
index 201f53e34d002266e204917adeff15c5daf9ee5c..33dfff103029c91b128a1a2474b04b607345fe9b 100644 (file)
@@ -1328,9 +1328,12 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
   for (ObjCInterfaceDecl::ivar_iterator 
          i = ID->getClassInterface()->ivar_begin(),
          e = ID->getClassInterface()->ivar_end(); i != e; ++i) {
-    ObjCIvarDecl *V = *i;
+    const ObjCIvarDecl *V = *i;
+    ObjCInterfaceDecl *OID = 
+      const_cast<ObjCInterfaceDecl *>(ID->getClassInterface());
+    FieldDecl *Field = OID->lookupFieldDeclForIvar(CGM.getContext(), V);
     unsigned Offset = 
-      Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(V));
+      Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
     std::string TypeStr;
     Ivar[0] = GetMethodVarName(V->getIdentifier());
     CGM.getContext().getObjCEncodingForType(V->getType(), TypeStr, true);
index 2959c08a4410d4b88578e92e026e39ebb9739966..a92bac7f1eb6bf190feaba3ffceb5aa5ef515801 100644 (file)
@@ -497,8 +497,12 @@ public:
   LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field,
                             bool isUnion, unsigned CVRQualifiers);
   LValue EmitLValueForIvar(llvm::Value* Base, const ObjCIvarDecl *Ivar,
+                           const FieldDecl *Field,
                            unsigned CVRQualifiers);
 
+  LValue EmitLValueForBitfield(llvm::Value* Base, FieldDecl* Field,
+                                unsigned CVRQualifiers, unsigned idx);
+
   LValue EmitCXXConditionDeclLValue(const CXXConditionDeclExpr *E);
 
   LValue EmitObjCMessageExprLValue(const ObjCMessageExpr *E);
index ff89341ddc556615de51bda5609b18f3800fe585..3470cca4d155f9bcfd189a167555ce265c3da0ec 100644 (file)
@@ -155,21 +155,6 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) {
   cast<llvm::OpaqueType>(OpaqueHolder.get())->refineAbstractTypeTo(NT);
 }
 
-/// Produces a vector containing the all of the instance variables in an
-/// Objective-C object, in the order that they appear.  Used to create LLVM
-/// structures corresponding to Objective-C objects.
-void CodeGenTypes::CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass,
-                                    std::vector<const llvm::Type*> &IvarTypes) {
-  ObjCInterfaceDecl *SuperClass = ObjCClass->getSuperClass();
-  if (SuperClass)
-    CollectObjCIvarTypes(SuperClass, IvarTypes);
-  for (ObjCInterfaceDecl::ivar_iterator I = ObjCClass->ivar_begin(),
-       E = ObjCClass->ivar_end(); I != E; ++I) {
-    IvarTypes.push_back(ConvertType((*I)->getType()));
-    ObjCIvarInfo[*I] = IvarTypes.size() - 1;
-  }
-}
-
 static const llvm::Type* getTypeForFormat(const llvm::fltSemantics &format) {
   if (&format == &llvm::APFloat::IEEEsingle)
     return llvm::Type::FloatTy;
@@ -280,21 +265,22 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
       ConvertTypeRecursive(QualType(cast<ASQualType>(Ty).getBaseType(), 0));
 
   case Type::ObjCInterface: {
-    // FIXME: This comment is broken. Either the code should check for
-    // the flag it is referring to or it should do the right thing in
-    // the presence of it.
-    
     // Warning: Use of this is strongly discouraged.  Late binding of instance
     // variables is supported on some runtimes and so using static binding can
     // break code when libraries are updated.  Only use this if you have
     // previously checked that the ObjCRuntime subclass in use does not support
     // late-bound ivars.
+    // We are issuing warnings elsewhere!
     ObjCInterfaceType OIT = cast<ObjCInterfaceType>(Ty);
-    std::vector<const llvm::Type*> IvarTypes;
-    CollectObjCIvarTypes(OIT.getDecl(), IvarTypes);
-    llvm::Type *T = llvm::StructType::get(IvarTypes);
-    TheModule.addTypeName("struct." + OIT.getDecl()->getNameAsString(), T);
-    return T;
+    ObjCInterfaceDecl *ID = OIT.getDecl();
+    RecordDecl *RD = ID->getRecordForDecl();
+    if(!RD) {
+      // Sometimes, class type is being directly generated in code gen for
+      // built-in class types.
+      ID->addLayoutToClass(Context);
+      RD = ID->getRecordForDecl();
+    }
+    return ConvertTagDeclType(cast<TagDecl>(RD));
   }
       
   case Type::ObjCQualifiedInterface: {
@@ -427,13 +413,6 @@ unsigned CodeGenTypes::getLLVMFieldNo(const FieldDecl *FD) {
   return I->second;
 }
 
-unsigned CodeGenTypes::getLLVMFieldNo(const ObjCIvarDecl *OID) {
-  llvm::DenseMap<const ObjCIvarDecl*, unsigned>::iterator
-    I = ObjCIvarInfo.find(OID);
-  assert(I != ObjCIvarInfo.end() && "Unable to find field info");
-  return I->second;
-}
-
 /// addFieldInfo - Assign field number to field FD.
 void CodeGenTypes::addFieldInfo(const FieldDecl *FD, unsigned No) {
   FieldInfo[FD] = No;
index 1c6019303c556a74f6696276ddac2eaab3ef9fbd..2fe7c89fadac60039b97768a23886a9459784207 100644 (file)
@@ -99,7 +99,6 @@ class CodeGenTypes {
   /// FieldInfo - This maps struct field with corresponding llvm struct type
   /// field no. This info is populated by record organizer.
   llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo;
-  llvm::DenseMap<const ObjCIvarDecl *, unsigned> ObjCIvarInfo;
 
 public:
   class BitFieldInfo {
@@ -158,9 +157,6 @@ public:
                                             ArgTypeIterator end,
                                             bool IsVariadic);
   
-  void CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass,
-                            std::vector<const llvm::Type*> &IvarTypes);
-  
   const CGRecordLayout *getCGRecordLayout(const TagDecl*) const;
   /// Returns a StructType representing an Objective-C object
   const llvm::Type *ConvertObjCInterfaceToStruct(const ObjCInterfaceDecl *OID);
@@ -168,8 +164,6 @@ public:
   /// getLLVMFieldNo - Return llvm::StructType element number
   /// that corresponds to the field FD.
   unsigned getLLVMFieldNo(const FieldDecl *FD);
-  unsigned getLLVMFieldNo(const ObjCIvarDecl *OID);
-    
   
   /// UpdateCompletedType - When we find the full definition for a TagDecl,
   /// replace the 'opaque' type we previously made for it if applicable.