Skip to content

Commit 431b666

Browse files
committed
Generate async main entrypoint for top-level
This patch adds the SILGen side of generating the asynchronous main entrypoint for top-level code. The behavior is the same as with the asynchronous MainType entrypoint.
1 parent 8e7943d commit 431b666

File tree

4 files changed

+94
-33
lines changed

4 files changed

+94
-33
lines changed

include/swift/SIL/SILDeclRef.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,14 @@ struct SILDeclRef {
240240
/// Produces a SILDeclRef for the entry-point of a main FileUnit.
241241
static SILDeclRef getMainFileEntryPoint(FileUnit *file);
242242

243+
/// Produces a SILDeclRef for the entry-point of an async main FileUnit.
244+
static SILDeclRef getAsyncMainFileEntryPoint(FileUnit *file);
245+
243246
bool isNull() const { return loc.isNull(); }
244247
explicit operator bool() const { return !isNull(); }
245-
248+
246249
bool hasDecl() const { return loc.is<ValueDecl *>(); }
250+
bool hasFileUnit() const { return loc.is<FileUnit *>(); }
247251
bool hasClosureExpr() const;
248252
bool hasAutoClosureExpr() const;
249253
bool hasFuncDecl() const;
@@ -260,11 +264,14 @@ struct SILDeclRef {
260264
return loc.get<FileUnit *>();
261265
}
262266

267+
/// Get ModuleDecl that contains the SILDeclRef
268+
ModuleDecl *getModuleContext() const;
269+
263270
/// Retrieves the ASTContext from the underlying AST node being stored.
264271
ASTContext &getASTContext() const;
265272

266273
llvm::Optional<AnyFunctionRef> getAnyFunctionRef() const;
267-
274+
268275
SILLocation getAsRegularLocation() const;
269276

270277
enum class ManglingKind {

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,14 @@ SILDeclRef SILDeclRef::getAsyncMainDeclEntryPoint(ValueDecl *decl) {
459459
return result;
460460
}
461461

462+
SILDeclRef SILDeclRef::getAsyncMainFileEntryPoint(FileUnit *file) {
463+
assert(file->hasEntryPoint() && !file->getMainDecl());
464+
SILDeclRef result;
465+
result.loc = file;
466+
result.kind = Kind::AsyncEntryPoint;
467+
return result;
468+
}
469+
462470
SILDeclRef SILDeclRef::getMainFileEntryPoint(FileUnit *file) {
463471
assert(file->hasEntryPoint() && !file->getMainDecl());
464472
SILDeclRef result;
@@ -492,6 +500,19 @@ FuncDecl *SILDeclRef::getFuncDecl() const {
492500
return dyn_cast<FuncDecl>(getDecl());
493501
}
494502

503+
ModuleDecl *SILDeclRef::getModuleContext() const {
504+
if (hasDecl()) {
505+
return getDecl()->getModuleContext();
506+
} else if (hasFileUnit()) {
507+
return getFileUnit()->getParentModule();
508+
} else if (hasClosureExpr()) {
509+
return getClosureExpr()->getParentModule();
510+
} else if (hasAutoClosureExpr()) {
511+
return getAutoClosureExpr()->getParentModule();
512+
}
513+
llvm_unreachable("Unknown declaration reference");
514+
}
515+
495516
bool SILDeclRef::isSetter() const {
496517
if (!hasDecl())
497518
return false;

lib/SILGen/SILGen.cpp

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,6 +1945,7 @@ namespace {
19451945
class SourceFileScope {
19461946
SILGenModule &sgm;
19471947
Optional<Scope> scope;
1948+
bool isAsyncTopLevel = false;
19481949
public:
19491950
SourceFileScope(SILGenModule &sgm, SourceFile *sf) : sgm(sgm) {
19501951
// If this is the script-mode file for the module, create a toplevel.
@@ -1954,30 +1955,39 @@ class SourceFileScope {
19541955
sgm.getASTContext().getEntryPointFunctionName()) &&
19551956
"already emitted toplevel?!");
19561957

1957-
RegularLocation TopLevelLoc = RegularLocation::getModuleLocation();
1958-
auto ref = SILDeclRef::getMainFileEntryPoint(sf);
1959-
auto *toplevel = sgm.getFunction(ref, ForDefinition);
1958+
auto mainEntryRef = SILDeclRef::getMainFileEntryPoint(sf);
1959+
SILFunction * toplevel = sgm.getFunction(mainEntryRef, ForDefinition);
19601960
toplevel->setBare(IsBare);
19611961

1962-
// Assign a debug scope pointing into the void to the top level function.
1963-
toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc, toplevel));
1962+
if (sf->isAsyncContext()) {
1963+
isAsyncTopLevel = true;
1964+
auto asyncEntryRef = SILDeclRef::getAsyncMainFileEntryPoint(sf);
1965+
SILFunction * asyncTopLevel = sgm.getFunction(asyncEntryRef, ForDefinition);
1966+
SILGenFunction(sgm, *toplevel, sf).emitAsyncMainThreadStart(asyncEntryRef);
1967+
toplevel = asyncTopLevel;
1968+
}
19641969

19651970
sgm.TopLevelSGF = new SILGenFunction(sgm, *toplevel, sf);
19661971
sgm.TopLevelSGF->MagicFunctionName = sgm.SwiftModule->getName();
19671972
auto moduleCleanupLoc = CleanupLocation::getModuleCleanupLocation();
1968-
sgm.TopLevelSGF->prepareEpilog(None, true, moduleCleanupLoc);
19691973

1970-
// Create the argc and argv arguments.
1971-
auto prologueLoc = RegularLocation::getModuleLocation();
1972-
prologueLoc.markAsPrologue();
1973-
auto entry = sgm.TopLevelSGF->B.getInsertionBB();
1974-
auto context = sgm.TopLevelSGF->getTypeExpansionContext();
1975-
auto paramTypeIter = sgm.TopLevelSGF->F.getConventions()
1976-
.getParameterSILTypes(context)
1977-
.begin();
1978-
entry->createFunctionArgument(*paramTypeIter);
1979-
entry->createFunctionArgument(*std::next(paramTypeIter));
1974+
sgm.TopLevelSGF->prepareEpilog(None, true, moduleCleanupLoc);
19801975

1976+
// emitAsyncMainThreadStart will handle creating argc argv
1977+
// for the async case
1978+
if (!sf->isAsyncContext()) {
1979+
// Create the argc and argv arguments.
1980+
auto prologueLoc = RegularLocation::getModuleLocation();
1981+
prologueLoc.markAsPrologue();
1982+
auto entry = sgm.TopLevelSGF->B.getInsertionBB();
1983+
auto context = sgm.TopLevelSGF->getTypeExpansionContext();
1984+
auto paramTypeIter = sgm.TopLevelSGF->F.getConventions()
1985+
.getParameterSILTypes(context)
1986+
.begin();
1987+
1988+
entry->createFunctionArgument(*paramTypeIter);
1989+
entry->createFunctionArgument(*std::next(paramTypeIter));
1990+
}
19811991
scope.emplace(sgm.TopLevelSGF->Cleanups, moduleCleanupLoc);
19821992
}
19831993
}
@@ -1997,8 +2007,23 @@ class SourceFileScope {
19972007
auto returnLoc = returnInfo.second;
19982008
returnLoc.markAutoGenerated();
19992009

2000-
SILType returnType = SGF.F.getConventions().getSingleSILResultType(
2001-
SGF.getTypeExpansionContext());
2010+
SILFunction *exitFunc = nullptr;
2011+
2012+
SILType returnType;
2013+
if (isAsyncTopLevel) {
2014+
FuncDecl *exitFuncDecl = sgm.getExit();
2015+
assert(exitFuncDecl && "Failed to find exit function declaration");
2016+
exitFunc = sgm.getFunction(
2017+
SILDeclRef(exitFuncDecl, SILDeclRef::Kind::Func, /*isForeign*/true),
2018+
NotForDefinition);
2019+
SILFunctionType & funcType = *exitFunc->getLoweredType().getAs<SILFunctionType>();
2020+
returnType = SILType::getPrimitiveObjectType(
2021+
funcType.getParameters().front().getInterfaceType());
2022+
} else {
2023+
returnType = SGF.F.getConventions().getSingleSILResultType(
2024+
SGF.getTypeExpansionContext());
2025+
}
2026+
20022027
auto emitTopLevelReturnValue = [&](unsigned value) -> SILValue {
20032028
// Create an integer literal for the value.
20042029
auto litType = SILType::getBuiltinIntegerType(32, sgm.getASTContext());
@@ -2059,8 +2084,16 @@ class SourceFileScope {
20592084
}
20602085

20612086
// Return.
2062-
if (SGF.B.hasValidInsertionPoint())
2063-
SGF.B.createReturn(returnLoc, returnValue);
2087+
if (SGF.B.hasValidInsertionPoint()) {
2088+
2089+
if (isAsyncTopLevel) {
2090+
SILValue exitCall = SGF.B.createFunctionRef(moduleLoc, exitFunc);
2091+
SGF.B.createApply(moduleLoc, exitCall, {}, {returnValue});
2092+
SGF.B.createUnreachable(moduleLoc);
2093+
} else {
2094+
SGF.B.createReturn(returnLoc, returnValue);
2095+
}
2096+
}
20642097

20652098
// Okay, we're done emitting the top-level function; destroy the
20662099
// emitter and verify the result.

lib/SILGen/SILGenFunction.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,7 @@ void SILGenFunction::emitAsyncMainThreadStart(SILDeclRef entryPoint) {
864864
entryBlock->createFunctionArgument(*std::next(paramTypeIter)); // argv
865865

866866
// Lookup necessary functions
867-
swift::ASTContext &ctx = entryPoint.getDecl()->getASTContext();
867+
swift::ASTContext &ctx = entryPoint.getASTContext();
868868

869869
B.setInsertionPoint(entryBlock);
870870

@@ -880,7 +880,7 @@ void SILGenFunction::emitAsyncMainThreadStart(SILDeclRef entryPoint) {
880880

881881
// Call CreateAsyncTask
882882
FuncDecl *builtinDecl = cast<FuncDecl>(getBuiltinValueDecl(
883-
getASTContext(),
883+
ctx,
884884
ctx.getIdentifier(getBuiltinName(BuiltinValueKind::CreateAsyncTask))));
885885
auto subs = SubstitutionMap::get(builtinDecl->getGenericSignature(),
886886
{TupleType::getEmpty(ctx)},
@@ -922,6 +922,7 @@ void SILGenFunction::emitAsyncMainThreadStart(SILDeclRef entryPoint) {
922922
JobType, {}, {task});
923923
jobResult = wrapCallArgs(jobResult, swiftJobRunFuncDecl, 0);
924924

925+
ModuleDecl * moduleDecl = entryPoint.getModuleContext();
925926
// Get main executor
926927
FuncDecl *getMainExecutorFuncDecl = SGM.getGetMainExecutor();
927928
if (!getMainExecutorFuncDecl) {
@@ -931,18 +932,18 @@ void SILGenFunction::emitAsyncMainThreadStart(SILDeclRef entryPoint) {
931932
// @_silgen_name("swift_task_getMainExecutor")
932933
// internal func _getMainExecutor() -> Builtin.Executor
933934

934-
ParameterList *emptyParams = ParameterList::createEmpty(getASTContext());
935+
ParameterList *emptyParams = ParameterList::createEmpty(ctx);
935936
getMainExecutorFuncDecl = FuncDecl::createImplicit(
936-
getASTContext(), StaticSpellingKind::None,
937+
ctx, StaticSpellingKind::None,
937938
DeclName(
938-
getASTContext(),
939-
DeclBaseName(getASTContext().getIdentifier("_getMainExecutor")),
939+
ctx,
940+
DeclBaseName(ctx.getIdentifier("_getMainExecutor")),
940941
/*Arguments*/ emptyParams),
941942
{}, /*async*/ false, /*throws*/ false, {}, emptyParams,
942-
getASTContext().TheExecutorType,
943-
entryPoint.getDecl()->getModuleContext());
943+
ctx.TheExecutorType,
944+
moduleDecl);
944945
getMainExecutorFuncDecl->getAttrs().add(
945-
new (getASTContext())
946+
new (ctx)
946947
SILGenNameAttr("swift_task_getMainExecutor", /*implicit*/ true));
947948
}
948949

@@ -972,8 +973,7 @@ void SILGenFunction::emitAsyncMainThreadStart(SILDeclRef entryPoint) {
972973
DeclBaseName(getASTContext().getIdentifier("_asyncMainDrainQueue")),
973974
/*Arguments*/ emptyParams),
974975
{}, /*async*/ false, /*throws*/ false, {}, emptyParams,
975-
getASTContext().getNeverType(),
976-
entryPoint.getDecl()->getModuleContext());
976+
getASTContext().getNeverType(), moduleDecl);
977977
drainQueueFuncDecl->getAttrs().add(new (getASTContext()) SILGenNameAttr(
978978
"swift_task_asyncMainDrainQueue", /*implicit*/ true));
979979
}

0 commit comments

Comments
 (0)