[cfe-commits] r55365 - in /cfe/trunk: include/clang/AST/DeclObjC.h lib/CodeGen/CGObjC.cpp lib/CodeGen/CGObjCMac.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h

Daniel Dunbar daniel at zuster.org
Tue Aug 26 01:29:32 PDT 2008


Author: ddunbar
Date: Tue Aug 26 03:29:31 2008
New Revision: 55365

URL: http://llvm.org/viewvc/llvm-project?rev=55365&view=rev
Log:
Objective-C @synthesize support.
 - Only supports simple assignment and atomic semantics are ignored.
 - Not quite usable yet because the methods do not actually get added
   to the class metadata.
 - Added ObjCPropertyDecl::getSetterKind (one of Assign, Copy, Retain).
 - Rearrange CodeGenFunction so synthesis can reuse function prolog /
   epilog code.

Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=55365&r1=55364&r2=55365&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Tue Aug 26 03:29:31 2008
@@ -1172,7 +1172,8 @@
     OBJC_PR_nonatomic = 0x40,
     OBJC_PR_setter    = 0x80
   };
-  
+
+  enum SetterKind { Assign, Retain, Copy };
   enum PropertyControl { None, Required, Optional };
 private:
   QualType DeclType;
@@ -1206,10 +1207,24 @@
     PropertyAttributes |= PRVal;
   }
 
+  // Helper methods for accessing attributes.
+
+  /// isReadOnly - Return true iff the property has a setter.
   bool isReadOnly() const {
     return (PropertyAttributes & OBJC_PR_readonly);
   }
-  
+
+  /// getSetterKind - Return the method used for doing assignment in
+  /// the property setter. This is only valid if the property has been
+  /// defined to have a setter.
+  SetterKind getSetterKind() const {
+    if (PropertyAttributes & OBJC_PR_retain)
+      return Retain;
+    if (PropertyAttributes & OBJC_PR_copy)
+      return Copy;
+    return Assign;
+  }
+
   Selector getGetterName() const { return GetterName; }
   void setGetterName(Selector Sel) { GetterName = Sel; }
   
@@ -1278,7 +1293,7 @@
     return PropertyIvarDecl ? Synthesize : Dynamic;
   }
   
-  ObjCIvarDecl *getPropertyIvarDecl() {
+  ObjCIvarDecl *getPropertyIvarDecl() const {
     return PropertyIvarDecl;
   }
   

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Tue Aug 26 03:29:31 2008
@@ -88,9 +88,12 @@
   return Runtime.GenerateMessageSend(*this, E, Receiver, isClassMessage);
 }
 
-/// Generate an Objective-C method.  An Objective-C method is a C function with
-/// its pointer, name, and types registered in the class struture.  
-void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
+/// StartObjCMethod - Begin emission of an ObjCMethod. This generates
+/// the LLVM function and sets the other context used by
+/// CodeGenFunction.
+
+// FIXME: This should really be merged with GenerateCode.
+void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD) {
   CurFn = CGM.getObjCRuntime().GenerateMethod(OMD);
   llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", CurFn);
   
@@ -127,8 +130,87 @@
     EmitParmDecl(*OMD->getParamDecl(i), AI);
   }
   assert(AI == CurFn->arg_end() && "Argument mismatch");
