]> granicus.if.org Git - clang/commitdiff
objc2's ir-gen for nonfragile ivar access.
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 3 Feb 2009 00:09:52 +0000 (00:09 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 3 Feb 2009 00:09:52 +0000 (00:09 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63578 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGObjC.cpp
lib/CodeGen/CGObjCGNU.cpp
lib/CodeGen/CGObjCMac.cpp
lib/CodeGen/CGObjCRuntime.h
lib/CodeGen/CodeGenFunction.h

index 2c16c1940b55550c18d0c21b66612e4360802d1f..4f8bd46b52421f9a9ada136680fe6ee9c75ca0d6 100644 (file)
@@ -1020,7 +1020,8 @@ llvm::Value *CodeGenFunction::EmitIvarOffset(ObjCInterfaceDecl *Interface,
                                 Offset);                                                             
 }
 
-LValue CodeGenFunction::EmitLValueForIvar(llvm::Value *BaseValue,
+LValue CodeGenFunction::EmitLValueForIvar(QualType ObjectTy,
+                                          llvm::Value *BaseValue,
                                           const ObjCIvarDecl *Ivar,
                                           const FieldDecl *Field,
                                           unsigned CVRQualifiers) {
@@ -1035,6 +1036,7 @@ LValue CodeGenFunction::EmitLValueForIvar(llvm::Value *BaseValue,
                                  CVRQualifiers, Index);
   }
   llvm::Value *V = CGM.getObjCRuntime().EmitObjCValueForIvar(*this,
+                                                             ObjectTy,
                                        BaseValue, Ivar, Field, CVRQualifiers);
   LValue LV = LValue::MakeAddr(V, Ivar->getType().getCVRQualifiers()|CVRQualifiers);
   SetVarDeclObjCAttribute(getContext(), Ivar, Ivar->getType(), LV);
@@ -1047,19 +1049,22 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
   llvm::Value *BaseValue = 0;
   const Expr *BaseExpr = E->getBase();
   unsigned CVRQualifiers = 0;
+  QualType ObjectTy;
   if (E->isArrow()) {
     BaseValue = EmitScalarExpr(BaseExpr);
     const PointerType *PTy = 
       cast<PointerType>(getContext().getCanonicalType(BaseExpr->getType()));
-    CVRQualifiers = PTy->getPointeeType().getCVRQualifiers();
+    ObjectTy = PTy->getPointeeType();
+    CVRQualifiers = ObjectTy.getCVRQualifiers();
   } else {
     LValue BaseLV = EmitLValue(BaseExpr);
     // FIXME: this isn't right for bitfields.
     BaseValue = BaseLV.getAddress();
-    CVRQualifiers = BaseExpr->getType().getCVRQualifiers();
+    ObjectTy = BaseExpr->getType();
+    CVRQualifiers = ObjectTy.getCVRQualifiers();
   }
 
-  return EmitLValueForIvar(BaseValue, E->getDecl(), 
+  return EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), 
                            getContext().getFieldDecl(E), CVRQualifiers);
 }
 
index 9dc45efc6872c7c51c4a9ef96e3b1132dc83f72c..3ebee12f0df56b3ace544b54c87476a1aba16ece 100644 (file)
@@ -194,7 +194,8 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
   } else {
     FieldDecl *Field = 
       IMP->getClassInterface()->lookupFieldDeclForIvar(getContext(), Ivar);
-    LValue LV = EmitLValueForIvar(LoadObjCSelf(), Ivar, Field, 0);
+    LValue LV = EmitLValueForIvar(TypeOfSelfObject(),
+                                  LoadObjCSelf(), Ivar, Field, 0);
     if (hasAggregateLLVMType(Ivar->getType())) {
       EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType());
     }
@@ -294,6 +295,14 @@ llvm::Value *CodeGenFunction::LoadObjCSelf() {
   return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
 }
 
+QualType CodeGenFunction::TypeOfSelfObject() {
+  const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
+  ImplicitParamDecl *selfDecl = OMD->getSelfDecl();
+  const PointerType *PTy = 
+    cast<PointerType>(getContext().getCanonicalType(selfDecl->getType()));
+  return PTy->getPointeeType();
+}
+
 RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) {
   // FIXME: Split it into two separate routines.
   if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) {
index 1ce28bf91d40451c83241468be339944033e1ad5..d3b57b0e9afa185671c2f451231e27cb9d74f4ff 100644 (file)
@@ -141,6 +141,7 @@ public:
   virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
                                         llvm::Value *src, llvm::Value *dest);
   virtual llvm::Value *EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+                                            QualType ObjectTy,
                                             llvm::Value *BaseValue,
                                             const ObjCIvarDecl *Ivar,
                                             const FieldDecl *Field,
@@ -1037,6 +1038,7 @@ void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
 }
 
 llvm::Value *CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+                                             QualType ObjectTy,
                                              llvm::Value *BaseValue,
                                              const ObjCIvarDecl *Ivar,
                                              const FieldDecl *Field,
index a577bd03cb261d52f3d9ea8b99fd99b1ae1def0f..2b1d9fff0ba6247f777fde3ab7a1e1880b19c918 100644 (file)
@@ -551,6 +551,7 @@ private:
                                         llvm::Value *src, llvm::Value *dest);
   
   virtual llvm::Value *EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+                                            QualType ObjectTy,
                                             llvm::Value *BaseValue,
                                             const ObjCIvarDecl *Ivar,
                                             const FieldDecl *Field,
@@ -676,12 +677,11 @@ public:
                                         llvm::Value *src, llvm::Value *dest)
     { return; }
   virtual llvm::Value *EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+                                            QualType ObjectTy,
                                             llvm::Value *BaseValue,
                                             const ObjCIvarDecl *Ivar,
                                             const FieldDecl *Field,
