Skip to content

Commit 45680e0

Browse files
committed
Add AsyncEntryPoint SILDeclRef type
The AsyncEntryPoint represents the thunk that is wrapped in a task. This thunk is used to ensure that the main function explicitly calls "exit", and to properly unwrap and report any unhandled errors returned from the user-written main. The function takes on the name `@async_main` in the emitted SIL.
1 parent 9d6fe19 commit 45680e0

File tree

9 files changed

+67
-3
lines changed

9 files changed

+67
-3
lines changed

include/swift/SIL/SILDeclRef.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,11 @@ struct SILDeclRef {
156156
/// The main entry-point function. This may reference a SourceFile for a
157157
/// top-level main, or a decl for e.g an @main decl.
158158
EntryPoint,
159+
160+
/// The asynchronous main entry-point function.
161+
AsyncEntryPoint,
159162
};
160-
163+
161164
/// The AST node represented by this SILDeclRef.
162165
Loc loc;
163166
/// The Kind of this SILDeclRef.
@@ -227,6 +230,9 @@ struct SILDeclRef {
227230
/// Produces a SILDeclRef for a synthetic main entry-point such as @main.
228231
static SILDeclRef getMainDeclEntryPoint(ValueDecl *decl);
229232

233+
/// Produces a SILDeclRef for the synthesized async main entry-point
234+
static SILDeclRef getAsyncMainDeclEntryPoint(ValueDecl *decl);
235+
230236
/// Produces a SILDeclRef for the entry-point of a main FileUnit.
231237
static SILDeclRef getMainFileEntryPoint(FileUnit *file);
232238

lib/IRGen/GenObjC.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ namespace {
474474
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
475475
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
476476
case SILDeclRef::Kind::EntryPoint:
477+
case SILDeclRef::Kind::AsyncEntryPoint:
477478
llvm_unreachable("Method does not have a selector");
478479

479480
case SILDeclRef::Kind::Destroyer:

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
268268
// The main entry-point is public.
269269
if (kind == Kind::EntryPoint)
270270
return SILLinkage::Public;
271+
if (kind == Kind::AsyncEntryPoint)
272+
return SILLinkage::Hidden;
271273

272274
// Add External to the linkage (e.g. Public -> PublicExternal) if this is a
273275
// declaration not a definition.
@@ -443,6 +445,15 @@ SILDeclRef SILDeclRef::getMainDeclEntryPoint(ValueDecl *decl) {
443445
return result;
444446
}
445447

448+
SILDeclRef SILDeclRef::getAsyncMainDeclEntryPoint(ValueDecl *decl) {
449+
auto *file = cast<FileUnit>(decl->getDeclContext()->getModuleScopeContext());
450+
assert(file->getMainDecl() == decl);
451+
SILDeclRef result;
452+
result.loc = decl;
453+
result.kind = Kind::AsyncEntryPoint;
454+
return result;
455+
}
456+
446457
SILDeclRef SILDeclRef::getMainFileEntryPoint(FileUnit *file) {
447458
assert(file->hasEntryPoint() && !file->getMainDecl());
448459
SILDeclRef result;
@@ -534,7 +545,7 @@ IsSerialized_t SILDeclRef::isSerialized() const {
534545
return IsNotSerialized;
535546
}
536547

537-
if (kind == Kind::EntryPoint)
548+
if (kind == Kind::EntryPoint || kind == Kind::AsyncEntryPoint)
538549
return IsNotSerialized;
539550

540551
if (isIVarInitializerOrDestroyer())
@@ -910,6 +921,9 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
910921
return mangler.mangleInitFromProjectedValueEntity(cast<VarDecl>(getDecl()),
911922
SKind);
912923

924+
case SILDeclRef::Kind::AsyncEntryPoint: {
925+
return "async_Main";
926+
}
913927
case SILDeclRef::Kind::EntryPoint: {
914928
return getASTContext().getEntryPointFunctionName();
915929
}
@@ -1236,7 +1250,8 @@ unsigned SILDeclRef::getParameterListCount() const {
12361250
return 1;
12371251

12381252
// Always uncurried even if the underlying function is curried.
1239-
if (kind == Kind::DefaultArgGenerator || kind == Kind::EntryPoint)
1253+
if (kind == Kind::DefaultArgGenerator || kind == Kind::EntryPoint ||
1254+
kind == Kind::AsyncEntryPoint)
12401255
return 1;
12411256

12421257
auto *vd = getDecl();

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,6 +2497,9 @@ static CanSILFunctionType getNativeSILFunctionType(
24972497
case SILDeclRef::Kind::Deallocator:
24982498
return getSILFunctionTypeForConventions(DeallocatorConventions());
24992499

2500+
case SILDeclRef::Kind::AsyncEntryPoint:
2501+
return getSILFunctionTypeForConventions(
2502+
DefaultConventions(NormalParameterConvention::Guaranteed));
25002503
case SILDeclRef::Kind::EntryPoint:
25012504
llvm_unreachable("Handled by getSILFunctionTypeForAbstractCFunction");
25022505
}
@@ -3027,6 +3030,7 @@ static ObjCSelectorFamily getObjCSelectorFamily(SILDeclRef c) {
30273030
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
30283031
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
30293032
case SILDeclRef::Kind::EntryPoint:
3033+
case SILDeclRef::Kind::AsyncEntryPoint:
30303034
llvm_unreachable("Unexpected Kind of foreign SILDeclRef");
30313035
}
30323036

@@ -3290,6 +3294,8 @@ TypeConverter::getDeclRefRepresentation(SILDeclRef c) {
32903294
case SILDeclRef::Kind::IVarDestroyer:
32913295
return SILFunctionTypeRepresentation::Method;
32923296

3297+
case SILDeclRef::Kind::AsyncEntryPoint:
3298+
return SILFunctionTypeRepresentation::Thin;
32933299
case SILDeclRef::Kind::EntryPoint:
32943300
return SILFunctionTypeRepresentation::CFunctionPointer;
32953301
}
@@ -4120,6 +4126,7 @@ static AbstractFunctionDecl *getBridgedFunction(SILDeclRef declRef) {
41204126
case SILDeclRef::Kind::IVarInitializer:
41214127
case SILDeclRef::Kind::IVarDestroyer:
41224128
case SILDeclRef::Kind::EntryPoint:
4129+
case SILDeclRef::Kind::AsyncEntryPoint:
41234130
return nullptr;
41244131
}
41254132
llvm_unreachable("bad SILDeclRef kind");

lib/SIL/IR/SILPrinter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ void SILDeclRef::print(raw_ostream &OS) const {
316316
switch (kind) {
317317
case SILDeclRef::Kind::Func:
318318
case SILDeclRef::Kind::EntryPoint:
319+
case SILDeclRef::Kind::AsyncEntryPoint:
319320
break;
320321
case SILDeclRef::Kind::Allocator:
321322
OS << "!allocator";

lib/SIL/IR/TypeLowering.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2553,6 +2553,32 @@ getFunctionInterfaceTypeWithCaptures(TypeConverter &TC,
25532553
innerExtInfo);
25542554
}
25552555

2556+
static CanAnyFunctionType getAsyncEntryPoint(ASTContext &C) {
2557+
2558+
// @main struct Main {
2559+
// static func main() async throws {}
2560+
// static func $main() async throws { try await main() }
2561+
// }
2562+
//
2563+
// func @async_main() async -> Void {
2564+
// do {
2565+
// try await Main.$main()
2566+
// exit(0)
2567+
// } catch {
2568+
// _emitErrorInMain(error)
2569+
// }
2570+
// }
2571+
//
2572+
// This generates the type signature for @async_main
2573+
// TODO: 'Never' return type would be more accurate.
2574+
2575+
CanType returnType = C.getVoidType()->getCanonicalType();
2576+
FunctionType::ExtInfo extInfo =
2577+
FunctionType::ExtInfoBuilder().withAsync(true).withThrows(false).build();
2578+
return CanAnyFunctionType::get(/*genericSig*/ nullptr, {}, returnType,
2579+
extInfo);
2580+
}
2581+
25562582
static CanAnyFunctionType getEntryPointInterfaceType(ASTContext &C) {
25572583
// Use standard library types if we have them; otherwise, fall back to
25582584
// builtins.
@@ -2666,6 +2692,8 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
26662692
case SILDeclRef::Kind::IVarDestroyer:
26672693
return getIVarInitDestroyerInterfaceType(cast<ClassDecl>(vd),
26682694
c.isForeign, true);
2695+
case SILDeclRef::Kind::AsyncEntryPoint:
2696+
return getAsyncEntryPoint(Context);
26692697
case SILDeclRef::Kind::EntryPoint:
26702698
return getEntryPointInterfaceType(Context);
26712699
}
@@ -2720,6 +2748,7 @@ TypeConverter::getConstantGenericSignature(SILDeclRef c) {
27202748
case SILDeclRef::Kind::StoredPropertyInitializer:
27212749
return vd->getDeclContext()->getGenericSignatureOfContext();
27222750
case SILDeclRef::Kind::EntryPoint:
2751+
case SILDeclRef::Kind::AsyncEntryPoint:
27232752
llvm_unreachable("Doesn't have generic signature");
27242753
}
27252754

lib/SILGen/SILGen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
10161016
postEmitFunction(constant, f);
10171017
return;
10181018
}
1019+
case SILDeclRef::Kind::AsyncEntryPoint:
10191020
case SILDeclRef::Kind::EntryPoint: {
10201021
f->setBare(IsBare);
10211022

lib/SILGen/SILGenFunction.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ DeclName SILGenModule::getMagicFunctionName(SILDeclRef ref) {
141141
case SILDeclRef::Kind::EnumElement:
142142
return getMagicFunctionName(cast<EnumElementDecl>(ref.getDecl())
143143
->getDeclContext());
144+
case SILDeclRef::Kind::AsyncEntryPoint:
144145
case SILDeclRef::Kind::EntryPoint:
145146
auto *file = ref.getDecl()->getDeclContext()->getParentSourceFile();
146147
return getMagicFunctionName(file);

lib/SILGen/SILGenFunction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
636636
/// application based on a main type and optionally a main type.
637637
void emitArtificialTopLevel(Decl *mainDecl);
638638

639+
/// Generate code into @main for starting the async main on the main thread.
640+
void emitAsyncMainThreadStart(SILDeclRef entryPoint);
641+
639642
/// Generates code for a class deallocating destructor. This
640643
/// calls the destroying destructor and then deallocates 'self'.
641644
void emitDeallocatingDestructor(DestructorDecl *dd);

0 commit comments

Comments
 (0)