From c1cf4a579f8a0a77719deedc1b8f850b77d36ecf Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 24 Sep 2008 04:04:31 +0000 Subject: [PATCH] Implement Obj-C getter synthesis for copy and retain. Also, "simple" getter synthesis no longer uses temporary AST objects. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56544 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjC.cpp | 68 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index a3da59410d..336d661001 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -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 @@ void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { /// 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 @@ void CodeGenFunction::GenerateObjCGetter(const ObjCPropertyImplDecl *PID) { 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 @@ void CodeGenFunction::GenerateObjCSetter(const ObjCPropertyImplDecl *PID) { FinishFunction(); } -llvm::Value *CodeGenFunction::LoadObjCSelf(void) { +llvm::Value *CodeGenFunction::LoadObjCSelf() { const ObjCMethodDecl *OMD = cast(CurFuncDecl); return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); } @@ -251,9 +289,16 @@ void CodeGenFunction::EmitObjCPropertySet(const ObjCPropertyRefExpr *E, 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(S.getElement())) { EmitStmt(SD); @@ -365,8 +410,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S) Builder.CreateBitCast(Collection, ConvertType(getContext().getObjCIdType()), "tmp"); - Builder.CreateCall(CGM.getObjCRuntime().EnumerationMutationFunction(), - V); + Builder.CreateCall(EnumerationMutationFn, V); EmitBlock(WasNotMutated); -- 2.40.0