Skip to content

Commit 84f92a3

Browse files
Merge pull request #34784 from nate-chandler/concurrency/irgen/rdar71491604
[Async CC] Find wtable in async context in thunk.
2 parents 35aa99b + e06d316 commit 84f92a3

File tree

4 files changed

+77
-13
lines changed

4 files changed

+77
-13
lines changed

lib/IRGen/GenThunk.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,34 +64,49 @@ IRGenModule::getAddrOfDispatchThunk(SILDeclRef declRef,
6464
static FunctionPointer lookupMethod(IRGenFunction &IGF, SILDeclRef declRef) {
6565
auto expansionContext = IGF.IGM.getMaximalTypeExpansionContext();
6666
auto *decl = cast<AbstractFunctionDecl>(declRef.getDecl());
67+
auto funcTy = IGF.IGM.getSILModule().Types.getConstantFunctionType(
68+
expansionContext, declRef);
69+
70+
auto getAsyncContextLayout = [&]() {
71+
auto originalType = funcTy;
72+
auto forwardingSubstitutionMap =
73+
decl->getGenericEnvironment()
74+
? decl->getGenericEnvironment()->getForwardingSubstitutionMap()
75+
: SubstitutionMap();
76+
auto substitutedType = originalType->substGenericArgs(
77+
IGF.IGM.getSILModule(), forwardingSubstitutionMap,
78+
IGF.IGM.getMaximalTypeExpansionContext());
79+
auto layout = irgen::getAsyncContextLayout(
80+
IGF.IGM, originalType, substitutedType, forwardingSubstitutionMap);
81+
return layout;
82+
};
6783

6884
// Protocol case.
6985
if (isa<ProtocolDecl>(decl->getDeclContext())) {
7086
// Find the witness table.
71-
llvm::Value *wtable = (IGF.CurFn->arg_end() - 1);
87+
llvm::Value *wtable;
88+
if (funcTy->isAsync()) {
89+
auto layout = getAsyncContextLayout();
90+
assert(layout.hasTrailingWitnesses());
91+
auto context = layout.emitCastTo(IGF, IGF.getAsyncContext());
92+
auto wtableAddr =
93+
layout.getSelfWitnessTableLayout().project(IGF, context, llvm::None);
94+
wtable = IGF.Builder.CreateLoad(wtableAddr);
95+
} else {
96+
wtable = (IGF.CurFn->arg_end() - 1);
97+
}
7298

7399
// Find the witness we're interested in.
74100
return emitWitnessMethodValue(IGF, wtable, declRef);
75101
}
76102

77103
// Class case.
78-
auto funcTy = IGF.IGM.getSILModule().Types.getConstantFunctionType(
79-
expansionContext, declRef);
80104

81105
// Load the metadata, or use the 'self' value if we have a static method.
82106
llvm::Value *self;
83107

84108
if (funcTy->isAsync()) {
85-
auto originalType = funcTy;
86-
auto forwardingSubstitutionMap =
87-
decl->getGenericEnvironment()
88-
? decl->getGenericEnvironment()->getForwardingSubstitutionMap()
89-
: SubstitutionMap();
90-
auto substitutedType = originalType->substGenericArgs(
91-
IGF.IGM.getSILModule(), forwardingSubstitutionMap,
92-
IGF.IGM.getMaximalTypeExpansionContext());
93-
auto layout = getAsyncContextLayout(IGF.IGM, originalType, substitutedType,
94-
forwardingSubstitutionMap);
109+
auto layout = getAsyncContextLayout();
95110
assert(layout.hasLocalContext());
96111
auto context = layout.emitCastTo(IGF, IGF.getAsyncContext());
97112
auto localContextAddr =
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import _Concurrency
2+
3+
public protocol Protokol {
4+
func protocolinstanceVoidToVoid() async
5+
}
6+
7+
public struct Impl : Protokol {
8+
public init() {}
9+
public func protocolinstanceVoidToVoid() async {
10+
print(self)
11+
}
12+
}
13+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift-dylib(%t/%target-library-name(PrintShims)) %S/../../Inputs/print-shims.swift -module-name PrintShims -emit-module -emit-module-path %t/PrintShims.swiftmodule
3+
// RUN: %target-codesign %t/%target-library-name(PrintShims)
4+
// RUN: %target-build-swift-dylib(%t/%target-library-name(ResilientProtocol)) %S/Inputs/protocol-1instance-void_to_void.swift -Xfrontend -enable-experimental-concurrency -module-name ResilientProtocol -emit-module -emit-module-path %t/ResilientProtocol.swiftmodule
5+
// RUN: %target-codesign %t/%target-library-name(ResilientProtocol)
6+
// RUN: %target-build-swift -Xfrontend -enable-experimental-concurrency %s -emit-ir -I %t -L %t -lPrintShim -lResilientProtocol | %FileCheck %s --check-prefix=CHECK-LL
7+
// RUN: %target-build-swift -Xfrontend -enable-experimental-concurrency %s -module-name main -o %t/main -I %t -L %t -lPrintShims -lResilientProtocol %target-rpath(%t)
8+
// RUN: %target-codesign %t/main
9+
// RUN: %target-run %t/main %t/%target-library-name(PrintShims) %t/%target-library-name(ResilientProtocol) | %FileCheck %s
10+
11+
// REQUIRES: executable_test
12+
// REQUIRES: swift_test_mode_optimize_none
13+
// REQUIRES: concurrency
14+
// UNSUPPORTED: use_os_stdlib
15+
// UNSUPPORTED: CPU=arm64e
16+
17+
import _Concurrency
18+
import ResilientProtocol
19+
20+
func call<T : Protokol>(_ t: T) async {
21+
await t.protocolinstanceVoidToVoid()
22+
}
23+
24+
// CHECK-LL: define hidden swiftcc void @"$s4main4callyyxY17ResilientProtocol8ProtokolRzlF"(%swift.task* {{%[0-9]+}}, %swift.executor* {{%[0-9]+}}, %swift.context* {{%[0-9]+}}) {{#[0-9]*}} {
25+
func test_case() async {
26+
let impl = Impl()
27+
await call(impl) // CHECK: Impl()
28+
}
29+
30+
_Concurrency.runAsync(test_case)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %target-swift-frontend %s -emit-ir -enable-library-evolution -enable-experimental-concurrency
2+
// REQUIRES: concurrency
3+
4+
public protocol P {
5+
func f() async
6+
}

0 commit comments

Comments
 (0)