Skip to content

Commit 22609ac

Browse files
Merge pull request #39957 from nate-chandler/rdar80704984_2
[SILGen] Handled foreign funcs with async, error, and more args.
2 parents dd88e0d + bc09cc9 commit 22609ac

File tree

4 files changed

+163
-33
lines changed

4 files changed

+163
-33
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3299,26 +3299,33 @@ class ArgEmitter {
32993299
}
33003300

33013301
void maybeEmitForeignArgument() {
3302-
if (Foreign.async
3303-
&& Foreign.async->completionHandlerParamIndex() == Args.size()) {
3304-
SILParameterInfo param = claimNextParameters(1).front();
3305-
(void)param;
3306-
3307-
// Leave a placeholder in the position. We'll fill this in with a block
3308-
// capturing the current continuation right before we invoke the
3309-
// function.
3310-
// (We can't do this immediately, because evaluating other arguments
3311-
// may require suspending the async task, which is not allowed while its
3312-
// continuation is active.)
3313-
Args.push_back(ManagedValue::forInContext());
3314-
} else if (Foreign.error
3315-
&& Foreign.error->getErrorParameterIndex() == Args.size()) {
3316-
SILParameterInfo param = claimNextParameters(1).front();
3317-
assert(param.getConvention() == ParameterConvention::Direct_Unowned);
3318-
(void) param;
3319-
3320-
// Leave a placeholder in the position.
3321-
Args.push_back(ManagedValue::forInContext());
3302+
bool keepGoing = true;
3303+
while (keepGoing) {
3304+
keepGoing = false;
3305+
if (Foreign.async &&
3306+
Foreign.async->completionHandlerParamIndex() == Args.size()) {
3307+
SILParameterInfo param = claimNextParameters(1).front();
3308+
(void)param;
3309+
3310+
// Leave a placeholder in the position. We'll fill this in with a block
3311+
// capturing the current continuation right before we invoke the
3312+
// function.
3313+
// (We can't do this immediately, because evaluating other arguments
3314+
// may require suspending the async task, which is not allowed while its
3315+
// continuation is active.)
3316+
Args.push_back(ManagedValue::forInContext());
3317+
keepGoing = true;
3318+
}
3319+
if (Foreign.error &&
3320+
Foreign.error->getErrorParameterIndex() == Args.size()) {
3321+
SILParameterInfo param = claimNextParameters(1).front();
3322+
assert(param.getConvention() == ParameterConvention::Direct_Unowned);
3323+
(void)param;
3324+
3325+
// Leave a placeholder in the position.
3326+
Args.push_back(ManagedValue::forInContext());
3327+
keepGoing = true;
3328+
}
33223329
}
33233330
}
33243331

@@ -3541,7 +3548,9 @@ struct ParamLowering {
35413548
}
35423549
}
35433550

3544-
if (foreign.error || foreign.async)
3551+
if (foreign.error)
3552+
++count;
3553+
if (foreign.async)
35453554
++count;
35463555

