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.
This commit is contained in:
Evan Wilde
2021-07-29 17:00:27 -07:00
parent b10c2c89a9
commit 552ae0635a
9 changed files with 67 additions and 3 deletions

View File

@@ -273,6 +273,8 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
// The main entry-point is public.
if (kind == Kind::EntryPoint)
return SILLinkage::Public;
if (kind == Kind::AsyncEntryPoint)
return SILLinkage::Hidden;
// Add External to the linkage (e.g. Public -> PublicExternal) if this is a
// declaration not a definition.
@@ -448,6 +450,15 @@ SILDeclRef SILDeclRef::getMainDeclEntryPoint(ValueDecl *decl) {
return result;
}
SILDeclRef SILDeclRef::getAsyncMainDeclEntryPoint(ValueDecl *decl) {
auto *file = cast<FileUnit>(decl->getDeclContext()->getModuleScopeContext());
assert(file->getMainDecl() == decl);
SILDeclRef result;
result.loc = decl;
result.kind = Kind::AsyncEntryPoint;
return result;
}
SILDeclRef SILDeclRef::getMainFileEntryPoint(FileUnit *file) {
assert(file->hasEntryPoint() && !file->getMainDecl());
SILDeclRef result;
@@ -539,7 +550,7 @@ IsSerialized_t SILDeclRef::isSerialized() const {
return IsNotSerialized;
}
if (kind == Kind::EntryPoint)
if (kind == Kind::EntryPoint || kind == Kind::AsyncEntryPoint)
return IsNotSerialized;
if (isIVarInitializerOrDestroyer())
@@ -925,6 +936,9 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
return mangler.mangleInitFromProjectedValueEntity(cast<VarDecl>(getDecl()),
SKind);
case SILDeclRef::Kind::AsyncEntryPoint: {
return "async_Main";
}
case SILDeclRef::Kind::EntryPoint: {
return getASTContext().getEntryPointFunctionName();
}
@@ -1257,7 +1271,8 @@ unsigned SILDeclRef::getParameterListCount() const {
return 1;
// Always uncurried even if the underlying function is curried.
if (kind == Kind::DefaultArgGenerator || kind == Kind::EntryPoint)
if (kind == Kind::DefaultArgGenerator || kind == Kind::EntryPoint ||
kind == Kind::AsyncEntryPoint)
return 1;
auto *vd = getDecl();