diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2012-01-06 00:29:35 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-01-06 00:29:35 +0000 |
commit | 84e49865cbc2392787efcf2211ec53a947128a9e (patch) | |
tree | bc2bc0b35f8183fd0b442fab41aae0d6d2297478 /lib/CodeGen/CGObjC.cpp | |
parent | ce52bb3dec520ef94574280ac3ef8ad63f4f1ce2 (diff) |
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
Diffstat (limited to 'lib/CodeGen/CGObjC.cpp')
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 91 |
1 files changed, 89 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<CallExpr>(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() {} |