+}
+
+/// Generate an Objective-C method.  An Objective-C method is a C function with
+/// its pointer, name, and types registered in the class struture.  
+void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
+  StartObjCMethod(OMD);
+  EmitStmt(OMD->getBody());
+
+  const CompoundStmt *S = dyn_cast<CompoundStmt>(OMD->getBody());
+  if (S) {
+    FinishFunction(S->getRBracLoc());
+  } else {
+    FinishFunction();
+  }
+}
+
+// FIXME: I wasn't sure about the synthesis approach. If we end up
+// generating an AST for the whole body we can just fall back to
+// having a GenerateFunction which takes the body Stmt.
+
+/// GenerateObjCGetter - Generate an Objective-C property getter
+/// function. The given Decl must be either an ObjCCategoryImplDecl
+/// or an ObjCImplementationDecl.
+void CodeGenFunction::GenerateObjCGetter(const ObjCPropertyImplDecl *PID) {
+  const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+  ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
+  assert(OMD && "Invalid call to generate getter (empty method)");
+  // FIXME: This is rather murky, we create this here since they will
+  // not have been created by Sema for us.
+  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);
+
+  FinishFunction();
+}
+
+/// GenerateObjCSetter - Generate an Objective-C property setter
+/// function. The given Decl must be either an ObjCCategoryImplDecl
+/// or an ObjCImplementationDecl.
+void CodeGenFunction::GenerateObjCSetter(const ObjCPropertyImplDecl *PID) {
+  const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+  ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
+  assert(OMD && "Invalid call to generate setter (empty method)");
+  // FIXME: This is rather murky, we create this here since they will
+  // not have been created by Sema for us.  
+  OMD->createImplicitParams(getContext());
+  StartObjCMethod(OMD);
+  
+  switch (PD->getSetterKind()) {
+  case ObjCPropertyDecl::Assign: break;
+  case ObjCPropertyDecl::Copy:
+      CGM.ErrorUnsupported(PID, "Obj-C setter with 'copy'");
+      break;
+  case ObjCPropertyDecl::Retain:
+      CGM.ErrorUnsupported(PID, "Obj-C setter with 'retain'");
+      break;
+  }
+
+  // FIXME: What about nonatomic?
+  SourceLocation Loc = PD->getLocation();
+  ValueDecl *Self = OMD->getSelfDecl();
+  ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
+  DeclRefExpr Base(Self, Self->getType(), Loc);
+  ParmVarDecl *ArgDecl = OMD->getParamDecl(0);
+  DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc);
+  ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base,
+                          true, true);
+  BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign,
+                        Ivar->getType(), Loc);
+  EmitStmt(&Assign);
 
-  GenerateFunction(OMD->getBody());
+  FinishFunction();
 }
 
 llvm::Value *CodeGenFunction::LoadObjCSelf(void) {

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Tue Aug 26 03:29:31 2008
@@ -233,9 +233,7 @@
                                 const llvm::Type *InterfaceTy);
 
   /// EmitMethodList - Emit the method list for the given
-  /// implementation. If ForClass is true the list of class methods
-  /// will be emitted, otherwise the list of instance methods will be
-  /// generated. The return value has type MethodListPtrTy.
+  /// implementation. The return value has type MethodListPtrTy.
   llvm::Constant *EmitMethodList(const std::string &Name,
                                  const char *Section,
                    llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator begin,

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Aug 26 03:29:31 2008
@@ -62,19 +62,15 @@
     !T->isVoidType() && !T->isVectorType() && !T->isFunctionType();
 }
 
-void CodeGenFunction::GenerateFunction(const Stmt *Body) {
-  // Emit the function body.
-  EmitStmt(Body);
-
+void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
   // Finish emission of indirect switches.
   EmitIndirectSwitches();
 
   // Emit debug descriptor for function end.
   CGDebugInfo *DI = CGM.getDebugInfo(); 
   if (DI) {
-    const CompoundStmt* s = dyn_cast<CompoundStmt>(Body);
-    if (s && s->getRBracLoc().isValid()) {
-      DI->setLocation(s->getRBracLoc());
+    if (EndLoc.isValid()) {
+      DI->setLocation(EndLoc);
     }
     DI->EmitRegionEnd(CurFn, Builder);
   }
@@ -156,7 +152,15 @@
       EmitParmDecl(*CurParam, V);
     }
   }
-  GenerateFunction(FD->getBody());
+
+  EmitStmt(FD->getBody());
+  
+  const CompoundStmt *S = dyn_cast<CompoundStmt>(FD->getBody());
+  if (S) {
+    FinishFunction(S->getRBracLoc());
+  } else {
+    FinishFunction();
+  }
 }
 
 /// isDummyBlock - Return true if BB is an empty basic block

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Aug 26 03:29:31 2008
@@ -39,6 +39,7 @@
   class FunctionTypeProto;
   class LabelStmt;
   class ObjCMethodDecl;
