Skip to content

Commit a0098c0

Browse files
Merge pull request #36037 from aschwaighofer/irgen_use_swifttailcc
Conditionally start using llvm::CallingConv::SwiftTail for async functions
2 parents b49be98 + afac324 commit a0098c0

File tree

63 files changed

+154
-143
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+154
-143
lines changed

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ FUNCTION(TaskCreateFutureFunc,
15271527
// ExecutorRef currentExecutor,
15281528
// ExecutorRef newExecutor);
15291529
FUNCTION(TaskSwitchFunc,
1530-
swift_task_switch, SwiftCC,
1530+
swift_task_switch, SwiftAsyncCC,
15311531
ConcurrencyAvailability,
15321532
RETURNS(VoidTy),
15331533
ARGS(SwiftTaskPtrTy, SwiftExecutorPtrTy, SwiftExecutorPtrTy),

lib/IRGen/GenCall.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,8 @@ static llvm::CallingConv::ID getFreestandingConvention(IRGenModule &IGM) {
462462
/// Expand the requirements of the given abstract calling convention
463463
/// into a "physical" calling convention.
464464
llvm::CallingConv::ID irgen::expandCallingConv(IRGenModule &IGM,
465-
SILFunctionTypeRepresentation convention) {
465+
SILFunctionTypeRepresentation convention,
466+
bool isAsync) {
466467
switch (convention) {
467468
case SILFunctionTypeRepresentation::CFunctionPointer:
468469
case SILFunctionTypeRepresentation::ObjCMethod:
@@ -474,6 +475,8 @@ llvm::CallingConv::ID irgen::expandCallingConv(IRGenModule &IGM,
474475
case SILFunctionTypeRepresentation::Closure:
475476
case SILFunctionTypeRepresentation::Thin:
476477
case SILFunctionTypeRepresentation::Thick:
478+
if (isAsync)
479+
return IGM.SwiftAsyncCC;
477480
return getFreestandingConvention(IGM);
478481
}
479482
llvm_unreachable("bad calling convention!");
@@ -1849,7 +1852,8 @@ Signature SignatureExpansion::getSignature() {
18491852
(FnType->getLanguage() == SILFunctionLanguage::C) &&
18501853
"C function type without C function info");
18511854

1852-
auto callingConv = expandCallingConv(IGM, FnType->getRepresentation());
1855+
auto callingConv =
1856+
expandCallingConv(IGM, FnType->getRepresentation(), FnType->isAsync());
18531857

18541858
Signature result;
18551859
result.Type = llvmType;
@@ -4808,7 +4812,7 @@ IRGenFunction::getFunctionPointerForResumeIntrinsic(llvm::Value *resume) {
48084812
IGM.VoidTy, {IGM.Int8PtrTy, IGM.Int8PtrTy, IGM.Int8PtrTy},
48094813
false /*vaargs*/);
48104814
auto signature =
4811-
Signature(fnTy, IGM.constructInitialAttributes(), IGM.SwiftCC);
4815+
Signature(fnTy, IGM.constructInitialAttributes(), IGM.SwiftAsyncCC);
48124816
auto fnPtr = FunctionPointer(
48134817
FunctionPointer::KindTy::Function,
48144818
Builder.CreateBitOrPointerCast(resume, fnTy->getPointerTo()),

lib/IRGen/GenCall.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ namespace irgen {
316316
std::pair<bool, bool> values = {true, true},
317317
Size initialContextSize = Size(0));
318318
llvm::CallingConv::ID expandCallingConv(IRGenModule &IGM,
319-
SILFunctionTypeRepresentation convention);
319+
SILFunctionTypeRepresentation convention,
320+
bool isAsync);
320321

321322
Signature emitCastOfFunctionPointer(IRGenFunction &IGF, llvm::Value *&fnPtr,
322323
CanSILFunctionType fnType);

lib/IRGen/GenFunc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2582,7 +2582,7 @@ llvm::Function *IRGenFunction::createAsyncSuspendFn() {
25822582
IGM.getTaskSwitchFuncFn(),
25832583
{ task, executor, targetExecutor });
25842584
suspendCall->setDoesNotThrow();
2585-
suspendCall->setCallingConv(IGM.SwiftCC);
2585+
suspendCall->setCallingConv(IGM.SwiftAsyncCC);
25862586
suspendCall->setTailCall();
25872587
Builder.CreateRetVoid();
25882588
return suspendFn;

lib/IRGen/GenObjC.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -710,8 +710,8 @@ static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM,
710710
llvm::Function::Create(fwdTy, llvm::Function::InternalLinkage,
711711
MANGLE_AS_STRING(OBJC_PARTIAL_APPLY_THUNK_SYM),
712712
&IGM.Module);
713-
fwd->setCallingConv(
714-
expandCallingConv(IGM, SILFunctionTypeRepresentation::Thick));
713+
fwd->setCallingConv(expandCallingConv(
714+
IGM, SILFunctionTypeRepresentation::Thick, false/*isAsync*/));
715715

716716
fwd->setAttributes(attrs);
717717
// Merge initial attributes with attrs.

lib/IRGen/IRGenModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,9 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
547547
// TODO: use "tinycc" on platforms that support it
548548
DefaultCC = SWIFT_DEFAULT_LLVM_CC;
549549
SwiftCC = llvm::CallingConv::Swift;
550+
// TODO: Once clang support is merged this should also use
551+
// clangASTContext.getTargetInfo().isSwiftAsyncCCSupported()
552+
SwiftAsyncCC = opts.UseAsyncLowering ? llvm::CallingConv::SwiftTail : SwiftCC;
550553

551554
if (opts.DebugInfoLevel > IRGenDebugInfoLevel::None)
552555
DebugInfo = IRGenDebugInfo::createIRGenDebugInfo(IRGen.Opts, *CI, *this,

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ class IRGenModule {
753753
llvm::CallingConv::ID C_CC; /// standard C calling convention
754754
llvm::CallingConv::ID DefaultCC; /// default calling convention
755755
llvm::CallingConv::ID SwiftCC; /// swift calling convention
756+
llvm::CallingConv::ID SwiftAsyncCC; /// swift calling convention for async
756757

757758
Signature getAssociatedTypeWitnessTableAccessFunctionSignature();
758759

stdlib/public/Concurrency/Actor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,7 @@ static void runOnAssumedThread(AsyncTask *task, ExecutorRef newExecutor,
13281328
actor->giveUpThread(runner);
13291329
}
13301330

1331+
SWIFT_CC(swiftasync)
13311332
void swift::swift_task_switch(AsyncTask *task, ExecutorRef currentExecutor,
13321333
ExecutorRef newExecutor) {
13331334
assert(task && "no task provided");

stdlib/public/Concurrency/Task.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ AsyncTaskAndContext swift::swift_task_create_future_f(
317317
return {task, initialContext};
318318
}
319319

320+
SWIFT_CC(swiftasync)
320321
void swift::swift_task_future_wait(
321322
AsyncTask *waitingTask, ExecutorRef executor,
322323
SWIFT_ASYNC_CONTEXT AsyncContext *rawContext) {

stdlib/public/Concurrency/TaskGroup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ void AsyncTask::groupOffer(AsyncTask *completedTask, AsyncContext *context,
153153

154154
// =============================================================================
155155
// ==== group.next() implementation (wait_next and groupPoll) ------------------
156-
156+
SWIFT_CC(swiftasync)
157157
void swift::swift_task_group_wait_next(
158158
AsyncTask *waitingTask,
159159
ExecutorRef executor,

test/IRGen/async.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ public class SomeClass {}
1616
@_silgen_name("swift_task_future_wait")
1717
public func task_future_wait(_ task: __owned SomeClass) async throws -> Int
1818

19-
// CHECK: define{{.*}} swiftcc void @"$s5async8testThisyyAA9SomeClassCnYF"(%swift.task* %0, %swift.executor* %1, %swift.context* swiftasync %2)
19+
// CHECK: define{{.*}} swift{{(tail)?}}cc void @"$s5async8testThisyyAA9SomeClassCnYF"(%swift.task* %0, %swift.executor* %1, %swift.context* swiftasync %2)
2020
// CHECK-64: call swiftcc i8* @swift_task_alloc(%swift.task* %{{[0-9]+}}, i64 64)
21-
// CHECK: tail call swiftcc void @swift_task_future_wait(
21+
// CHECK: tail call swift{{(tail)?}}cc void @swift_task_future_wait(
2222
public func testThis(_ task: __owned SomeClass) async {
2323
do {
2424
let _ = try await task_future_wait(task)

test/IRGen/async/Inputs/class_open-1instance-void_to_void.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ func printGeneric<T>(_ t: T) {
66
// CHECK-LL: @"$s4main6call_fyyAA1CCYFTu" = {{(dllexport )?}}{{(protected )?}}global %swift.async_func_pointer
77
// CHECK-LL: @"$s4main1CC1fyyYFTu" = {{(dllexport )?}}{{(protected )?}}global %swift.async_func_pointer
88

9-
// CHECK-LL: define {{(dllexport )?}}{{(protected )?}}swiftcc void @"$s4main6call_fyyAA1CCYF"(%swift.task* {{%[0-9]+}}, %swift.executor* {{%[0-9]+}}, %swift.context* swiftasync {{%[0-9]+}}) {{#[0-9]*}} {
10-
// CHECK-LL: define {{(dllexport )?}}{{(protected )?}}swiftcc void @"$s4main1CC1fyyYF"(%swift.task* {{%[0-9]+}}, %swift.executor* {{%[0-9]+}}, %swift.context* swiftasync {{%[0-9]+}}) {{#[0-9]*}} {
9+
// CHECK-LL: define {{(dllexport )?}}{{(protected )?}}swift{{(tail)?}}cc void @"$s4main6call_fyyAA1CCYF"(%swift.task* {{%[0-9]+}}, %swift.executor* {{%[0-9]+}}, %swift.context* swiftasync {{%[0-9]+}}) {{#[0-9]*}} {
10+
// CHECK-LL: define {{(dllexport )?}}{{(protected )?}}swift{{(tail)?}}cc void @"$s4main1CC1fyyYF"(%swift.task* {{%[0-9]+}}, %swift.executor* {{%[0-9]+}}, %swift.context* swiftasync {{%[0-9]+}}) {{#[0-9]*}} {
1111
public func call_f(_ c: C) async {
1212
print("entering call_f")
1313
await c.f()

test/IRGen/async/builtins.sil

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ sil_stage canonical
88
import Builtin
99
import Swift
1010

11-
// CHECK-LABEL: define hidden swiftcc void @get_task(%swift.task* %0, %swift.executor* %1, %swift.context* swiftasync %2)
11+
// CHECK-LABEL: define hidden swift{{(tail)?}}cc void @get_task(%swift.task* %0, %swift.executor* %1, %swift.context* swiftasync %2)
1212
sil hidden [ossa] @get_task : $@async @convention(thin) () -> @owned Builtin.NativeObject {
1313
bb0:
1414
// CHECK: [[TASKLOC:%.*]] = alloca %swift.task*
@@ -22,24 +22,24 @@ bb0:
2222
return %1 : $Builtin.NativeObject
2323
}
2424

25-
// CHECK-LABEL: define hidden swiftcc void @cancel_task(%swift.refcounted* %0)
25+
// CHECK-LABEL: define hidden swift{{(tail)?}}cc void @cancel_task(%swift.refcounted* %0)
2626
// CHECK: [[TASK:%.*]] = bitcast %swift.refcounted* %0 to %swift.task*
27-
// CHECK-NEXT: call swiftcc void @swift_task_cancel(%swift.task* [[TASK]])
27+
// CHECK-NEXT: call swift{{(tail)?}}cc void @swift_task_cancel(%swift.task* [[TASK]])
2828
sil hidden [ossa] @cancel_task : $@convention(method) (@guaranteed Builtin.NativeObject) -> () {
2929
bb0(%0 : @guaranteed $Builtin.NativeObject):
3030
%4 = builtin "cancelAsyncTask"(%0 : $Builtin.NativeObject) : $()
3131
%5 = tuple ()
3232
return %5 : $()
3333
}
3434

35-
// CHECK-LABEL: define hidden swiftcc void @launch_task
35+
// CHECK-LABEL: define hidden swift{{(tail)?}}cc void @launch_task
3636
sil hidden [ossa] @launch_task : $@convention(method) @async (Int, Optional<Builtin.NativeObject>, @guaranteed @async @callee_guaranteed () -> (@error Error)) -> () {
3737
bb0(%0 : $Int, %1: @unowned $Optional<Builtin.NativeObject>, %2: @guaranteed $@async @callee_guaranteed () -> (@error Error)):
3838
%copy = copy_value %1 : $Optional<Builtin.NativeObject>
3939
%3 = begin_borrow %copy : $Optional<Builtin.NativeObject>
4040
// CHECK: [[FN_CONTEXT:%.*]] = load %swift.refcounted*, %swift.refcounted** %.data
4141
// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[FN_CONTEXT]])
42-
// CHECK: [[NEW_TASK_AND_CONTEXT:%.*]] = call swiftcc %swift.async_task_and_context @swift_task_create_f(
42+
// CHECK: [[NEW_TASK_AND_CONTEXT:%.*]] = call swift{{(tail)?}}cc %swift.async_task_and_context @swift_task_create_f(
4343
// CHECK-NEXT: [[NEW_CONTEXT_RAW:%.*]] = extractvalue %swift.async_task_and_context [[NEW_TASK_AND_CONTEXT]], 1
4444
// CHECK-NEXT: [[NEW_CONTEXT:%.*]] = bitcast %swift.context* [[NEW_CONTEXT_RAW]] to
4545
// CHECK-NEXT: [[CONTEXT_INFO_LOC:%.*]] = getelementptr inbounds <{{.*}}>* [[NEW_CONTEXT]]
@@ -52,7 +52,7 @@ bb0(%0 : $Int, %1: @unowned $Optional<Builtin.NativeObject>, %2: @guaranteed $@a
5252
return %21 : $()
5353
}
5454

55-
// CHECK-LABEL: define hidden swiftcc void @launch_future
55+
// CHECK-LABEL: define hidden swift{{(tail)?}}cc void @launch_future
5656
sil hidden [ossa] @launch_future : $@convention(method) <T> (Int, Optional<Builtin.NativeObject>, @guaranteed @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for <T>, @in_guaranteed T) -> () {
5757
bb0(%0 : $Int, %1: @unowned $Optional<Builtin.NativeObject>, %2: @guaranteed $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for <T>, %3: $*T):
5858
%copy = copy_value %1 : $Optional<Builtin.NativeObject>
@@ -63,7 +63,7 @@ bb0(%0 : $Int, %1: @unowned $Optional<Builtin.NativeObject>, %2: @guaranteed $@a
6363
// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[FN_CONTEXT:%.*]])
6464
%9 = metatype $@thick T.Type
6565
%10 = init_existential_metatype %9 : $@thick T.Type, $@thick Any.Type
66-
// CHECK: [[NEW_TASK_AND_CONTEXT:%.*]] = call swiftcc %swift.async_task_and_context @swift_task_create_future_f(
66+
// CHECK: [[NEW_TASK_AND_CONTEXT:%.*]] = call swift{{(tail)?}}cc %swift.async_task_and_context @swift_task_create_future_f(
6767
// CHECK-NEXT: [[NEW_CONTEXT_RAW:%.*]] = extractvalue %swift.async_task_and_context [[NEW_TASK_AND_CONTEXT]], 1
6868
// CHECK-NEXT: [[NEW_CONTEXT:%.*]] = bitcast %swift.context* [[NEW_CONTEXT_RAW]] to
6969
// CHECK-32-NEXT: [[CONTEXT_INFO_LOC:%.*]] = getelementptr inbounds <{{.*}}>* [[NEW_CONTEXT]], i32 0, i32 6
@@ -77,7 +77,7 @@ bb0(%0 : $Int, %1: @unowned $Optional<Builtin.NativeObject>, %2: @guaranteed $@a
7777
return %21 : $()
7878
}
7979

80-
// CHECK-LABEL: define hidden swiftcc void @launch_void_future
80+
// CHECK-LABEL: define hidden swift{{(tail)?}}cc void @launch_void_future
8181
sil hidden [ossa] @launch_void_future : $@convention(method) (Int, Optional<Builtin.NativeObject>, @guaranteed @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for <()>) -> () {
8282
bb0(%0 : $Int, %1: @unowned $Optional<Builtin.NativeObject>, %2: @guaranteed $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error Error) for <()>):
8383
%copy = copy_value %1 : $Optional<Builtin.NativeObject>
@@ -88,7 +88,7 @@ bb0(%0 : $Int, %1: @unowned $Optional<Builtin.NativeObject>, %2: @guaranteed $@a
8888
// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[FN_CONTEXT:%.*]])
8989
%8 = metatype $@thick ().Type // user: %9
9090
%9 = init_existential_metatype %8 : $@thick ().Type, $@thick Any.Type // user: %10
91-
// CHECK: [[NEW_TASK_AND_CONTEXT:%.*]] = call swiftcc %swift.async_task_and_context @swift_task_create_future_f(
91+
// CHECK: [[NEW_TASK_AND_CONTEXT:%.*]] = call swift{{(tail)?}}cc %swift.async_task_and_context @swift_task_create_future_f(
9292
// CHECK-NEXT: [[NEW_CONTEXT_RAW:%.*]] = extractvalue %swift.async_task_and_context [[NEW_TASK_AND_CONTEXT]], 1
9393
// CHECK-NEXT: [[NEW_CONTEXT:%.*]] = bitcast %swift.context* [[NEW_CONTEXT_RAW]] to
9494
// CHECK-32-NEXT: [[CONTEXT_INFO_LOC:%.*]] = getelementptr inbounds <{{.*}}>* [[NEW_CONTEXT]], i32 0, i32 6

test/IRGen/async/class_resilience.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,17 @@ open class MyBaseClass<T> {
4141
// CHECK-LABEL: @"$s16class_resilience9MyDerivedCMn" = hidden constant
4242
// CHECK-SAME: %swift.async_func_pointer* @"$s16class_resilience9MyDerivedC4waitSiyYF010resilient_A09BaseClassCADxyYFTVTu"
4343

44-
// CHECK-LABEL: define {{(dllexport )?}}{{(protected )?}}swiftcc void @"$s16class_resilience14callsAwaitableyx010resilient_A09BaseClassCyxGYlF"(%swift.task* %0, %swift.executor* %1, %swift.context* swiftasync %2)
44+
// CHECK-LABEL: define {{(dllexport )?}}{{(protected )?}}swift{{(tail)?}}cc void @"$s16class_resilience14callsAwaitableyx010resilient_A09BaseClassCyxGYlF"(%swift.task* %0, %swift.executor* %1, %swift.context* swiftasync %2)
4545
// CHECK: %swift.async_func_pointer* @"$s15resilient_class9BaseClassC4waitxyYFTjTu"
4646
// CHECK: ret void
4747
public func callsAwaitable<T>(_ c: BaseClass<T>) async -> T {
4848
return await c.wait()
4949
}
5050

51-
// CHECK-LABEL: define {{(dllexport )?}}{{(protected )?}}swiftcc void @"$s16class_resilience11MyBaseClassC4waitxyYFTj"(%swift.task* %0, %swift.executor* %1, %swift.context* swiftasync %2) #0 {
51+
// CHECK-LABEL: define {{(dllexport )?}}{{(protected )?}}swift{{(tail)?}}cc void @"$s16class_resilience11MyBaseClassC4waitxyYFTj"(%swift.task* %0, %swift.executor* %1, %swift.context* swiftasync %2) #0 {
5252

5353
class MyDerived : BaseClass<Int> {
5454
override func wait() async -> Int {
5555
return await super.wait()
5656
}
57-
}
57+
}

test/IRGen/async/debug.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// REQUIRES: concurrency
33

44
// Don't assert on dynamically sized variables.
5-
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s5debug1fyxxYKlF"
5+
// CHECK: define{{( dllexport)?}}{{( protected)?}} swift{{(tail)?}}cc void @"$s5debug1fyxxYKlF"
66

77
public func f<Success>(_ value: Success) async throws -> Success {
88
switch Result<Success, Error>.success(value) {

test/IRGen/async/hop_to_executor.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ bb0(%0 : $MyActor):
4646
// CHECK-arm64e: [[PTRAUTH_SIGN:%[^,]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[CTXT_INT]], i32 2, i64 [[PTRAUTH_BLEND]])
4747
// CHECK-arm64e: [[CTXT:%[^,]+]] = inttoptr i64 [[PTRAUTH_SIGN]] to %swift.context*
4848
// CHECK: store %swift.context* [[CTXT]], %swift.context** [[CTXT_ADDR]]
49-
// CHECK: tail call swiftcc void @swift_task_switch(%swift.task* %2, %swift.executor* %3, %swift.executor* %1)
49+
// CHECK: tail call swift{{(tail)?}}cc void @swift_task_switch(%swift.task* %2, %swift.executor* %3, %swift.executor* %1)
5050
// CHECK: ret void
5151

5252
sil_vtable MyActor {

0 commit comments

Comments
 (0)