[cfe-commits] r56544 - /cfe/trunk/lib/CodeGen/CGObjC.cpp

Daniel Dunbar daniel at zuster.org
Tue Sep 23 21:04:31 PDT 2008


Author: ddunbar
Date: Tue Sep 23 23:04:31 2008
New Revision: 56544

URL: http://llvm.org/viewvc/llvm-project?rev=56544&view=rev
Log:
Implement Obj-C getter synthesis for copy and retain.

Also, "simple" getter synthesis no longer uses temporary AST objects.

Modified:
    cfe/trunk/lib/CodeGen/CGObjC.cpp

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Tue Sep 23 23:04:31 2008
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/Basic/Diagnostic.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/Target/TargetData.h"
 
 using namespace clang;
 using namespace CodeGen;
@@ -143,6 +144,7 @@
 /// function. The given Decl must be either an ObjCCategoryImplDecl
 /// or an ObjCImplementationDecl.
 void CodeGenFunction::GenerateObjCGetter(const ObjCPropertyImplDecl *PID) {
+  ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
   const ObjCPropertyDecl *PD = PID->getPropertyDecl();
   ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
   assert(OMD && "Invalid call to generate getter (empty method)");
@@ -151,15 +153,51 @@
   OMD->createImplicitParams(getContext());
   StartObjCMethod(OMD);
 
-  // FIXME: What about nonatomic?
-  SourceLocation Loc = PD->getLocation();
-  ValueDecl *Self = OMD->getSelfDecl();
-  ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
-  DeclRefExpr Base(Self, Self->getType(), Loc);
-  ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base,
-                          true, true);
-  ReturnStmt Return(Loc, &IvarRef);
-  EmitStmt(&Return);
+  // Determine if we should use an objc_getProperty call for
+  // this. Non-atomic and properties with assign semantics are
+  // directly evaluated, and in gc-only mode we don't need it at all.
+  if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly &&
+      PD->getSetterKind() != ObjCPropertyDecl::Assign &&
+      !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
+    llvm::Value *GetPropertyFn = 
+      CGM.getObjCRuntime().GetPropertyGetFunction();
+    
+    if (!GetPropertyFn) {
+      CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy");
+      FinishFunction();
+      return;
+    }
+
+    // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
+    // FIXME: Can't this be simpler? This might even be worse than the
+    // corresponding gcc code.
+    CodeGenTypes &Types = CGM.getTypes();
+    ValueDecl *Cmd = OMD->getCmdDecl();
+    llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd");
+    QualType IdTy = getContext().getObjCIdType();
+    llvm::Value *SelfAsId = 
+      Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
+    llvm::Value *Offset = EmitIvarOffset(OMD->getClassInterface(), Ivar);
+    llvm::Value *True =
+      llvm::ConstantInt::get(Types.ConvertTypeForMem(getContext().BoolTy), 1);
+    CallArgList Args;
+    Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy));
+    Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType()));
+    Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy));
+    Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
+    RValue RV = EmitCall(GetPropertyFn, PD->getType(), Args);
+    // We need to fix the type here. Ivars with copy & retain are
+    // always objects so we don't need to worry about complex or
+    // aggregates.
+    RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), 
+                                           Types.ConvertType(PD->getType())));
+    EmitReturnOfRValue(RV, PD->getType());
+  } else {
+    EmitReturnOfRValue(EmitLoadOfLValue(EmitLValueForIvar(LoadObjCSelf(), 
+                                                          Ivar, 0), 
+                                        Ivar->getType()), 
+                       PD->getType());
+  }
 
   FinishFunction();
 }
@@ -202,7 +240,7 @@
   FinishFunction();
 }
 
-llvm::Value *CodeGenFunction::LoadObjCSelf(void) {
+llvm::Value *CodeGenFunction::LoadObjCSelf() {
   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
   return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
 }
@@ -251,9 +289,16 @@
 
 void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
 {
+  llvm::Function *EnumerationMutationFn = 
+    CGM.getObjCRuntime().EnumerationMutationFunction();
   llvm::Value *DeclAddress;
   QualType ElementTy;
   
+  if (!EnumerationMutationFn) {
+    CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime");
+    return;
+  }
+
   if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
     EmitStmt(SD);
     
@@ -365,8 +410,7 @@
     Builder.CreateBitCast(Collection, 
                           ConvertType(getContext().getObjCIdType()),
                           "tmp");
-  Builder.CreateCall(CGM.getObjCRuntime().EnumerationMutationFunction(),
-                     V);
+  Builder.CreateCall(EnumerationMutationFn, V);
   
   EmitBlock(WasNotMutated);
   





More information about the cfe-commits mailing list