Skip to content

Commit e7f1ea5

Browse files
[Concurrency] SILGenModule::emitEntryPoint crashes when exit hasn't been imported
If `exit` hasn't been imported, SILGenModule::emitEntryPoint crashes because it doesn't synthesize an exit function like SILGenFunction::emitCallToMain does. Make it do so. rdar://122413238
1 parent 78cf572 commit e7f1ea5

File tree

3 files changed

+40
-15
lines changed

3 files changed

+40
-15
lines changed

lib/SILGen/SILGenTopLevel.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,23 @@
2020
using namespace swift;
2121
using namespace Lowering;
2222

23+
static FuncDecl *synthesizeExit(ASTContext &ctx, ModuleDecl *moduleDecl) {
24+
// Synthesize an exit function with this interface.
25+
// @_extern(c)
26+
// func exit(_: Int32) -> Never
27+
ParameterList *params =
28+
ParameterList::createWithoutLoc(ParamDecl::createImplicit(
29+
ctx, Identifier(), Identifier(), ctx.getInt32Type(), moduleDecl));
30+
FuncDecl *exitFuncDecl = FuncDecl::createImplicit(
31+
ctx, StaticSpellingKind::None,
32+
DeclName(ctx, DeclBaseName(ctx.getIdentifier("exit")), params), {},
33+
/*async*/ false, /*throws*/ false, /*thrownType*/ Type(), {}, params,
34+
ctx.getNeverType(), moduleDecl);
35+
exitFuncDecl->getAttrs().add(new (ctx) ExternAttr(
36+
llvm::None, llvm::None, ExternKind::C, /*implicit*/ true));
37+
return exitFuncDecl;
38+
}
39+
2340
void SILGenModule::emitEntryPoint(SourceFile *SF, SILFunction *TopLevel) {
2441

2542
auto EntryRef = SILDeclRef::getMainFileEntryPoint(SF);
@@ -85,7 +102,10 @@ void SILGenModule::emitEntryPoint(SourceFile *SF, SILFunction *TopLevel) {
85102
SILType returnType;
86103
if (isAsyncTopLevel) {
87104
FuncDecl *exitFuncDecl = getExit();
88-
assert(exitFuncDecl && "Failed to find exit function declaration");
105+
if (!exitFuncDecl) {
106+
// If it doesn't exist, we can conjure one up instead of crashing
107+
exitFuncDecl = synthesizeExit(getASTContext(), TopLevel->getModule().getSwiftModule());
108+
}
89109
exitFunc = getFunction(
90110
SILDeclRef(exitFuncDecl, SILDeclRef::Kind::Func, /*isForeign*/ true),
91111
NotForDefinition);
@@ -216,20 +236,7 @@ void SILGenFunction::emitCallToMain(FuncDecl *mainFunc) {
216236
FuncDecl *exitFuncDecl = SGM.getExit();
217237
if (!exitFuncDecl) {
218238
// If it doesn't exist, we can conjure one up instead of crashing
219-
// @_extern(c)
220-
// func exit(_: Int32) -> Never
221-
ASTContext &ctx = getASTContext();
222-
ModuleDecl *moduleDecl = mainFunc->getModuleContext();
223-
ParameterList *params =
224-
ParameterList::createWithoutLoc(ParamDecl::createImplicit(
225-
ctx, Identifier(), Identifier(), ctx.getInt32Type(), moduleDecl));
226-
exitFuncDecl = FuncDecl::createImplicit(
227-
ctx, StaticSpellingKind::None,
228-
DeclName(ctx, DeclBaseName(ctx.getIdentifier("exit")), params), {},
229-
/*async*/ false, /*throws*/ false, /*thrownType*/ Type(), {}, params,
230-
ctx.getNeverType(), moduleDecl);
231-
exitFuncDecl->getAttrs().add(new (ctx) ExternAttr(
232-
llvm::None, llvm::None, ExternKind::C, /*implicit*/ true));
239+
exitFuncDecl = synthesizeExit(getASTContext(), mainFunc->getModuleContext());
233240
}
234241
SILFunction *exitSILFunc = SGM.getFunction(
235242
SILDeclRef(exitFuncDecl, SILDeclRef::Kind::Func, /*isForeign*/ true),
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-typecheck-verify-swift -parse-as-library -disable-availability-checking -parse-stdlib
2+
// expect-no-diagnostics
3+
4+
import _Concurrency
5+
6+
@main struct Main {
7+
static func main() async {
8+
}
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -parse-stdlib
2+
// expect-no-diagnostics
3+
4+
import _Concurrency
5+
6+
func foo() async {
7+
}
8+
9+
await foo()

0 commit comments

Comments
 (0)