From f7264e327fa98943c891ad399b3ab3f566061480 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 16 Sep 2025 10:36:26 -0700 Subject: [PATCH] [IRGen] Only use a stub for swift_coroFrameAlloc when we need it swift_coroFrameAlloc was introduced in the Swift 6.2 runtime. Give it the appropriate availability in IRGen, so that it gets weak availability when needed (per the deployment target). Then, only create the stub function for calling into swift_coroFrameAlloc or malloc (when the former isn't available) when we're back-deploying to a runtime prior to Swift 6.2. This is a small code size/performance win when allocating coroutine frames on Swift 6.2-or-newer platforms. This has a side effect of fixing a bug in Embedded Swift, where the swift_coroFrameAlloc was getting unconditionally set to have weak external linkage despite behind defined in the same LLVM module (because it comes from the standard library). Fixes rdar://149695139 / issue #80947. --- include/swift/AST/FeatureAvailability.def | 1 + include/swift/Runtime/RuntimeFunctions.def | 3 ++- lib/Driver/DarwinToolChains.cpp | 2 ++ lib/Frontend/CompilerInvocation.cpp | 2 ++ lib/IRGen/GenFunc.cpp | 11 ++++++++--- lib/IRGen/IRGenModule.cpp | 8 ++++++++ .../yield_once_enable_emit_type_malloc_coro_frame.sil | 10 +++++----- ...ld_once_enable_emit_type_malloc_coro_frame_ios.sil | 2 ++ ...e_enable_emit_type_malloc_coro_frame_macos_new.sil | 4 ++++ 9 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 test/IRGen/yield_once_enable_emit_type_malloc_coro_frame_ios.sil create mode 100644 test/IRGen/yield_once_enable_emit_type_malloc_coro_frame_macos_new.sil diff --git a/include/swift/AST/FeatureAvailability.def b/include/swift/AST/FeatureAvailability.def index 1321362c5c1b2..71413c18a11d8 100644 --- a/include/swift/AST/FeatureAvailability.def +++ b/include/swift/AST/FeatureAvailability.def @@ -82,6 +82,7 @@ FEATURE(ValueGenericType, (6, 2)) FEATURE(InitRawStructMetadata2, (6, 2)) FEATURE(CustomGlobalExecutors, (6, 2)) FEATURE(TaskExecutor, (6, 2)) +FEATURE(TypedCoroAlloc, (6, 2)) FEATURE(Differentiation, FUTURE) FEATURE(ClearSensitive, FUTURE) diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def index a4d9e06c97d64..7709fc11dac54 100644 --- a/include/swift/Runtime/RuntimeFunctions.def +++ b/include/swift/Runtime/RuntimeFunctions.def @@ -2059,7 +2059,8 @@ FUNCTION(Free, c, free, C_CC, AlwaysAvailable, NO_ATTRS, EFFECT(RuntimeEffect::Deallocating), UNKNOWN_MEMEFFECTS) -FUNCTION(CoroFrameAlloc, Swift, swift_coroFrameAlloc, C_CC, AlwaysAvailable, +FUNCTION(CoroFrameAlloc, Swift, swift_coroFrameAlloc, C_CC, + TypedCoroAllocAvailability, RETURNS(Int8PtrTy), ARGS(SizeTy, Int64Ty), NO_ATTRS, diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 1ca6696397c3f..70491e78a1092 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -366,6 +366,8 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments, runtimeCompatibilityVersion = llvm::VersionTuple(5, 8); } else if (value == "6.0") { runtimeCompatibilityVersion = llvm::VersionTuple(6, 0); + } else if (value == "6.2") { + runtimeCompatibilityVersion = llvm::VersionTuple(6, 2); } else if (value == "none") { runtimeCompatibilityVersion = std::nullopt; } else { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 8116eaa657799..acb6cf8688adc 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -3699,6 +3699,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, runtimeCompatibilityVersion = llvm::VersionTuple(5, 8); } else if (version == "6.0") { runtimeCompatibilityVersion = llvm::VersionTuple(6, 0); + } else if (version == "6.2") { + runtimeCompatibilityVersion = llvm::VersionTuple(6, 2); } else { Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value, versionArg->getAsString(Args), version); diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index 72b88a99a1b29..0660d8df54abc 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -863,15 +863,20 @@ CanType irgen::getArgumentLoweringType(CanType type, SILParameterInfo paramInfo, } llvm::Constant *irgen::getCoroFrameAllocStubFn(IRGenModule &IGM) { + // If the coroutine allocation function is always available, call it directly. + auto coroAllocPtr = IGM.getCoroFrameAllocFn(); + auto coroAllocFn = dyn_cast(coroAllocPtr); + if (coroAllocFn->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) + return coroAllocFn; + + // Otherwise, create a stub function to call it when available, or malloc + // when it isn't. return IGM.getOrCreateHelperFunction( "__swift_coroFrameAllocStub", IGM.Int8PtrTy, {IGM.SizeTy, IGM.Int64Ty}, [&](IRGenFunction &IGF) { auto parameters = IGF.collectParameters(); auto *size = parameters.claimNext(); - auto coroAllocPtr = IGF.IGM.getCoroFrameAllocFn(); - auto coroAllocFn = dyn_cast(coroAllocPtr); - coroAllocFn->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); auto *coroFrameAllocFn = IGF.IGM.getOpaquePtr(coroAllocPtr); auto *nullSwiftCoroFrameAlloc = IGF.Builder.CreateCmp( llvm::CmpInst::Predicate::ICMP_NE, coroFrameAllocFn, diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 7776f8ca4e3d0..b13893ff833d2 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -902,6 +902,14 @@ namespace RuntimeConstants { return RuntimeAvailability::AlwaysAvailable; } + RuntimeAvailability TypedCoroAllocAvailability(ASTContext &context) { + auto featureAvailability = context.getTypedCoroAllocAvailability(); + if (!isDeploymentAvailabilityContainedIn(context, featureAvailability)) { + return RuntimeAvailability::ConditionallyAvailable; + } + return RuntimeAvailability::AlwaysAvailable; + } + RuntimeAvailability ConcurrencyDiscardingTaskGroupAvailability(ASTContext &context) { auto featureAvailability = context.getConcurrencyDiscardingTaskGroupAvailability(); diff --git a/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame.sil b/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame.sil index 6ed9e6fbb7535..9eddb211dd261 100644 --- a/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame.sil +++ b/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame.sil @@ -1,5 +1,5 @@ -// REQUIRES: OS=macosx || OS=iOS -// RUN: %target-swift-frontend -emit-irgen %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-ptrsize-%target-ptrauth +// REQUIRES: OS=macosx +// RUN: %target-swift-frontend -target %target-cpu-apple-macosx15.0 -emit-irgen %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-ptrsize-%target-ptrauth import Builtin @@ -44,6 +44,9 @@ unwind: // CHECK-NEXT: unreachable } +// CHECK-32: declare extern_weak ptr @swift_coroFrameAlloc(i32, i64) +// CHECK-64: declare extern_weak ptr @swift_coroFrameAlloc(i64, i64) + // CHECK-32: define linkonce_odr hidden ptr @__swift_coroFrameAllocStub(i32 %0, i64 %1) #1{{( comdat)?}} { // CHECK-64: define linkonce_odr hidden ptr @__swift_coroFrameAllocStub(i64 %0, i64 %1) #1{{( comdat)?}} { // CHECK: [[T0:%.*]] = icmp ne ptr @swift_coroFrameAlloc, null @@ -59,9 +62,6 @@ unwind: // CHECK-64: [[T2:%.*]] = call ptr @malloc(i64 %0) // CHECK: ret ptr [[T2]] -// CHECK-32: declare extern_weak ptr @swift_coroFrameAlloc(i32, i64) -// CHECK-64: declare extern_weak ptr @swift_coroFrameAlloc(i64, i64) - // CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$sIetA_TC" // CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) diff --git a/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame_ios.sil b/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame_ios.sil new file mode 100644 index 0000000000000..05b29b0fed1e1 --- /dev/null +++ b/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame_ios.sil @@ -0,0 +1,2 @@ +// REQUIRES: OS=iOS +// RUN: %target-swift-frontend -target %target-cpu-apple-iphoneos16.0 -emit-irgen %S/yield_once_enable_emit_type_malloc_coro_frame.sil | %FileCheck %S/yield_once_enable_emit_type_malloc_coro_frame.sil --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-ptrsize-%target-ptrauth diff --git a/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame_macos_new.sil b/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame_macos_new.sil new file mode 100644 index 0000000000000..376564aaee80e --- /dev/null +++ b/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame_macos_new.sil @@ -0,0 +1,4 @@ +// REQUIRES: OS=macosx +// RUN: %target-swift-frontend -target %target-cpu-apple-macosx26.0 -emit-irgen %S/yield_once_enable_emit_type_malloc_coro_frame.sil | %FileCheck %s + +// CHECK-NOT: __swift_coroFrameAllocStub