From 86957eb200492e95a09bce1b2c76f66345468f84 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 24 Sep 2008 06:32:09 +0000 Subject: [PATCH] Implement Obj-C synthesized setters for copy / retain. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56547 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjC.cpp | 85 +++++++++++++++++++++++++++++---------- lib/CodeGen/CGObjCMac.cpp | 3 +- 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 336d661001..c389adba58 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -206,6 +206,7 @@ void CodeGenFunction::GenerateObjCGetter(const ObjCPropertyImplDecl *PID) { /// function. The given Decl must be either an ObjCCategoryImplDecl /// or an ObjCImplementationDecl. void CodeGenFunction::GenerateObjCSetter(const ObjCPropertyImplDecl *PID) { + ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); const ObjCPropertyDecl *PD = PID->getPropertyDecl(); ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); assert(OMD && "Invalid call to generate setter (empty method)"); @@ -213,29 +214,69 @@ void CodeGenFunction::GenerateObjCSetter(const ObjCPropertyImplDecl *PID) { // 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); + bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy; + bool IsAtomic = + !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); + + // Determine if we should use an objc_setProperty call for + // this. Properties with 'copy' semantics always use it, as do + // non-atomic properties with 'release' semantics as long as we are + // not in gc-only mode. + if (IsCopy || + (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && + PD->getSetterKind() == ObjCPropertyDecl::Retain)) { + llvm::Value *SetPropertyFn = + CGM.getObjCRuntime().GetPropertySetFunction(); + + if (!SetPropertyFn) { + CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); + FinishFunction(); + return; + } + + // Emit objc_setProperty((id) self, _cmd, offset, arg, + // , ). + // 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 *Arg = LocalDeclMap[OMD->getParamDecl(0)]; + llvm::Value *ArgAsId = + Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"), + Types.ConvertType(IdTy)); + llvm::Value *True = + llvm::ConstantInt::get(Types.ConvertTypeForMem(getContext().BoolTy), 1); + llvm::Value *False = + llvm::ConstantInt::get(Types.ConvertTypeForMem(getContext().BoolTy), 0); + 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(ArgAsId), IdTy)); + Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False), + getContext().BoolTy)); + Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False), + getContext().BoolTy)); + EmitCall(SetPropertyFn, PD->getType(), Args); + } else { + 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); + } FinishFunction(); } diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 8a10d33e41..9e5940c5dc 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -2164,10 +2164,11 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) Params.push_back(ObjectPtrTy); Params.push_back(SelectorPtrTy); Params.push_back(LongTy); + Params.push_back(ObjectPtrTy); Params.push_back(Types.ConvertTypeForMem(Ctx.BoolTy)); Params.push_back(Types.ConvertTypeForMem(Ctx.BoolTy)); SetPropertyFn = - llvm::Function::Create(llvm::FunctionType::get(ObjectPtrTy, + llvm::Function::Create(llvm::FunctionType::get(llvm::Type::VoidTy, Params, false), llvm::Function::ExternalLinkage, -- 2.40.0