35473556
if (foreign.self.isImportAsMember()) {
@@ -4202,18 +4211,12 @@ ApplyOptions CallEmission::emitArgumentsForNormalApply(
42024211

42034212
args.push_back({});
42044213

4205-
if (!foreign.async || (foreign.async && foreign.error)) {
4206-
// Claim the foreign error argument(s) with the method formal params.
4207-
auto siteForeignError = ForeignInfo{{}, foreign.error, {}};
4208-
std::move(*callSite).emit(SGF, origFormalType, substFnType, paramLowering,
4209-
args.back(), delayedArgs, siteForeignError);
4210-
}
4211-
if (foreign.async) {
4212-
// Claim the foreign async argument(s) with the method formal params.
4213-
auto siteForeignAsync = ForeignInfo{{}, {}, foreign.async};
4214-
std::move(*callSite).emit(SGF, origFormalType, substFnType, paramLowering,
4215-
args.back(), delayedArgs, siteForeignAsync);
4216-
}
4214+
// Claim the foreign error and/or async arguments when claiming the formal
4215+
// params.
4216+
auto siteForeignError = ForeignInfo{{}, foreign.error, foreign.async};
4217+
// Claim the method formal params.
4218+
std::move(*callSite).emit(SGF, origFormalType, substFnType, paramLowering,
4219+
args.back(), delayedArgs, siteForeignError);
42174220
}
42184221

42194222
uncurriedLoc = callSite->Loc;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <Foundation/Foundation.h>
2+
3+
#pragma clang assume_nonnull begin
4+
5+
typedef void (^CompletionHandler)(int status, NSInteger bytesTransferred);
6+
7+
@interface PFXObject : NSObject
8+
- (BOOL)enqueueFailingRequestWithData:(nullable NSMutableData *)data
9+
error:(NSError *_Nullable *)error
10+
completionHandler:
11+
(nullable CompletionHandler)completionHandler;
12+
- (BOOL)enqueuePassingRequestWithData:(nullable NSMutableData *)data
13+
error:(NSError *_Nullable *)error
14+
completionHandler:
15+
(nullable CompletionHandler)completionHandler;
16+
- (BOOL)enqueueFailingRequestWithData:(nullable NSMutableData *)data
17+
completionTimeout:(NSTimeInterval)completionTimeout
18+
error:(NSError *_Nullable *)error
19+
completionHandler:
20+
(nullable CompletionHandler)completionHandler;
21+
- (BOOL)enqueuePassingRequestWithData:(nullable NSMutableData *)data
22+
completionTimeout:(NSTimeInterval)completionTimeout
23+
error:(NSError *_Nullable *)error
24+
completionHandler:
25+
(nullable CompletionHandler)completionHandler;
26+
@end
27+
28+
#pragma clang assume_nonnull end
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include "rdar80704984_3.h"
2+
3+
#pragma clang assume_nonnull begin
4+
5+
@implementation PFXObject
6+
7+
- (BOOL)enqueueFailingRequestWithData:(nullable NSMutableData *)data
8+
error:(NSError *_Nullable *)error
9+
completionHandler:
10+
(nullable CompletionHandler)completionHandler {
11+
*error = [[NSError alloc] initWithDomain:@"d" code:1 userInfo:nil];
12+
return NO;
13+
}
14+
- (BOOL)enqueuePassingRequestWithData:(nullable NSMutableData *)data
15+
error:(NSError *_Nullable *)error
16+
completionHandler:
17+
(nullable CompletionHandler)completionHandler {
18+
dispatch_async(dispatch_get_main_queue(), ^{
19+
completionHandler(0, 2);
20+
});
21+
return YES;
22+
}
23+
24+
- (BOOL)enqueueFailingRequestWithData:(nullable NSMutableData *)data
25+
completionTimeout:(NSTimeInterval)completionTimeout
26+
error:(NSError *_Nullable *)error
27+
completionHandler:
28+
(nullable CompletionHandler)completionHandler {
29+
*error = [[NSError alloc] initWithDomain:@"d" code:2 userInfo:nil];
30+
return NO;
31+
}
32+
- (BOOL)enqueuePassingRequestWithData:(nullable NSMutableData *)data
33+
completionTimeout:(NSTimeInterval)completionTimeout
34+
error:(NSError *_Nullable *)error
35+
completionHandler:
36+
(nullable CompletionHandler)completionHandler {
37+
dispatch_async(dispatch_get_main_queue(), ^{
38+
completionHandler(0, 3);
39+
});
40+
return YES;
41+
}
42+
43+
@end
44+
45+
#pragma clang assume_nonnull end
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-clang %S/Inputs/rdar80704984_3.m -I %S/Inputs -c -o %t/rdar80704984_3.o
3+
// RUN: %target-build-swift -Xfrontend -disable-availability-checking -import-objc-header %S/Inputs/rdar80704984_3.h -Xlinker %t/rdar80704984_3.o -parse-as-library %s -o %t/a.out
4+
// RUN: %target-codesign %t/a.out
5+
// RUN: %target-run %t/a.out | %FileCheck %s
6+
7+
// REQUIRES: executable_test
8+
// REQUIRES: objc_interop
9+
10+
// rdar://82123254
11+
// UNSUPPORTED: use_os_stdlib
12+
// UNSUPPORTED: back_deployment_runtime
13+
14+
func run1(on object: PFXObject) async throws {
15+
do {
16+
_ = try await object.enqueueFailingRequest(with: nil)
17+
}
18+
catch let error {
19+
// CHECK: Domain=d Code=1
20+
print(error)
21+
}
22+
}
23+
24+
func run2(on object: PFXObject) async throws {
25+
// CHECK: (0, 2)
26+
print(try await object.enqueuePassingRequest(with: nil))
27+
28+
}
29+
30+
func run3(on object: PFXObject) async throws {
31+
do {
32+
_ = try await object.enqueueFailingRequest(with: nil, completionTimeout: 57.0)
33+
}
34+
catch let error {
35+
// CHECK: Domain=d Code=2
36+
print(error)
37+
}
38+
}
39+
40+
func run4(on object: PFXObject) async throws {
41+
// CHECK: (0, 3)
42+
print(try await object.enqueuePassingRequest(with: nil, completionTimeout: 57.0))
43+
44+
}
45+
46+
@main struct Main {
47+
static func main() async throws {
48+
let object = PFXObject()
49+
try await run1(on: object)
50+
try await run2(on: object)
51+
try await run3(on: object)
52+
try await run4(on: object)
53+
}
54+
}

0 commit comments

Comments
 (0)