From d0c35cf2d5c0a2a4c4c849e482f70e9677fdc517 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 1 Mar 2024 12:45:53 +0000 Subject: [PATCH 1/2] [IRGen] Don't call objc_retainAutoreleasedReturnValue() without interop. When ObjC interop is not enabled, we shouldn't be emitting calls to `objc_retainAutoreleasedReturnValue()` as that function might not exist. Call `swift_retain()` instead, to balance the `swift_release()` of the returned value. Fixes #47846, #45359. rdar://23335318 --- lib/IRGen/GenCall.cpp | 5 +++- test/IRGen/Inputs/CFBridgedType.h | 6 +++++ test/IRGen/Inputs/module.modulemap | 8 +++++-- test/IRGen/autorelease.sil | 2 +- ...f_objc_retainAutoreleasedReturnValue.swift | 24 +++++++++++++++++++ 5 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 test/IRGen/Inputs/CFBridgedType.h create mode 100644 test/IRGen/cf_objc_retainAutoreleasedReturnValue.swift diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 5dd48ccb841e0..5ec3a5eca122d 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -2605,7 +2605,10 @@ class SyncCallEmission final : public CallEmission { if (fnConv.getNumDirectSILResults() == 1 && (fnConv.getDirectSILResults().begin()->getConvention() == ResultConvention::Autoreleased)) { - result = emitObjCRetainAutoreleasedReturnValue(IGF, result); + if (IGF.IGM.Context.LangOpts.EnableObjCInterop) + result = emitObjCRetainAutoreleasedReturnValue(IGF, result); + else + IGF.emitNativeStrongRetain(result, IGF.getDefaultAtomicity()); } auto origFnType = getCallee().getOrigFunctionType(); diff --git a/test/IRGen/Inputs/CFBridgedType.h b/test/IRGen/Inputs/CFBridgedType.h new file mode 100644 index 0000000000000..415c2af3d49ff --- /dev/null +++ b/test/IRGen/Inputs/CFBridgedType.h @@ -0,0 +1,6 @@ +#define CF_BRIDGED_TYPE(T) __attribute__((objc_bridge(T))) + +typedef struct CF_BRIDGED_TYPE(id) __CFBridgedType *CFBridgedTypeRef; + +__attribute__((cf_audited_transfer)) +CFBridgedTypeRef returnsACFBridgedType(void); diff --git a/test/IRGen/Inputs/module.modulemap b/test/IRGen/Inputs/module.modulemap index 4b318ea597ee8..1bce3f3c6d5b6 100644 --- a/test/IRGen/Inputs/module.modulemap +++ b/test/IRGen/Inputs/module.modulemap @@ -33,5 +33,9 @@ module SynthesizedProtocol { } module PointerAuth { - header "ptrauth_field_fptr_import.h" - } + header "ptrauth_field_fptr_import.h" +} + +module CFBridgedType { + header "CFBridgedType.h" +} \ No newline at end of file diff --git a/test/IRGen/autorelease.sil b/test/IRGen/autorelease.sil index 078f74250f663..dece04bf42341 100644 --- a/test/IRGen/autorelease.sil +++ b/test/IRGen/autorelease.sil @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -emit-ir | %FileCheck -check-prefix CHECK -check-prefix CHECK-%target-ptrsize -check-prefix %target-cpu -DINT=i%target-ptrsize %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -enable-objc-interop -emit-ir | %FileCheck -check-prefix CHECK -check-prefix CHECK-%target-ptrsize -check-prefix %target-cpu -DINT=i%target-ptrsize %s // rdar://16565958 diff --git a/test/IRGen/cf_objc_retainAutoreleasedReturnValue.swift b/test/IRGen/cf_objc_retainAutoreleasedReturnValue.swift new file mode 100644 index 0000000000000..08db4c789f0c3 --- /dev/null +++ b/test/IRGen/cf_objc_retainAutoreleasedReturnValue.swift @@ -0,0 +1,24 @@ +// RUN: %target-swift-frontend -module-name cf_objc_retainAutoreleasedReturnValue -I %S/Inputs %s -enable-objc-interop -emit-ir | %FileCheck %s +// RUN: %target-swift-frontend -module-name cf_objc_retainAutoreleasedReturnValue -I %S/Inputs %s -emit-ir | %FileCheck %s --check-prefix=NO_INTEROP + +import CFBridgedType + +@inline(never) +public func foo() { + let _ = returnsACFBridgedType() +} + +// With interop enabled, this should use objc_retainAutoreleasedReturnValue() + +// CHECK-LABEL: define protected swiftcc void @"$s37cf_objc_retainAutoreleasedReturnValue3fooyyF"() +// CHECK: entry: +// CHECK: %0 = call {{.*}}@returnsACFBridgedType() +// CHECK: %1 = notail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %0) + +// Without interop, it should call swift_retain() instead. + +// NO_INTEROP-LABEL: define protected swiftcc void @"$s37cf_objc_retainAutoreleasedReturnValue3fooyyF"() +// NO_INTEROP: entry: +// NO_INTEROP: %0 = call {{.*}}@returnsACFBridgedType() +// NO_INTEROP: %1 = call ptr @swift_retain(ptr returned %0) + From 0d7c575177b576347000bcee01033c5241b7b7f8 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 1 Mar 2024 15:36:59 +0000 Subject: [PATCH 2/2] [IRGen][Test] Update tests for non-Linux platform support. Tweak the tests slightly for WASM, Windows and Darwin. rdar://23335318 --- test/IRGen/autorelease.sil | 2 ++ ...cf_objc_retainAutoreleasedReturnValue.swift | 16 ++++++---------- ...f_objc_retainAutoreleasedReturnValue2.swift | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 test/IRGen/cf_objc_retainAutoreleasedReturnValue2.swift diff --git a/test/IRGen/autorelease.sil b/test/IRGen/autorelease.sil index dece04bf42341..5ec98c807b839 100644 --- a/test/IRGen/autorelease.sil +++ b/test/IRGen/autorelease.sil @@ -1,5 +1,7 @@ // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -enable-objc-interop -emit-ir | %FileCheck -check-prefix CHECK -check-prefix CHECK-%target-ptrsize -check-prefix %target-cpu -DINT=i%target-ptrsize %s +// REQUIRES: objc_codegen + // rdar://16565958 import Builtin diff --git a/test/IRGen/cf_objc_retainAutoreleasedReturnValue.swift b/test/IRGen/cf_objc_retainAutoreleasedReturnValue.swift index 08db4c789f0c3..884025261880a 100644 --- a/test/IRGen/cf_objc_retainAutoreleasedReturnValue.swift +++ b/test/IRGen/cf_objc_retainAutoreleasedReturnValue.swift @@ -1,5 +1,9 @@ // RUN: %target-swift-frontend -module-name cf_objc_retainAutoreleasedReturnValue -I %S/Inputs %s -enable-objc-interop -emit-ir | %FileCheck %s -// RUN: %target-swift-frontend -module-name cf_objc_retainAutoreleasedReturnValue -I %S/Inputs %s -emit-ir | %FileCheck %s --check-prefix=NO_INTEROP + +// We need to require objc_codegen to avoid this test on WASM. +// (That's why the other half of this test is in a separate file.) + +// REQUIRES: objc_codegen import CFBridgedType @@ -10,15 +14,7 @@ public func foo() { // With interop enabled, this should use objc_retainAutoreleasedReturnValue() -// CHECK-LABEL: define protected swiftcc void @"$s37cf_objc_retainAutoreleasedReturnValue3fooyyF"() +// CHECK-LABEL: define {{.*}}swiftcc void @"$s37cf_objc_retainAutoreleasedReturnValue3fooyyF"() // CHECK: entry: // CHECK: %0 = call {{.*}}@returnsACFBridgedType() // CHECK: %1 = notail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %0) - -// Without interop, it should call swift_retain() instead. - -// NO_INTEROP-LABEL: define protected swiftcc void @"$s37cf_objc_retainAutoreleasedReturnValue3fooyyF"() -// NO_INTEROP: entry: -// NO_INTEROP: %0 = call {{.*}}@returnsACFBridgedType() -// NO_INTEROP: %1 = call ptr @swift_retain(ptr returned %0) - diff --git a/test/IRGen/cf_objc_retainAutoreleasedReturnValue2.swift b/test/IRGen/cf_objc_retainAutoreleasedReturnValue2.swift new file mode 100644 index 0000000000000..463c608a450f6 --- /dev/null +++ b/test/IRGen/cf_objc_retainAutoreleasedReturnValue2.swift @@ -0,0 +1,18 @@ +// RUN: %target-swift-frontend -module-name cf_objc_retainAutoreleasedReturnValue -I %S/Inputs %s -disable-objc-interop -emit-ir | %FileCheck %s + +// This is in a separate file because *this* one works on WASM. +// (cf_objc_retainAutoreleasedReturnValue.swift does not.) + +import CFBridgedType + +@inline(never) +public func foo() { + let _ = returnsACFBridgedType() +} + +// With interop disabled, this should use swift_retain(). + +// CHECK-LABEL: define {{.*}}swiftcc void @"$s37cf_objc_retainAutoreleasedReturnValue3fooyyF"() +// CHECK: entry: +// CHECK: %0 = call {{.*}}@returnsACFBridgedType() +// CHECK: %1 = call ptr @swift_retain(ptr returned %0)