From 84e49865cbc2392787efcf2211ec53a947128a9e Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 6 Jan 2012 00:29:35 +0000 Subject: [PATCH] objc++: sythesize a helper function to be used for copying atomic properties of c++ objects with non-trivial copy assignment in setters/getters. Not yet used. // rdar://6137845 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147636 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjC.cpp | 91 ++++++++++++++++++++++++++++++++++- lib/CodeGen/CodeGenFunction.h | 2 + 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 58319cf579..9f18f4c334 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -809,9 +809,9 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, EmitStmt(propImpl->getSetterCXXAssignment()); return; } - + const ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); - ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); + ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); ObjCMethodDecl *setterMethod = prop->getSetterMethodDecl(); PropertyImplStrategy strategy(CGM, propImpl); @@ -944,6 +944,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, /// is illegal within a category. void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, const ObjCPropertyImplDecl *PID) { + GenerateObjCAtomicCopyHelperFunction(PID); const ObjCPropertyDecl *PD = PID->getPropertyDecl(); ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); assert(OMD && "Invalid call to generate setter (empty method)"); @@ -2481,4 +2482,90 @@ void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) { Builder.CreateCall(extender, object)->setDoesNotThrow(); } +/// GenerateObjCAtomicCopyHelperFunction - Given a c++ object type with +/// non-trivial copy assignment function, produce following helper function. +/// static void copyHelper(Ty *dest, const Ty *source) { *dest = *source; } +/// +llvm::Constant * +CodeGenFunction::GenerateObjCAtomicCopyHelperFunction( + const ObjCPropertyImplDecl *PID) { + if (!getLangOptions().CPlusPlus) + return 0; + QualType Ty = PID->getPropertyIvarDecl()->getType(); + if (!Ty->isRecordType()) + return 0; + const ObjCPropertyDecl *PD = PID->getPropertyDecl(); + if (!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic) || + hasTrivialSetExpr(PID)) + return 0; + assert(PID->getSetterCXXAssignment() && "SetterCXXAssignment - null"); + + ASTContext &C = getContext(); + IdentifierInfo *II + = &CGM.getContext().Idents.get("__copy_helper_atomic_property_"); + FunctionDecl *FD = FunctionDecl::Create(C, + C.getTranslationUnitDecl(), + SourceLocation(), + SourceLocation(), II, C.VoidTy, 0, + SC_Static, + SC_None, + false, + true); + + QualType DestTy = C.getPointerType(Ty); + QualType SrcTy = Ty; + SrcTy.addConst(); + SrcTy = C.getPointerType(SrcTy); + + FunctionArgList args; + ImplicitParamDecl dstDecl(FD, SourceLocation(), 0, DestTy); + args.push_back(&dstDecl); + ImplicitParamDecl srcDecl(FD, SourceLocation(), 0, SrcTy); + args.push_back(&srcDecl); + + const CGFunctionInfo &FI = + CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo()); + + llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false); + + llvm::Function *Fn = + llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, + "__copy_helper_atomic_property_", &CGM.getModule()); + + if (CGM.getModuleDebugInfo()) + DebugInfo = CGM.getModuleDebugInfo(); + + + StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); + + DeclRefExpr *DstExpr = + new (C) DeclRefExpr(&dstDecl, DestTy, + VK_RValue, SourceLocation()); + + Expr* DST = new (C) UnaryOperator(DstExpr, UO_Deref, DestTy->getPointeeType(), + VK_LValue, OK_Ordinary, SourceLocation()); + + DeclRefExpr *SrcExpr = + new (C) DeclRefExpr(&srcDecl, SrcTy, + VK_RValue, SourceLocation()); + + Expr* SRC = new (C) UnaryOperator(SrcExpr, UO_Deref, SrcTy->getPointeeType(), + VK_LValue, OK_Ordinary, SourceLocation()); + + Expr *Args[2] = { DST, SRC }; + CallExpr *CalleeExp = cast(PID->getSetterCXXAssignment()); + CXXOperatorCallExpr *TheCall = + new (C) CXXOperatorCallExpr(C, OO_Equal, CalleeExp->getCallee(), + Args, 2, DestTy->getPointeeType(), + VK_LValue, SourceLocation()); + + EmitStmt(TheCall); + + FinishFunction(); + + return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); + +} + + CGObjCRuntime::~CGObjCRuntime() {} diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 105cfbec82..9a24426e75 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1333,6 +1333,8 @@ public: llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo); llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo); + llvm::Constant *GenerateObjCAtomicCopyHelperFunction( + const ObjCPropertyImplDecl *PID); void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags); -- 2.40.0