mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -156,8 +156,11 @@ struct SILDeclRef {
|
|||||||
/// The main entry-point function. This may reference a SourceFile for a
|
/// The main entry-point function. This may reference a SourceFile for a
|
||||||
/// top-level main, or a decl for e.g an @main decl.
|
/// top-level main, or a decl for e.g an @main decl.
|
||||||
EntryPoint,
|
EntryPoint,
|
||||||
|
|
||||||
|
/// The asynchronous main entry-point function.
|
||||||
|
AsyncEntryPoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The AST node represented by this SILDeclRef.
|
/// The AST node represented by this SILDeclRef.
|
||||||
Loc loc;
|
Loc loc;
|
||||||
/// The Kind of this SILDeclRef.
|
/// The Kind of this SILDeclRef.
|
||||||
@@ -231,6 +234,9 @@ struct SILDeclRef {
|
|||||||
/// Produces a SILDeclRef for a synthetic main entry-point such as @main.
|
/// Produces a SILDeclRef for a synthetic main entry-point such as @main.
|
||||||
static SILDeclRef getMainDeclEntryPoint(ValueDecl *decl);
|
static SILDeclRef getMainDeclEntryPoint(ValueDecl *decl);
|
||||||
|
|
||||||
|
/// Produces a SILDeclRef for the synthesized async main entry-point
|
||||||
|
static SILDeclRef getAsyncMainDeclEntryPoint(ValueDecl *decl);
|
||||||
|
|
||||||
/// Produces a SILDeclRef for the entry-point of a main FileUnit.
|
/// Produces a SILDeclRef for the entry-point of a main FileUnit.
|
||||||
static SILDeclRef getMainFileEntryPoint(FileUnit *file);
|
static SILDeclRef getMainFileEntryPoint(FileUnit *file);
|
||||||
|
|
||||||
|
|||||||
@@ -474,6 +474,7 @@ namespace {
|
|||||||
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
|
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
|
||||||
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
|
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
|
||||||
case SILDeclRef::Kind::EntryPoint:
|
case SILDeclRef::Kind::EntryPoint:
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint:
|
||||||
llvm_unreachable("Method does not have a selector");
|
llvm_unreachable("Method does not have a selector");
|
||||||
|
|
||||||
case SILDeclRef::Kind::Destroyer:
|
case SILDeclRef::Kind::Destroyer:
|
||||||
|
|||||||
@@ -273,6 +273,8 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
|
|||||||
// The main entry-point is public.
|
// The main entry-point is public.
|
||||||
if (kind == Kind::EntryPoint)
|
if (kind == Kind::EntryPoint)
|
||||||
return SILLinkage::Public;
|
return SILLinkage::Public;
|
||||||
|
if (kind == Kind::AsyncEntryPoint)
|
||||||
|
return SILLinkage::Hidden;
|
||||||
|
|
||||||
// Add External to the linkage (e.g. Public -> PublicExternal) if this is a
|
// Add External to the linkage (e.g. Public -> PublicExternal) if this is a
|
||||||
// declaration not a definition.
|
// declaration not a definition.
|
||||||
@@ -448,6 +450,15 @@ SILDeclRef SILDeclRef::getMainDeclEntryPoint(ValueDecl *decl) {
|
|||||||
return result;
|
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) {
|
SILDeclRef SILDeclRef::getMainFileEntryPoint(FileUnit *file) {
|
||||||
assert(file->hasEntryPoint() && !file->getMainDecl());
|
assert(file->hasEntryPoint() && !file->getMainDecl());
|
||||||
SILDeclRef result;
|
SILDeclRef result;
|
||||||
@@ -539,7 +550,7 @@ IsSerialized_t SILDeclRef::isSerialized() const {
|
|||||||
return IsNotSerialized;
|
return IsNotSerialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind == Kind::EntryPoint)
|
if (kind == Kind::EntryPoint || kind == Kind::AsyncEntryPoint)
|
||||||
return IsNotSerialized;
|
return IsNotSerialized;
|
||||||
|
|
||||||
if (isIVarInitializerOrDestroyer())
|
if (isIVarInitializerOrDestroyer())
|
||||||
@@ -925,6 +936,9 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
|
|||||||
return mangler.mangleInitFromProjectedValueEntity(cast<VarDecl>(getDecl()),
|
return mangler.mangleInitFromProjectedValueEntity(cast<VarDecl>(getDecl()),
|
||||||
SKind);
|
SKind);
|
||||||
|
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint: {
|
||||||
|
return "async_Main";
|
||||||
|
}
|
||||||
case SILDeclRef::Kind::EntryPoint: {
|
case SILDeclRef::Kind::EntryPoint: {
|
||||||
return getASTContext().getEntryPointFunctionName();
|
return getASTContext().getEntryPointFunctionName();
|
||||||
}
|
}
|
||||||
@@ -1257,7 +1271,8 @@ unsigned SILDeclRef::getParameterListCount() const {
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// Always uncurried even if the underlying function is curried.
|
// 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;
|
return 1;
|
||||||
|
|
||||||
auto *vd = getDecl();
|
auto *vd = getDecl();
|
||||||
|
|||||||
@@ -2526,6 +2526,9 @@ static CanSILFunctionType getNativeSILFunctionType(
|
|||||||
case SILDeclRef::Kind::Deallocator:
|
case SILDeclRef::Kind::Deallocator:
|
||||||
return getSILFunctionTypeForConventions(DeallocatorConventions());
|
return getSILFunctionTypeForConventions(DeallocatorConventions());
|
||||||
|
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint:
|
||||||
|
return getSILFunctionTypeForConventions(
|
||||||
|
DefaultConventions(NormalParameterConvention::Guaranteed));
|
||||||
case SILDeclRef::Kind::EntryPoint:
|
case SILDeclRef::Kind::EntryPoint:
|
||||||
llvm_unreachable("Handled by getSILFunctionTypeForAbstractCFunction");
|
llvm_unreachable("Handled by getSILFunctionTypeForAbstractCFunction");
|
||||||
}
|
}
|
||||||
@@ -3071,6 +3074,7 @@ static ObjCSelectorFamily getObjCSelectorFamily(SILDeclRef c) {
|
|||||||
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
|
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
|
||||||
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
|
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
|
||||||
case SILDeclRef::Kind::EntryPoint:
|
case SILDeclRef::Kind::EntryPoint:
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint:
|
||||||
llvm_unreachable("Unexpected Kind of foreign SILDeclRef");
|
llvm_unreachable("Unexpected Kind of foreign SILDeclRef");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3343,6 +3347,8 @@ TypeConverter::getDeclRefRepresentation(SILDeclRef c) {
|
|||||||
case SILDeclRef::Kind::IVarDestroyer:
|
case SILDeclRef::Kind::IVarDestroyer:
|
||||||
return SILFunctionTypeRepresentation::Method;
|
return SILFunctionTypeRepresentation::Method;
|
||||||
|
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint:
|
||||||
|
return SILFunctionTypeRepresentation::Thin;
|
||||||
case SILDeclRef::Kind::EntryPoint:
|
case SILDeclRef::Kind::EntryPoint:
|
||||||
return SILFunctionTypeRepresentation::CFunctionPointer;
|
return SILFunctionTypeRepresentation::CFunctionPointer;
|
||||||
}
|
}
|
||||||
@@ -4170,6 +4176,7 @@ static AbstractFunctionDecl *getBridgedFunction(SILDeclRef declRef) {
|
|||||||
case SILDeclRef::Kind::IVarInitializer:
|
case SILDeclRef::Kind::IVarInitializer:
|
||||||
case SILDeclRef::Kind::IVarDestroyer:
|
case SILDeclRef::Kind::IVarDestroyer:
|
||||||
case SILDeclRef::Kind::EntryPoint:
|
case SILDeclRef::Kind::EntryPoint:
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
llvm_unreachable("bad SILDeclRef kind");
|
llvm_unreachable("bad SILDeclRef kind");
|
||||||
|
|||||||
@@ -316,6 +316,7 @@ void SILDeclRef::print(raw_ostream &OS) const {
|
|||||||
switch (kind) {
|
switch (kind) {
|
||||||
case SILDeclRef::Kind::Func:
|
case SILDeclRef::Kind::Func:
|
||||||
case SILDeclRef::Kind::EntryPoint:
|
case SILDeclRef::Kind::EntryPoint:
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint:
|
||||||
break;
|
break;
|
||||||
case SILDeclRef::Kind::Allocator:
|
case SILDeclRef::Kind::Allocator:
|
||||||
OS << "!allocator";
|
OS << "!allocator";
|
||||||
|
|||||||
@@ -2556,6 +2556,32 @@ getFunctionInterfaceTypeWithCaptures(TypeConverter &TC,
|
|||||||
innerExtInfo);
|
innerExtInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CanAnyFunctionType getAsyncEntryPoint(ASTContext &C) {
|
||||||
|
|
||||||
|
// @main struct Main {
|
||||||
|
// static func main() async throws {}
|
||||||
|
// static func $main() async throws { try await main() }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func @async_main() async -> Void {
|
||||||
|
// do {
|
||||||
|
// try await Main.$main()
|
||||||
|
// exit(0)
|
||||||
|
// } catch {
|
||||||
|
// _emitErrorInMain(error)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// This generates the type signature for @async_main
|
||||||
|
// TODO: 'Never' return type would be more accurate.
|
||||||
|
|
||||||
|
CanType returnType = C.getVoidType()->getCanonicalType();
|
||||||
|
FunctionType::ExtInfo extInfo =
|
||||||
|
FunctionType::ExtInfoBuilder().withAsync(true).withThrows(false).build();
|
||||||
|
return CanAnyFunctionType::get(/*genericSig*/ nullptr, {}, returnType,
|
||||||
|
extInfo);
|
||||||
|
}
|
||||||
|
|
||||||
static CanAnyFunctionType getEntryPointInterfaceType(ASTContext &C) {
|
static CanAnyFunctionType getEntryPointInterfaceType(ASTContext &C) {
|
||||||
// Use standard library types if we have them; otherwise, fall back to
|
// Use standard library types if we have them; otherwise, fall back to
|
||||||
// builtins.
|
// builtins.
|
||||||
@@ -2675,6 +2701,8 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
|
|||||||
case SILDeclRef::Kind::IVarDestroyer:
|
case SILDeclRef::Kind::IVarDestroyer:
|
||||||
return getIVarInitDestroyerInterfaceType(cast<ClassDecl>(vd),
|
return getIVarInitDestroyerInterfaceType(cast<ClassDecl>(vd),
|
||||||
c.isForeign, true);
|
c.isForeign, true);
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint:
|
||||||
|
return getAsyncEntryPoint(Context);
|
||||||
case SILDeclRef::Kind::EntryPoint:
|
case SILDeclRef::Kind::EntryPoint:
|
||||||
return getEntryPointInterfaceType(Context);
|
return getEntryPointInterfaceType(Context);
|
||||||
}
|
}
|
||||||
@@ -2729,6 +2757,7 @@ TypeConverter::getConstantGenericSignature(SILDeclRef c) {
|
|||||||
case SILDeclRef::Kind::StoredPropertyInitializer:
|
case SILDeclRef::Kind::StoredPropertyInitializer:
|
||||||
return vd->getDeclContext()->getGenericSignatureOfContext();
|
return vd->getDeclContext()->getGenericSignatureOfContext();
|
||||||
case SILDeclRef::Kind::EntryPoint:
|
case SILDeclRef::Kind::EntryPoint:
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint:
|
||||||
llvm_unreachable("Doesn't have generic signature");
|
llvm_unreachable("Doesn't have generic signature");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1039,6 +1039,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
|
|||||||
postEmitFunction(constant, f);
|
postEmitFunction(constant, f);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint:
|
||||||
case SILDeclRef::Kind::EntryPoint: {
|
case SILDeclRef::Kind::EntryPoint: {
|
||||||
f->setBare(IsBare);
|
f->setBare(IsBare);
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ DeclName SILGenModule::getMagicFunctionName(SILDeclRef ref) {
|
|||||||
case SILDeclRef::Kind::EnumElement:
|
case SILDeclRef::Kind::EnumElement:
|
||||||
return getMagicFunctionName(cast<EnumElementDecl>(ref.getDecl())
|
return getMagicFunctionName(cast<EnumElementDecl>(ref.getDecl())
|
||||||
->getDeclContext());
|
->getDeclContext());
|
||||||
|
case SILDeclRef::Kind::AsyncEntryPoint:
|
||||||
case SILDeclRef::Kind::EntryPoint:
|
case SILDeclRef::Kind::EntryPoint:
|
||||||
auto *file = ref.getDecl()->getDeclContext()->getParentSourceFile();
|
auto *file = ref.getDecl()->getDeclContext()->getParentSourceFile();
|
||||||
return getMagicFunctionName(file);
|
return getMagicFunctionName(file);
|
||||||
|
|||||||
@@ -638,6 +638,9 @@ public:
|
|||||||
/// application based on a main type and optionally a main type.
|
/// application based on a main type and optionally a main type.
|
||||||
void emitArtificialTopLevel(Decl *mainDecl);
|
void emitArtificialTopLevel(Decl *mainDecl);
|
||||||
|
|
||||||
|
/// Generate code into @main for starting the async main on the main thread.
|
||||||
|
void emitAsyncMainThreadStart(SILDeclRef entryPoint);
|
||||||
|
|
||||||
/// Generates code for a class deallocating destructor. This
|
/// Generates code for a class deallocating destructor. This
|
||||||
/// calls the destroying destructor and then deallocates 'self'.
|
/// calls the destroying destructor and then deallocates 'self'.
|
||||||
void emitDeallocatingDestructor(DestructorDecl *dd);
|
void emitDeallocatingDestructor(DestructorDecl *dd);
|
||||||
|
|||||||
Reference in New Issue
Block a user