+  class ObjCPropertyImplDecl;
   class TargetInfo;
   class VarDecl;
 
@@ -112,9 +113,20 @@
   ASTContext &getContext() const;
 
   void GenerateObjCMethod(const ObjCMethodDecl *OMD);
+
+  void StartObjCMethod(const ObjCMethodDecl *MD);
+
+  /// GenerateObjCGetter - Synthesize an Objective-C property getter
+  /// function.
+  void GenerateObjCGetter(const ObjCPropertyImplDecl *PID);
+
+  /// GenerateObjCSetter - Synthesize an Objective-C property setter
+  /// function for the given property.
+  void GenerateObjCSetter(const ObjCPropertyImplDecl *PID);
+
   void GenerateCode(const FunctionDecl *FD,
                     llvm::Function *Fn);
-  void GenerateFunction(const Stmt *Body);
+  void FinishFunction(SourceLocation EndLoc=SourceLocation());
   
   const llvm::Type *ConvertType(QualType T);
 

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Aug 26 03:29:31 2008
@@ -836,6 +836,32 @@
   return GetAddrOfConstantString(str + "\0");
 }
 
+/// EmitObjCPropertyImplementations - Emit information for synthesized
+/// properties for an implementation.
+void CodeGenModule::EmitObjCPropertyImplementations(const 
+                                                    ObjCImplementationDecl *D) {
+  for (ObjCImplementationDecl::propimpl_iterator i = D->propimpl_begin(),
+         e = D->propimpl_end(); i != e; ++i) {
+    ObjCPropertyImplDecl *PID = *i;
+    
+    // Dynamic is just for type-checking.
+    if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
+      ObjCPropertyDecl *PD = PID->getPropertyDecl();
+
+      // Determine which methods need to be implemented, some may have
+      // been overridden. Note that ::isSynthesized is not the method
+      // we want, that just indicates if the decl came from a
+      // property. What we want to know is if the method is defined in
+      // this implementation.
+      if (!D->getInstanceMethod(PD->getGetterName()))
+        CodeGenFunction(*this).GenerateObjCGetter(PID);
+      if (!PD->isReadOnly() &&
+          !D->getInstanceMethod(PD->getSetterName()))
+        CodeGenFunction(*this).GenerateObjCSetter(PID);
+    }
+  }
+}
+
 /// EmitTopLevelDecl - Emit code for a single top level declaration.
 void CodeGenModule::EmitTopLevelDecl(Decl *D) {
   // If an error has occurred, stop code generation, but continue
@@ -868,13 +894,18 @@
     break;
 
   case Decl::ObjCCategoryImpl:
+    // Categories have properties but don't support synthesize so we
+    // can ignore them here.
+
     Runtime->GenerateCategory(cast<ObjCCategoryImplDecl>(D));
     break;
 
-  case Decl::ObjCImplementation:
-    Runtime->GenerateClass(cast<ObjCImplementationDecl>(D));
+  case Decl::ObjCImplementation: {
+    ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D);
+    EmitObjCPropertyImplementations(OMD);
+    Runtime->GenerateClass(OMD);
     break;
-    
+  } 
   case Decl::ObjCMethod: {
     ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(D);
     // If this is not a prototype, emit the body.
@@ -882,9 +913,6 @@
       CodeGenFunction(*this).GenerateObjCMethod(OMD);
     break;
   }
-  case Decl::ObjCPropertyImpl:
-    assert(0 && "FIXME: ObjCPropertyImpl unsupported");
-    break;
   case Decl::ObjCCompatibleAlias: 
     assert(0 && "FIXME: ObjCCompatibleAlias unsupported");
     break;

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Aug 26 03:29:31 2008
@@ -217,6 +217,7 @@
   llvm::GlobalValue *EmitForwardFunctionDefinition(const FunctionDecl *D);
   void EmitGlobalFunctionDefinition(const FunctionDecl *D);
   void EmitGlobalVarDefinition(const VarDecl *D);
+  void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D);
   
   // FIXME: Hardcoding priority here is gross.
   void AddGlobalCtor(llvm::Function * Ctor, int Priority=65535);





More information about the cfe-commits mailing list