From e99bc83fa55f4dea390822bc0e2e9b077ffd226e Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Mon, 17 Dec 2012 15:59:29 +0000 Subject: [PATCH] Added support for new property helpers (GNUstep runtime). llvm-svn: 170344 --- clang/lib/CodeGen/CGObjC.cpp | 7 +- clang/lib/CodeGen/CGObjCGNU.cpp | 76 ++++++++++++++++++- clang/lib/CodeGen/CGObjCMac.cpp | 13 +++- clang/lib/CodeGen/CGObjCRuntime.h | 9 ++- clang/test/CodeGenObjC/optimized-setter.m | 1 + .../property-object-reference-2.mm | 4 + 6 files changed, 97 insertions(+), 13 deletions(-) diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index deac5f6aa4ff..ced5a4cb1c85 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -772,7 +772,7 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF, args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); llvm::Value *copyCppAtomicObjectFn = - CGF.CGM.getObjCRuntime().GetCppAtomicObjectFunction(); + CGF.CGM.getObjCRuntime().GetCppAtomicObjectGetFunction(); CGF.EmitCall(CGF.getTypes().arrangeFreeFunctionCall(CGF.getContext().VoidTy, args, FunctionType::ExtInfo(), @@ -1007,7 +1007,7 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF, args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); llvm::Value *copyCppAtomicObjectFn = - CGF.CGM.getObjCRuntime().GetCppAtomicObjectFunction(); + CGF.CGM.getObjCRuntime().GetCppAtomicObjectSetFunction(); CGF.EmitCall(CGF.getTypes().arrangeFreeFunctionCall(CGF.getContext().VoidTy, args, FunctionType::ExtInfo(), @@ -2800,8 +2800,7 @@ void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) { } static bool hasAtomicCopyHelperAPI(const ObjCRuntime &runtime) { - // For now, only NeXT has these APIs. - return runtime.isNeXTFamily(); + return runtime.hasAtomicCopyHelper(); } /// GenerateObjCAtomicSetterCopyHelperFunction - Given a c++ object type with diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 245c8914b163..1cd8dbf2090f 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -492,8 +492,9 @@ public: virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, bool copy); virtual llvm::Constant *GetSetStructFunction(); - virtual llvm::Constant *GetCppAtomicObjectFunction(); virtual llvm::Constant *GetGetStructFunction(); + virtual llvm::Constant *GetCppAtomicObjectGetFunction(); + virtual llvm::Constant *GetCppAtomicObjectSetFunction(); virtual llvm::Constant *EnumerationMutationFunction(); virtual void EmitTryStmt(CodeGenFunction &CGF, @@ -601,6 +602,20 @@ class CGObjCGNUstep : public CGObjCGNU { /// arguments. Returns the slot for the corresponding method. Superclass /// message lookup rarely changes, so this is a good caching opportunity. LazyRuntimeFunction SlotLookupSuperFn; + /// Specialised function for setting atomic retain properties + LazyRuntimeFunction SetPropertyAtomic; + /// Specialised function for setting atomic copy properties + LazyRuntimeFunction SetPropertyAtomicCopy; + /// Specialised function for setting nonatomic retain properties + LazyRuntimeFunction SetPropertyNonAtomic; + /// Specialised function for setting nonatomic copy properties + LazyRuntimeFunction SetPropertyNonAtomicCopy; + /// Function to perform atomic copies of C++ objects with nontrivial copy + /// constructors from Objective-C ivars. + LazyRuntimeFunction CxxAtomicObjectGetFn; + /// Function to perform atomic copies of C++ objects with nontrivial copy + /// constructors to Objective-C ivars. + LazyRuntimeFunction CxxAtomicObjectSetFn; /// Type of an slot structure pointer. This is returned by the various /// lookup functions. llvm::Type *SlotTy; @@ -676,8 +691,60 @@ class CGObjCGNUstep : public CGObjCGNU { // void __cxa_end_catch(void) ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy, NULL); // void _Unwind_Resume_or_Rethrow(void*) - ExceptionReThrowFn.init(&CGM, "_Unwind_Resume_or_Rethrow", VoidTy, PtrTy, NULL); + ExceptionReThrowFn.init(&CGM, "_Unwind_Resume_or_Rethrow", VoidTy, + PtrTy, NULL); } + llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); + SetPropertyAtomic.init(&CGM, "objc_setProperty_atomic", VoidTy, IdTy, + SelectorTy, IdTy, PtrDiffTy, NULL); + SetPropertyAtomicCopy.init(&CGM, "objc_setProperty_atomic_copy", VoidTy, + IdTy, SelectorTy, IdTy, PtrDiffTy, NULL); + SetPropertyNonAtomic.init(&CGM, "objc_setProperty_nonatomic", VoidTy, + IdTy, SelectorTy, IdTy, PtrDiffTy, NULL); + SetPropertyNonAtomicCopy.init(&CGM, "objc_setProperty_nonatomic_copy", + VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy, NULL); + // void objc_setCppObjectAtomic(void *dest, const void *src, void + // *helper); + CxxAtomicObjectSetFn.init(&CGM, "objc_setCppObjectAtomic", VoidTy, PtrTy, + PtrTy, PtrTy, NULL); + // void objc_getCppObjectAtomic(void *dest, const void *src, void + // *helper); + CxxAtomicObjectGetFn.init(&CGM, "objc_getCppObjectAtomic", VoidTy, PtrTy, + PtrTy, PtrTy, NULL); + } + virtual llvm::Constant *GetCppAtomicObjectGetFunction() { + // The optimised functions were added in version 1.7 of the GNUstep + // runtime. + assert (CGM.getLangOpts().ObjCRuntime.getVersion() >= + VersionTuple(1, 7)); + return CxxAtomicObjectGetFn; + } + virtual llvm::Constant *GetCppAtomicObjectSetFunction() { + ObjCRuntime R = CGM.getLangOpts().ObjCRuntime; + // The optimised functions were added in version 1.7 of the GNUstep + // runtime. + if (R.getVersion() < VersionTuple(1, 7)) return 0; + return CxxAtomicObjectSetFn; + } + virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, + bool copy) { + // The optimised property functions omit the GC check, and so are not + // safe to use in GC mode. The standard functions are fast in GC mode, + // so there is less advantage in using them. + assert ((CGM.getLangOpts().getGC() == LangOptions::NonGC)) return 0; + // The optimised functions were added in version 1.7 of the GNUstep + // runtime. + assert (CGM.getLangOpts().ObjCRuntime.getVersion() >= + VersionTuple(1, 7)); + + if (atomic) { + if (copy) return SetPropertyAtomicCopy; + return SetPropertyAtomic; + } + if (copy) return SetPropertyNonAtomicCopy; + return SetPropertyNonAtomic; + + return 0; } }; @@ -2535,7 +2602,10 @@ llvm::Constant *CGObjCGNU::GetGetStructFunction() { llvm::Constant *CGObjCGNU::GetSetStructFunction() { return SetStructPropertyFn; } -llvm::Constant *CGObjCGNU::GetCppAtomicObjectFunction() { +llvm::Constant *CGObjCGNU::GetCppAtomicObjectGetFunction() { + return 0; +} +llvm::Constant *CGObjCGNU::GetCppAtomicObjectSetFunction() { return 0; } diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index d84875bfd514..aff804cd4b46 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -1223,7 +1223,8 @@ public: bool copy); virtual llvm::Constant *GetGetStructFunction(); virtual llvm::Constant *GetSetStructFunction(); - virtual llvm::Constant *GetCppAtomicObjectFunction(); + virtual llvm::Constant *GetCppAtomicObjectGetFunction(); + virtual llvm::Constant *GetCppAtomicObjectSetFunction(); virtual llvm::Constant *EnumerationMutationFunction(); virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF, @@ -1494,7 +1495,10 @@ public: virtual llvm::Constant *GetGetStructFunction() { return ObjCTypes.getCopyStructFn(); } - virtual llvm::Constant *GetCppAtomicObjectFunction() { + virtual llvm::Constant *GetCppAtomicObjectSetFunction() { + return ObjCTypes.getCppAtomicObjectFunction(); + } + virtual llvm::Constant *GetCppAtomicObjectGetFunction() { return ObjCTypes.getCppAtomicObjectFunction(); } @@ -3409,7 +3413,10 @@ llvm::Constant *CGObjCMac::GetSetStructFunction() { return ObjCTypes.getCopyStructFn(); } -llvm::Constant *CGObjCMac::GetCppAtomicObjectFunction() { +llvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() { + return ObjCTypes.getCppAtomicObjectFunction(); +} +llvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() { return ObjCTypes.getCppAtomicObjectFunction(); } diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index 934464b9e5c6..584bf6738f02 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -209,9 +209,12 @@ public: virtual llvm::Constant *GetGetStructFunction() = 0; // API for atomic copying of qualified aggregates in setter. virtual llvm::Constant *GetSetStructFunction() = 0; - // API for atomic copying of qualified aggregates with non-trivial copy - // assignment (c++) in setter/getter. - virtual llvm::Constant *GetCppAtomicObjectFunction() = 0; + /// API for atomic copying of qualified aggregates with non-trivial copy + /// assignment (c++) in setter. + virtual llvm::Constant *GetCppAtomicObjectSetFunction() = 0; + /// API for atomic copying of qualified aggregates with non-trivial copy + /// assignment (c++) in getter. + virtual llvm::Constant *GetCppAtomicObjectGetFunction() = 0; /// GetClass - Return a reference to the class for the given /// interface decl. diff --git a/clang/test/CodeGenObjC/optimized-setter.m b/clang/test/CodeGenObjC/optimized-setter.m index 6f5cfb126332..7e0a1d769f6e 100644 --- a/clang/test/CodeGenObjC/optimized-setter.m +++ b/clang/test/CodeGenObjC/optimized-setter.m @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -emit-llvm -fobjc-runtime=macosx-10.8 -triple x86_64-apple-macosx10.8.0 -o - | FileCheck %s // RUN: %clang_cc1 %s -emit-llvm -fobjc-runtime=ios-6.0.0 -triple x86_64-apple-ios6.0.0 -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -fobjc-runtime=gnustep-1.7 -triple x86_64-unknown-freebsd -o - | FileCheck %s // rdar://10179974 @interface I diff --git a/clang/test/CodeGenObjCXX/property-object-reference-2.mm b/clang/test/CodeGenObjCXX/property-object-reference-2.mm index 2a380385bc9d..25bfdf848d3a 100644 --- a/clang/test/CodeGenObjCXX/property-object-reference-2.mm +++ b/clang/test/CodeGenObjCXX/property-object-reference-2.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.7 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-unknown-freebsd -fobjc-runtime=gnustep-1.7 -emit-llvm -o - | FileCheck -check-prefix=CHECK-GNUSTEP %s // rdar://6137845 extern int DEFAULT(); @@ -54,3 +55,6 @@ struct TCPPObject // CHECK: [[THREE:%.*]] = bitcast %struct.TCPPObject* [[MYPROPERTY:%.*]] to i8* // CHECK: call void @objc_copyCppObjectAtomic(i8* [[TWO]], i8* [[THREE]], i8* bitcast (void (%struct.TCPPObject*, %struct.TCPPObject*)* @__assign_helper_atomic_property_ to i8*)) // CHECK: ret void + +// CHECK-GNUSTEP: objc_getCppObjectAtomic +// CHECK-GNUSTEP: objc_setCppObjectAtomic