From b65d71b24aa36f2a200d23efde4651e3861faea9 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 26 Oct 2020 17:16:44 -0700 Subject: [PATCH 1/2] [Async CC] Added conveniences to retrieve argumments. Because all async functions have the same signature, namely void(%swift.task*, %swift.executor*, %swift.context*) it is always possible to provide access to the three argument values (the current task, current executor, and current context) within an IRGenFunction which is async. Here, that is provided in the form of IRGenFunction::getAsyncExecutor,IRGenFunction::getAsyncContext, and IRGenFunction::getAsyncTask. --- lib/IRGen/GenCall.cpp | 21 +++++++++++++++++++++ lib/IRGen/GenCall.h | 5 +++++ lib/IRGen/IRGenFunction.h | 8 ++++++-- lib/IRGen/IRGenSIL.cpp | 38 +++++++++++++++++++++++++++++++++++++- 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index ce0a7784b0f12..e83064f00cfbd 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -273,6 +273,27 @@ static llvm::Value *getAsyncTask(IRGenFunction &IGF) { return llvm::Constant::getNullValue(IGF.IGM.SwiftTaskPtrTy); } +llvm::Value *IRGenFunction::getAsyncTask() { + assert(isAsync()); + auto *value = CurFn->getArg((unsigned)AsyncFunctionArgumentIndex::Task); + assert(value->getType() == IGM.SwiftTaskPtrTy); + return value; +} + +llvm::Value *IRGenFunction::getAsyncExecutor() { + assert(isAsync()); + auto *value = CurFn->getArg((unsigned)AsyncFunctionArgumentIndex::Executor); + assert(value->getType() == IGM.SwiftExecutorPtrTy); + return value; +} + +llvm::Value *IRGenFunction::getAsyncContext() { + assert(isAsync()); + auto *value = CurFn->getArg((unsigned)AsyncFunctionArgumentIndex::Context); + assert(value->getType() == IGM.SwiftContextPtrTy); + return value; +} + llvm::Type *ExplosionSchema::getScalarResultType(IRGenModule &IGM) const { if (size() == 0) { return IGM.VoidTy; diff --git a/lib/IRGen/GenCall.h b/lib/IRGen/GenCall.h index 8f0b58da52721..5a7baea76eb4d 100644 --- a/lib/IRGen/GenCall.h +++ b/lib/IRGen/GenCall.h @@ -340,6 +340,11 @@ namespace irgen { CanSILFunctionType coroutineType, Explosion &yieldedValues); + enum class AsyncFunctionArgumentIndex : unsigned { + Task = 0, + Executor = 1, + Context = 2, + }; } // end namespace irgen } // end namespace swift diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h index 4c3ece3df24a4..61f43c33993c4 100644 --- a/lib/IRGen/IRGenFunction.h +++ b/lib/IRGen/IRGenFunction.h @@ -83,7 +83,7 @@ class IRGenFunction { OptimizationMode Mode = OptimizationMode::NotSet, const SILDebugScope *DbgScope = nullptr, Optional DbgLoc = None); - ~IRGenFunction(); + virtual ~IRGenFunction(); void unimplemented(SourceLoc Loc, StringRef Message); @@ -127,7 +127,11 @@ class IRGenFunction { assert(handle != nullptr && "setting a null handle"); CoroutineHandle = handle; } - + + virtual llvm::Value *getAsyncTask(); + virtual llvm::Value *getAsyncExecutor(); + virtual llvm::Value *getAsyncContext(); + private: void emitPrologue(); void emitEpilogue(); diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index e115b77558d50..150d3a744eb4e 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -852,7 +852,43 @@ class IRGenSILFunction : } } } - + + llvm::Value *getAsyncTask() override { + // FIXME: (1) Remove this override, (2) mark the IRGenFunction::getAsyncTask + // declaration as non-virtual, and (3) mark IRGenFunction's + // destructor non-virtual once Task.runDetached is available. + // rdar://problem/70597390*/ + if (CurSILFn->getLoweredFunctionType()->getRepresentation() == + SILFunctionTypeRepresentation::CFunctionPointer) { + return llvm::Constant::getNullValue(IGM.SwiftTaskPtrTy); + } + return IRGenFunction::getAsyncTask(); + } + + llvm::Value *getAsyncExecutor() override { + // FIXME: (1) Remove this override, (2) mark the + // IRGenFunction::getAsyncExecutor declaration as non-virtual, and + // (3) mark IRGenFunction's destructor non-virtual once + // Task.runDetached is available. rdar://problem/70597390*/ + if (CurSILFn->getLoweredFunctionType()->getRepresentation() == + SILFunctionTypeRepresentation::CFunctionPointer) { + return llvm::Constant::getNullValue(IGM.SwiftExecutorPtrTy); + } + return IRGenFunction::getAsyncExecutor(); + } + + llvm::Value *getAsyncContext() override { + // FIXME: (1) Remove this override, (2) mark the + // IRGenFunction::getAsyncContext declaration as non-virtual, and + // (3) mark IRGenFunction's destructor non-virtual once + // Task.runDetached is available. rdar://problem/70597390*/ + if (CurSILFn->getLoweredFunctionType()->getRepresentation() == + SILFunctionTypeRepresentation::CFunctionPointer) { + return llvm::Constant::getNullValue(IGM.SwiftContextPtrTy); + } + return IRGenFunction::getAsyncContext(); + } + //===--------------------------------------------------------------------===// // SIL instruction lowering //===--------------------------------------------------------------------===// From a5b9e8685061dc7037656e9f1f47b2af9a5f3025 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 26 Oct 2020 16:46:14 -0700 Subject: [PATCH 2/2] [NFC] Used convenience to retrieve context arg. --- lib/IRGen/IRGenSIL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 150d3a744eb4e..06127a14fd9f3 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -3215,7 +3215,7 @@ static void emitReturnInst(IRGenSILFunction &IGF, assert(!IGF.IndirectReturn.isValid() && "Formally direct results should stay direct results for async " "functions"); - llvm::Value *context = IGF.CurFn->getArg(2); + llvm::Value *context = IGF.getAsyncContext(); auto layout = getAsyncContextLayout(IGF); Address dataAddr = layout.emitCastTo(IGF, context);