diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2012-01-06 22:33:54 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-01-06 22:33:54 +0000 |
commit | cd93b96bc51c255d104095bc6a6d8eac74a84b1e (patch) | |
tree | c31c8e9b2814e9b28ae61a27b9ce088de0a9c601 | |
parent | 5eca482fe895ea57bc82410222e6426c09e63284 (diff) |
objc++: more code gen stuff for atomic property api,
currently turned off. // rdar://6137845
Also, fixes a test case which should be nonatomic under
new API.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147691 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 78 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 3 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 10 | ||||
-rw-r--r-- | test/CodeGenObjCXX/property-reference.mm | 2 |
4 files changed, 78 insertions, 15 deletions
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 9f18f4c334..0f23a2129a 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -776,6 +776,44 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD, copyStructFn, ReturnValueSlot(), args); } +/// emitCPPObjectAtomicSetterCall - Call the runtime function to store +/// the value from the first formal parameter into the given ivar, using +/// the Cpp API for atomic Cpp objects with non-trivial copy assignment. +static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF, + ObjCMethodDecl *OMD, + ObjCIvarDecl *ivar, + llvm::Constant *AtomicHelperFn) { + // objc_copyCppObjectAtomic (&CppObjectIvar, &Arg, + // AtomicHelperFn); + CallArgList args; + + // The first argument is the address of the ivar. + llvm::Value *ivarAddr = + CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), + CGF.LoadObjCSelf(), ivar, 0).getAddress(); + ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy); + args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy); + + // The second argument is the address of the parameter variable. + ParmVarDecl *argVar = *OMD->param_begin(); + DeclRefExpr argRef(argVar, argVar->getType().getNonReferenceType(), + VK_LValue, SourceLocation()); + llvm::Value *argAddr = CGF.EmitLValue(&argRef).getAddress(); + argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy); + args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy); + + // Third argument is the helper function. + args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); + + llvm::Value *copyCppAtomicObjectFn = + CGF.CGM.getObjCRuntime().GetCppAtomicObjectFunction(); + CGF.EmitCall(CGF.getTypes().getFunctionInfo(CGF.getContext().VoidTy, args, + FunctionType::ExtInfo()), + copyCppAtomicObjectFn, ReturnValueSlot(), args); + + +} + static bool hasTrivialSetExpr(const ObjCPropertyImplDecl *PID) { Expr *setter = PID->getSetterCXXAssignment(); if (!setter) return true; @@ -802,17 +840,24 @@ static bool hasTrivialSetExpr(const ObjCPropertyImplDecl *PID) { void CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, - const ObjCPropertyImplDecl *propImpl) { + const ObjCPropertyImplDecl *propImpl, + llvm::Constant *AtomicHelperFn) { + const ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); + ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); + ObjCMethodDecl *setterMethod = prop->getSetterMethodDecl(); + // Just use the setter expression if Sema gave us one and it's - // non-trivial. There's no way to do this atomically. + // non-trivial. if (!hasTrivialSetExpr(propImpl)) { - EmitStmt(propImpl->getSetterCXXAssignment()); + if (!AtomicHelperFn) + // If non-atomic, assignment is called directly. + EmitStmt(propImpl->getSetterCXXAssignment()); + else + // If atomic, assignment is called via a locking api. + emitCPPObjectAtomicSetterCall(*this, setterMethod, ivar, + AtomicHelperFn); return; } - - const ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); - ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - ObjCMethodDecl *setterMethod = prop->getSetterMethodDecl(); PropertyImplStrategy strategy(CGM, propImpl); switch (strategy.getKind()) { @@ -944,13 +989,13 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, /// is illegal within a category. void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, const ObjCPropertyImplDecl *PID) { - GenerateObjCAtomicCopyHelperFunction(PID); + llvm::Constant *AtomicHelperFn = GenerateObjCAtomicCopyHelperFunction(PID); const ObjCPropertyDecl *PD = PID->getPropertyDecl(); ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); assert(OMD && "Invalid call to generate setter (empty method)"); StartObjCMethod(OMD, IMP->getClassInterface(), PID->getLocStart()); - generateObjCSetterBody(IMP, PID); + generateObjCSetterBody(IMP, PID, AtomicHelperFn); FinishFunction(); } @@ -2489,15 +2534,21 @@ void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) { llvm::Constant * CodeGenFunction::GenerateObjCAtomicCopyHelperFunction( const ObjCPropertyImplDecl *PID) { - if (!getLangOptions().CPlusPlus) + // FIXME. This api is for NeXt runtime only for now. + if (!getLangOptions().CPlusPlus || !getLangOptions().NeXTRuntime) 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)) + hasTrivialSetExpr(PID) || /* temporary */ true) return 0; + + llvm::Constant * HelperFn = CGM.getAtomicHelperFnMap(Ty); + if (HelperFn) + return HelperFn; + assert(PID->getSetterCXXAssignment() && "SetterCXXAssignment - null"); ASTContext &C = getContext(); @@ -2562,8 +2613,9 @@ CodeGenFunction::GenerateObjCAtomicCopyHelperFunction( EmitStmt(TheCall); FinishFunction(); - - return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); + HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); + CGM.setAtomicHelperFnMap(Ty, HelperFn); + return HelperFn; } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 9a24426e75..d016bbe3e4 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1310,7 +1310,8 @@ public: void GenerateObjCSetter(ObjCImplementationDecl *IMP, const ObjCPropertyImplDecl *PID); void generateObjCSetterBody(const ObjCImplementationDecl *classImpl, - const ObjCPropertyImplDecl *propImpl); + const ObjCPropertyImplDecl *propImpl, + llvm::Constant *AtomicHelperFn); bool IndirectObjCSetterArg(const CGFunctionInfo &FI); bool IvarTypeWithAggrGCObjects(QualType Ty); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 0517521d2c..e78089b5c5 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -276,6 +276,8 @@ class CodeGenModule : public CodeGenTypeCache { llvm::StringMap<llvm::Constant*> CFConstantStringMap; llvm::StringMap<llvm::GlobalVariable*> ConstantStringMap; llvm::DenseMap<const Decl*, llvm::Value*> StaticLocalDeclMap; + + llvm::DenseMap<QualType, llvm::Constant *> AtomicHelperFnMap; /// CXXGlobalInits - Global variables with initializers that need to run /// before main. @@ -398,6 +400,14 @@ public: StaticLocalDeclMap[D] = GV; } + llvm::Constant *getAtomicHelperFnMap(QualType Ty) { + return AtomicHelperFnMap[Ty]; + } + void setAtomicHelperFnMap(QualType Ty, + llvm::Constant *Fn) { + AtomicHelperFnMap[Ty] = Fn; + } + CGDebugInfo *getModuleDebugInfo() { return DebugInfo; } ASTContext &getContext() const { return Context; } diff --git a/test/CodeGenObjCXX/property-reference.mm b/test/CodeGenObjCXX/property-reference.mm index 63e2be4ba8..4897f6d0e8 100644 --- a/test/CodeGenObjCXX/property-reference.mm +++ b/test/CodeGenObjCXX/property-reference.mm @@ -35,7 +35,7 @@ namespace test1 { @interface Test1 { test1::A ivar; } -@property const test1::A &prop1; +@property (nonatomic) const test1::A &prop1; @end @implementation Test1 @synthesize prop1 = ivar; |