Skip to content

Commit 552ae06

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 b10c2c8 commit 552ae06

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.
@@ -231,6 +234,9 @@ struct SILDeclRef {
231234
/// Produces a SILDeclRef for a synthetic main entry-point such as @main.
232235
static SILDeclRef getMainDeclEntryPoint(ValueDecl *decl);
233236

237+
/// Produces a SILDeclRef for the synthesized async main entry-point
238+
static SILDeclRef getAsyncMainDeclEntryPoint(ValueDecl *decl);
239+
234240
/// Produces a SILDeclRef for the entry-point of a main FileUnit.
235241
static SILDeclRef getMainFileEntryPoint(FileUnit *file);
236242

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
@@ -273,6 +273,8 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
273273
// The main entry-point is public.
274274
if (kind == Kind::EntryPoint)
275275
return SILLinkage::Public;
276+
if (kind == Kind::AsyncEntryPoint)
277+
return SILLinkage::Hidden;
276278

277279
// Add External to the linkage (e.g. Public -> PublicExternal) if this is a
278280
// declaration not a definition.
@@ -448,6 +450,15 @@ SILDeclRef SILDeclRef::getMainDeclEntryPoint(ValueDecl *decl) {
448450
return result;
449451
}
450452

453+
SILDeclRef SILDeclRef::getAsyncMainDeclEntryPoint(ValueDecl *decl) {
454+
auto *file = cast<FileUnit>(decl->getDeclContext()->getModuleScopeContext());
455+
assert(file->getMainDecl() == decl);
456+
SILDeclRef result;
457+
result.loc = decl;
458+
result.kind = Kind::AsyncEntryPoint;
459+
return result;
460+
}
461+
451462
SILDeclRef SILDeclRef::getMainFileEntryPoint(FileUnit *file) {
452463
assert(file->hasEntryPoint() && !file->getMainDecl());
453464
SILDeclRef result;
@@ -539,7 +550,7 @@ IsSerialized_t SILDeclRef::isSerialized() const {
539550
return IsNotSerialized;
540551
}
541552

542-
if (kind == Kind::EntryPoint)
553+
if (kind == Kind::EntryPoint || kind == Kind::AsyncEntryPoint)
543554
return IsNotSerialized;
544555

545556
if (isIVarInitializerOrDestroyer())
@@ -925,6 +936,9 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
925936
return mangler.mangleInitFromProjectedValueEntity(cast<VarDecl>(getDecl()),
926937
SKind);
927938

939+
case SILDeclRef::Kind::AsyncEntryPoint: {
940+
return "async_Main";
941+
}
928942
case SILDeclRef::Kind::EntryPoint: {
929943
return getASTContext().getEntryPointFunctionName();
930944
}
@@ -1257,7 +1271,8 @@ unsigned SILDeclRef::getParameterListCount() const {
12571271
return 1;
12581272

12591273
// Always uncurried even if the underlying function is curried.
1260-
if (kind == Kind::DefaultArgGenerator || kind == Kind::EntryPoint)
1274+
if (kind == Kind::DefaultArgGenerator || kind == Kind::EntryPoint ||
1275+
kind == Kind::AsyncEntryPoint)
12611276
return 1;
12621277

12631278
auto *vd = getDecl();

lib/SIL/IR/SILFunctionType.cpp

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

2529+
case SILDeclRef::Kind::AsyncEntryPoint:
2530+
return getSILFunctionTypeForConventions(
2531+
DefaultConventions(NormalParameterConvention::Guaranteed));
25292532
case SILDeclRef::Kind::EntryPoint:
25302533
llvm_unreachable("Handled by getSILFunctionTypeForAbstractCFunction");
25312534
}
@@ -3071,6 +3074,7 @@ static ObjCSelectorFamily getObjCSelectorFamily(SILDeclRef c) {
30713074
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
30723075
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
30733076
case SILDeclRef::Kind::EntryPoint:
3077+
case SILDeclRef::Kind::AsyncEntryPoint:
30743078
llvm_unreachable("Unexpected Kind of foreign SILDeclRef");
30753079
}
30763080

@@ -3343,6 +3347,8 @@ TypeConverter::getDeclRefRepresentation(SILDeclRef c) {
33433347
case SILDeclRef::Kind::IVarDestroyer:
33443348
return SILFunctionTypeRepresentation::Method;
33453349

3350+
case SILDeclRef::Kind::AsyncEntryPoint:
3351+
return SILFunctionTypeRepresentation::Thin;
33463352
case SILDeclRef::Kind::EntryPoint:
33473353
return SILFunctionTypeRepresentation::CFunctionPointer;
33483354
}
@@ -4170,6 +4176,7 @@ static AbstractFunctionDecl *getBridgedFunction(SILDeclRef declRef) {
41704176
case SILDeclRef::Kind::IVarInitializer:
41714177
case SILDeclRef::Kind::IVarDestroyer:
41724178
case SILDeclRef::Kind::EntryPoint:
4179+
case SILDeclRef::Kind::AsyncEntryPoint:
41734180
return nullptr;
41744181
}
41754182
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
@@ -2556,6 +2556,32 @@ getFunctionInterfaceTypeWithCaptures(TypeConverter &TC,
25562556
innerExtInfo);
25572557
}
25582558

2559+
static CanAnyFunctionType getAsyncEntryPoint(ASTContext &C) {
2560+
2561+
// @main struct Main {
2562+
// static func main() async throws {}
2563+
// static func $main() async throws { try await main() }
2564+
// }
2565+
//
2566+
// func @async_main() async -> Void {
2567+
// do {
2568+
// try await Main.$main()
2569+
// exit(0)
2570+
// } catch {
2571+
// _emitErrorInMain(error)
2572+
// }
2573+
// }
2574+
//
2575+
// This generates the type signature for @async_main
2576+
// TODO: 'Never' return type would be more accurate.
2577+
2578+
CanType returnType = C.getVoidType()->getCanonicalType();
2579+
FunctionType::ExtInfo extInfo =
2580+
FunctionType::ExtInfoBuilder().withAsync(true).withThrows(false).build();
2581+
return CanAnyFunctionType::get(/*genericSig*/ nullptr, {}, returnType,
2582+
extInfo);
2583+
}
2584+
25592585
static CanAnyFunctionType getEntryPointInterfaceType(ASTContext &C) {
25602586
// Use standard library types if we have them; otherwise, fall back to
25612587
// builtins.
@@ -2675,6 +2701,8 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
26752701
case SILDeclRef::Kind::IVarDestroyer:
26762702
return getIVarInitDestroyerInterfaceType(cast<ClassDecl>(vd),
26772703
c.isForeign, true);
2704+
case SILDeclRef::Kind::AsyncEntryPoint:
2705+
return getAsyncEntryPoint(Context);
26782706
case SILDeclRef::Kind::EntryPoint:
26792707
return getEntryPointInterfaceType(Context);
26802708
}
@@ -2729,6 +2757,7 @@ TypeConverter::getConstantGenericSignature(SILDeclRef c) {
27292757
case SILDeclRef::Kind::StoredPropertyInitializer:
27302758
return vd->getDeclContext()->getGenericSignatureOfContext();
27312759
case SILDeclRef::Kind::EntryPoint:
2760+
case SILDeclRef::Kind::AsyncEntryPoint:
27322761
llvm_unreachable("Doesn't have generic signature");
27332762
}
27342763

lib/SILGen/SILGen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
10391039
postEmitFunction(constant, f);
10401040
return;
10411041
}
1042+
case SILDeclRef::Kind::AsyncEntryPoint:
10421043
case SILDeclRef::Kind::EntryPoint: {
10431044
f->setBare(IsBare);
10441045

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
@@ -638,6 +638,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
638638
/// application based on a main type and optionally a main type.
639639
void emitArtificialTopLevel(Decl *mainDecl);
640640

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

0 commit comments

Comments
 (0)