-                                            unsigned CVRQualifiers)
-  { return 0; }
-  
+                                            unsigned CVRQualifiers);
 };
   
 } // end anonymous namespace
@@ -2114,6 +2114,7 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
 /// EmitObjCValueForIvar - Code Gen for ivar reference.
 ///
 llvm::Value *CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+                                             QualType ObjectTy,
                                              llvm::Value *BaseValue,
                                              const ObjCIvarDecl *Ivar,
                                              const FieldDecl *Field,
@@ -3755,15 +3756,16 @@ llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar(
   
   std::string ExternalName("\01_OBJC_IVAR_$_" + ID->getNameAsString() + '.' 
                            + Ivar->getNameAsString());
-  llvm::Constant *Init = llvm::ConstantInt::get(ObjCTypes.IntTy, Offset);
+  llvm::Constant *Init = llvm::ConstantInt::get(ObjCTypes.LongTy, Offset);
   
   llvm::GlobalVariable *IvarOffsetGV = 
     CGM.getModule().getGlobalVariable(ExternalName);
   if (IvarOffsetGV) {
     // ivar offset symbol already built due to user code referencing it.
     IvarOffsetGV->setAlignment(
-      CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.Int8PtrTy));
+      CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy));
     IvarOffsetGV->setInitializer(Init);
+    IvarOffsetGV->setSection("__DATA, __objc_const");
     UsedGlobals.push_back(IvarOffsetGV);
     return IvarOffsetGV;
   }
@@ -3776,7 +3778,7 @@ llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar(
                              ExternalName,
                              &CGM.getModule());
   IvarOffsetGV->setAlignment(
-    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.Int8PtrTy));
+    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy));
   // @private and @package have hidden visibility.
   bool globalVisibility = (Ivar->getAccessControl() == ObjCIvarDecl::Public ||
                            Ivar->getAccessControl() == ObjCIvarDecl::Protected);
@@ -3789,10 +3791,7 @@ llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar(
 
   IvarOffsetGV->setSection("__DATA, __objc_const");
   UsedGlobals.push_back(IvarOffsetGV);
-  
-  return llvm::ConstantExpr::getBitCast(
-                IvarOffsetGV,
-                llvm::PointerType::getUnqual(ObjCTypes.LongTy));
+  return IvarOffsetGV;
 }
 
 /// EmitIvarList - Emit the ivar list for the given
@@ -4094,6 +4093,52 @@ CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
   Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
   return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
 }
+
+/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
+/// This code gen. amounts to generating code for:
+/// @code
+/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
+/// @encode
+/// 
+llvm::Value *CGObjCNonFragileABIMac::EmitObjCValueForIvar(
+                                             CodeGen::CodeGenFunction &CGF,
+                                             QualType ObjectTy,
+                                             llvm::Value *BaseValue,
+                                             const ObjCIvarDecl *Ivar,
+                                             const FieldDecl *Field,
+                                             unsigned CVRQualifiers) {
+  assert(ObjectTy->isObjCInterfaceType() && 
+         "CGObjCNonFragileABIMac::EmitObjCValueForIvar");
+  NamedDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl();
+  // NOTE. This name must match one in EmitIvarOffsetVar.
+  // FIXME. Consolidate into one naming routine.
+  std::string ExternalName("\01_OBJC_IVAR_$_" + ID->getNameAsString() + '.' 
+                           + Ivar->getNameAsString());
+  
+  llvm::GlobalVariable *IvarOffsetGV = 
+    CGM.getModule().getGlobalVariable(ExternalName);
+  if (!IvarOffsetGV)
+    IvarOffsetGV = 
+      new llvm::GlobalVariable(ObjCTypes.LongTy,
+                               false,
+                               llvm::GlobalValue::ExternalLinkage,
+                               0,
+                               ExternalName,
+                               &CGM.getModule());
+  // (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().ConvertType(Ivar->getType());
+  llvm::Type *ptrIvarTy = llvm::PointerType::getUnqual(IvarTy);
+  V = CGF.Builder.CreateBitCast(V, ptrIvarTy);
+  return V;
+}
+
 /* *** */
 
 CodeGen::CGObjCRuntime *
index ded1db2c0b135df0172bbae72a51636ec6b6e5c0..ade77af1561b2d9083d8e8d780089d84ae86405b 100644 (file)
@@ -158,6 +158,7 @@ public:
                                         llvm::Value *src, llvm::Value *dest) = 0;
   
   virtual llvm::Value *EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+                                            QualType ObjectTy,
                                             llvm::Value *BaseValue,
                                             const ObjCIvarDecl *Ivar,
                                             const FieldDecl *Field,
index 9033a65be26bc14e02f2fd8f8bd6ce3c98227b8a..75353a7d9836de8b20082669100847747a59f870 100644 (file)
@@ -233,6 +233,10 @@ public:
   /// LoadObjCSelf - Load the value of self. This function is only
   /// valid while generating code for an Objective-C method.
   llvm::Value *LoadObjCSelf();
+  
+  /// TypeOfSelfObject
+  /// Return type of object that this self represents.
+  QualType TypeOfSelfObject();
 
   /// isObjCPointerType - Return true if the specificed AST type will map onto
   /// some Objective-C pointer type.
@@ -521,7 +525,8 @@ public:
                               const ObjCIvarDecl *Ivar);
   LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field,
                             bool isUnion, unsigned CVRQualifiers);
-  LValue EmitLValueForIvar(llvm::Value* Base, const ObjCIvarDecl *Ivar,
+  LValue EmitLValueForIvar(QualType ObjectTy,
+                           llvm::Value* Base, const ObjCIvarDecl *Ivar,
                            const FieldDecl *Field,
                            unsigned CVRQualifiers);