Skip to content

Commit 6722d71

Browse files
authored
Merge pull request #34819 from jckarter/silgen-foreign-to-native-thunk
SILGen: Update emitForeignToNativeThunk to handle async methods.
2 parents 328bd47 + 81b8cdc commit 6722d71

File tree

2 files changed

+66
-10
lines changed

2 files changed

+66
-10
lines changed

lib/SILGen/SILGenBridging.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,11 +1662,19 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
16621662
getConstantInfo(getTypeExpansionContext(), foreignDeclRef);
16631663
auto foreignFnTy = foreignCI.SILFnType;
16641664

1665-
// Find the foreign error convention and 'self' parameter index.
1665+
// Find the foreign error/async convention and 'self' parameter index.
1666+
bool hasError = false;
1667+
Optional<ForeignAsyncConvention> foreignAsync;
1668+
if (nativeFnTy->isAsync()) {
1669+
foreignAsync = fd->getForeignAsyncConvention();
1670+
assert(foreignAsync && "couldn't find foreign async convention?!");
1671+
}
16661672
Optional<ForeignErrorConvention> foreignError;
16671673
if (nativeFnTy->hasErrorResult()) {
1674+
hasError = true;
16681675
foreignError = fd->getForeignErrorConvention();
1669-
assert(foreignError && "couldn't find foreign error convention!");
1676+
assert((foreignError || foreignAsync)
1677+
&& "couldn't find foreign error or async convention for foreign error!");
16701678
}
16711679
ImportAsMemberStatus memberStatus = fd->getImportAsMemberStatus();
16721680

@@ -1707,7 +1715,7 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
17071715

17081716
// Set up the throw destination if necessary.
17091717
CleanupLocation cleanupLoc(fd);
1710-
if (foreignError) {
1718+
if (hasError) {
17111719
prepareRethrowEpilog(cleanupLoc);
17121720
}
17131721

@@ -1719,14 +1727,20 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
17191727
SmallVector<ManagedValue, 8> args;
17201728
unsigned foreignArgIndex = 0;
17211729

1722-
// A helper function to add a function error argument in the
1730+
// A helper function to add a placeholder for a foreign argument in the
17231731
// appropriate position.
1724-
auto maybeAddForeignErrorArg = [&] {
1725-
if (foreignError &&
1726-
foreignArgIndex == foreignError->getErrorParameterIndex()) {
1732+
auto maybeAddForeignArg = [&]() -> bool {
1733+
if ((foreignError
1734+
&& foreignArgIndex == foreignError->getErrorParameterIndex())
1735+
|| (foreignAsync
1736+
&& foreignArgIndex == foreignAsync->completionHandlerParamIndex()))
1737+
{
17271738
args.push_back(ManagedValue());
17281739
++foreignArgIndex;
1740+
return true;
17291741
}
1742+
1743+
return false;
17301744
};
17311745

17321746
{
@@ -1768,7 +1782,7 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
17681782
llvm_unreachable("unsupported convention");
17691783
}
17701784

1771-
maybeAddForeignErrorArg();
1785+
while (maybeAddForeignArg());
17721786

17731787
bool isSelf = (hasSelfParam && nativeParamIndex == params.size() - 1);
17741788

@@ -1825,7 +1839,7 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
18251839
}
18261840
}
18271841

1828-
maybeAddForeignErrorArg();
1842+
while (maybeAddForeignArg());
18291843

18301844
// Call the original.
18311845
auto subs = getForwardingSubstitutionMap();
@@ -1846,7 +1860,7 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
18461860
bridgedFormalResultType),
18471861
nativeFormalResultType,
18481862
foreignError,
1849-
{}, // TODO foreignAsync
1863+
foreignAsync,
18501864
ImportAsMemberStatus());
18511865

18521866
auto init = indirectResult
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -I %S/Inputs/custom-modules -enable-experimental-concurrency %s -verify | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s
2+
// REQUIRES: objc_interop
3+
4+
import Foundation
5+
import ObjCConcurrency
6+
7+
@objc protocol SlowServing {
8+
func requestInt() async -> Int
9+
func requestString() async -> String
10+
func requestIntAndString() async -> (Int, String)
11+
func tryRequestIntAndString() async throws -> (Int, String)
12+
}
13+
14+
// CHECK-LABEL: sil {{.*}}@{{.*}}15testSlowServing
15+
func testSlowServing(p: SlowServing) async throws {
16+
// CHECK: objc_method {{.*}} $@convention(objc_method) <τ_0_0 where τ_0_0 : SlowServing> (@convention(block) (Int) -> (), τ_0_0) -> ()
17+
let _: Int = await p.requestInt()
18+
// CHECK: objc_method {{.*}} $@convention(objc_method) <τ_0_0 where τ_0_0 : SlowServing> (@convention(block) (NSString) -> (), τ_0_0) -> ()
19+
let _: String = await p.requestString()
20+
// CHECK: objc_method {{.*}} $@convention(objc_method) <τ_0_0 where τ_0_0 : SlowServing> (@convention(block) (Int, NSString) -> (), τ_0_0) -> ()
21+
let _: (Int, String) = await p.requestIntAndString()
22+
// CHECK: objc_method {{.*}} $@convention(objc_method) <τ_0_0 where τ_0_0 : SlowServing> (@convention(block) (Int, Optional<NSString>, Optional<NSError>) -> (), τ_0_0) -> ()
23+
let _: (Int, String) = try await p.tryRequestIntAndString()
24+
}
25+
26+
/*
27+
class SlowSwiftServer: NSObject, SlowServing {
28+
func requestInt() async -> Int { return 0 }
29+
func requestString() async -> String { return "" }
30+
func requestIntAndString() async -> (Int, String) { return (0, "") }
31+
func tryRequestIntAndString() async throws -> (Int, String) { return (0, "") }
32+
}
33+
*/
34+
35+
protocol NativelySlowServing {
36+
func doSomethingSlow(_: String) async -> Int
37+
func findAnswer() async throws -> String
38+
func serverRestart(_: String) async
39+
func findMultipleAnswers() async throws -> (String, Int)
40+
}
41+
42+
extension SlowServer: NativelySlowServing {}

0 commit comments

Comments
 (0)