Skip to content

Commit 5087e41

Browse files
committed
SILGen: Implement native-to-foreign thunks for async methods.
Bridging an async Swift method back to an ObjC completion-handler-based API requires that the ObjC thunk spawn a task on which to execute the Swift async API and pass its results back on to the completion handler.
1 parent 8914ba6 commit 5087e41

File tree

9 files changed

+340
-48
lines changed

9 files changed

+340
-48
lines changed

include/swift/AST/ExtInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ class SILExtInfo {
827827
SILExtInfo withNoEscape(bool noEscape = true) const {
828828
return builder.withNoEscape(noEscape).build();
829829
}
830+
830831

831832
SILExtInfo withAsync(bool isAsync = true) const {
832833
return builder.withAsync(isAsync).build();

include/swift/SIL/SILDeclRef.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,8 @@ struct SILDeclRef {
428428
assert(isAutoDiffDerivativeFunction());
429429
return pointer.get<AutoDiffDerivativeFunctionIdentifier *>();
430430
}
431+
432+
bool hasAsync() const;
431433

432434
private:
433435
friend struct llvm::DenseMapInfo<swift::SILDeclRef>;

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,3 +1230,13 @@ bool SILDeclRef::isDynamicallyReplaceable() const {
12301230
// enabled.
12311231
return decl->shouldUseNativeMethodReplacement();
12321232
}
1233+
1234+
bool SILDeclRef::hasAsync() const {
1235+
if (hasDecl()) {
1236+
if (auto afd = dyn_cast<AbstractFunctionDecl>(getDecl())) {
1237+
return afd->hasAsync();
1238+
}
1239+
return false;
1240+
}
1241+
return getAbstractClosureExpr()->isBodyAsync();
1242+
}

lib/SILGen/SILGen.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,13 @@ FuncDecl *
391391
SILGenModule::getResumeUnsafeThrowingContinuationWithError() {
392392
return lookupConcurrencyIntrinsic(getASTContext(),
393393
ResumeUnsafeThrowingContinuationWithError,
394-
"_resumeUnsafeThrowingContinuationWithError");
394+
"_resumeUnsafeThrowingContinuationWithError");
395+
}
396+
FuncDecl *
397+
SILGenModule::getRunTaskForBridgedAsyncMethod() {
398+
return lookupConcurrencyIntrinsic(getASTContext(),
399+
RunTaskForBridgedAsyncMethod,
400+
"_runTaskForBridgedAsyncMethod");
395401
}
396402
FuncDecl *
397403
SILGenModule::getRunAsyncHandler() {
@@ -776,7 +782,16 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
776782
PrettyStackTraceSILFunction X("silgen emitNativeToForeignThunk", f);
777783
f->setBare(IsBare);
778784
f->setThunk(IsThunk);
785+
// If the native function is async, then the foreign entry point is not,
786+
// so it needs to spawn a detached task in which to run the native
787+
// implementation, so the actual thunk logic needs to go into a closure
788+
// implementation function.
789+
if (constant.hasAsync()) {
790+
f = SILGenFunction(*this, *f, dc).emitNativeAsyncToForeignThunk(constant);
791+
}
792+
779793
SILGenFunction(*this, *f, dc).emitNativeToForeignThunk(constant);
794+
780795
postEmitFunction(constant, f);
781796
return;
782797
}

lib/SILGen/SILGen.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
123123
Optional<FuncDecl*> TaskFutureGet;
124124
Optional<FuncDecl*> TaskFutureGetThrowing;
125125

126+
Optional<FuncDecl*> RunTaskForBridgedAsyncMethod;
126127
Optional<FuncDecl*> ResumeUnsafeContinuation;
127128
Optional<FuncDecl*> ResumeUnsafeThrowingContinuation;
128129
Optional<FuncDecl*> ResumeUnsafeThrowingContinuationWithError;
@@ -322,7 +323,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
322323

323324
/// Emits a thunk from a Swift function to the native Swift convention.
324325
void emitNativeToForeignThunk(SILDeclRef thunk);
325-
326+
326327
void preEmitFunction(SILDeclRef constant, SILFunction *F, SILLocation L);
327328
void postEmitFunction(SILDeclRef constant, SILFunction *F);
328329

@@ -495,6 +496,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
495496
FuncDecl *getResumeUnsafeThrowingContinuationWithError();
496497
/// Retrieve the _Concurrency._runAsyncHandler intrinsic.
497498
FuncDecl *getRunAsyncHandler();
499+
/// Retrieve the _Concurrency._runTaskForBridgedAsyncMethod intrinsic.
500+
FuncDecl *getRunTaskForBridgedAsyncMethod();
498501

499502
SILFunction *getKeyPathProjectionCoroutine(bool isReadAccess,
500503
KeyPathTypeKind typeKind);

0 commit comments

Comments
 (0)