[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