-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Re-working async-main #38604
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Re-working async-main #38604
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
b10c2c8
Paramterize module in lookupIntrinsic
etcwilde 552ae06
Add AsyncEntryPoint SILDeclRef type
etcwilde d376ee9
Run first thunk of Async main synchronously
etcwilde 493eca3
Inherit main thread priority/context
etcwilde d9baba9
Fix priority test
etcwilde bb80f9f
Replace reinterpret cast with struct
etcwilde File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -338,24 +338,15 @@ SILGenModule::getConformanceToBridgedStoredNSError(SILLocation loc, Type type) { | |
return SwiftModule->lookupConformance(type, proto); | ||
} | ||
|
||
static FuncDecl *lookupConcurrencyIntrinsic(ASTContext &C, | ||
Optional<FuncDecl*> &cache, | ||
StringRef name) { | ||
static FuncDecl *lookupIntrinsic(ModuleDecl &module, | ||
Optional<FuncDecl *> &cache, Identifier name) { | ||
if (cache) | ||
return *cache; | ||
|
||
auto *module = C.getLoadedModule(C.Id_Concurrency); | ||
if (!module) { | ||
cache = nullptr; | ||
return nullptr; | ||
} | ||
|
||
SmallVector<ValueDecl *, 1> decls; | ||
module->lookupQualified(module, | ||
DeclNameRef(C.getIdentifier(name)), | ||
NL_QualifiedDefault | NL_IncludeUsableFromInline, | ||
decls); | ||
|
||
SmallVector<ValueDecl *, 1> decls; | ||
module.lookupQualified(&module, DeclNameRef(name), | ||
NL_QualifiedDefault | NL_IncludeUsableFromInline, | ||
decls); | ||
if (decls.size() != 1) { | ||
cache = nullptr; | ||
return nullptr; | ||
|
@@ -365,6 +356,18 @@ static FuncDecl *lookupConcurrencyIntrinsic(ASTContext &C, | |
return func; | ||
} | ||
|
||
static FuncDecl *lookupConcurrencyIntrinsic(ASTContext &C, | ||
Optional<FuncDecl *> &cache, | ||
StringRef name) { | ||
auto *module = C.getLoadedModule(C.Id_Concurrency); | ||
if (!module) { | ||
cache = nullptr; | ||
return nullptr; | ||
} | ||
|
||
return lookupIntrinsic(*module, cache, C.getIdentifier(name)); | ||
} | ||
|
||
FuncDecl * | ||
SILGenModule::getAsyncLetStart() { | ||
return lookupConcurrencyIntrinsic(getASTContext(), | ||
|
@@ -437,6 +440,37 @@ SILGenModule::getCheckExpectedExecutor() { | |
"_checkExpectedExecutor"); | ||
} | ||
|
||
FuncDecl *SILGenModule::getAsyncMainDrainQueue() { | ||
return lookupConcurrencyIntrinsic(getASTContext(), AsyncMainDrainQueue, | ||
"_asyncMainDrainQueue"); | ||
} | ||
|
||
FuncDecl *SILGenModule::getGetMainExecutor() { | ||
return lookupConcurrencyIntrinsic(getASTContext(), GetMainExecutor, | ||
"_getMainExecutor"); | ||
} | ||
|
||
FuncDecl *SILGenModule::getSwiftJobRun() { | ||
return lookupConcurrencyIntrinsic(getASTContext(), SwiftJobRun, | ||
"_swiftJobRun"); | ||
} | ||
|
||
FuncDecl *SILGenModule::getExit() { | ||
if (ExitFunc) | ||
return *ExitFunc; | ||
|
||
ASTContext &C = getASTContext(); | ||
ModuleDecl *concurrencyShims = | ||
C.getModuleByIdentifier(C.getIdentifier("_SwiftConcurrencyShims")); | ||
|
||
if (!concurrencyShims) { | ||
ExitFunc = nullptr; | ||
return nullptr; | ||
} | ||
|
||
return lookupIntrinsic(*concurrencyShims, ExitFunc, C.getIdentifier("exit")); | ||
} | ||
|
||
ProtocolConformance *SILGenModule::getNSErrorConformanceToError() { | ||
if (NSErrorConformanceToError) | ||
return *NSErrorConformanceToError; | ||
|
@@ -1036,6 +1070,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) { | |
postEmitFunction(constant, f); | ||
return; | ||
} | ||
case SILDeclRef::Kind::AsyncEntryPoint: | ||
case SILDeclRef::Kind::EntryPoint: { | ||
f->setBare(IsBare); | ||
|
||
|
@@ -1046,7 +1081,27 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) { | |
auto *decl = constant.getDecl(); | ||
auto *dc = decl->getDeclContext(); | ||
PrettyStackTraceSILFunction X("silgen emitArtificialTopLevel", f); | ||
SILGenFunction(*this, *f, dc).emitArtificialTopLevel(decl); | ||
// In all cases, a constant.kind == EntryPoint indicates the main entrypoint | ||
// to the program, @main. | ||
// In the synchronous case, the decl is not async, so emitArtificialTopLevel | ||
// emits the error unwrapping and call to MainType.$main() into @main. | ||
// | ||
// In the async case, emitAsyncMainThreadStart is responsible for generating | ||
// the contents of @main. This wraps @async_main in a task, passes that task | ||
// to swift_job_run to execute the first thunk, and starts the runloop to | ||
// run any additional continuations. The kind is EntryPoint, and the decl is | ||
// async. | ||
// When the kind is 'AsyncMain', we are generating @async_main. In this | ||
// case, emitArtificialTopLevel emits the code for calling MaintType.$main, | ||
// unwrapping errors, and calling exit(0) into @async_main to run the | ||
// user-specified main function. | ||
if (constant.kind == SILDeclRef::Kind::EntryPoint && isa<FuncDecl>(decl) && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's worth a comment here to describe the intent, e.g., that @main is initiating the asynchronous task on the main actor, and @async_Main is actually running the user's async main |
||
static_cast<FuncDecl *>(decl)->hasAsync()) { | ||
SILDeclRef mainEntryPoint = SILDeclRef::getAsyncMainDeclEntryPoint(decl); | ||
SILGenFunction(*this, *f, dc).emitAsyncMainThreadStart(mainEntryPoint); | ||
} else { | ||
SILGenFunction(*this, *f, dc).emitArtificialTopLevel(decl); | ||
} | ||
postEmitFunction(constant, f); | ||
return; | ||
} | ||
|
@@ -2029,10 +2084,15 @@ class SILGenModuleRAII { | |
|
||
// If the source file contains an artificial main, emit the implicit | ||
// top-level code. | ||
if (auto *mainDecl = sf->getMainDecl()) | ||
if (auto *mainDecl = sf->getMainDecl()) { | ||
if (isa<FuncDecl>(mainDecl) && | ||
static_cast<FuncDecl *>(mainDecl)->hasAsync()) | ||
emitSILFunctionDefinition( | ||
SILDeclRef::getAsyncMainDeclEntryPoint(mainDecl)); | ||
emitSILFunctionDefinition(SILDeclRef::getMainDeclEntryPoint(mainDecl)); | ||
} | ||
} | ||
|
||
void emitSILFunctionDefinition(SILDeclRef ref) { | ||
SGM.emitFunctionDefinition(ref, SGM.getFunction(ref, ForDefinition)); | ||
} | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes,
isFilenameAndLocation
verifies that both the storage kind is aFilenameAndLocationKind
and that it actually stores a location. While the source location is aFilenameAndLocationKind
, the location is null, so it still returns false.Then we crash in
getPrimaryASTNode()
because SourceLocations don't have a corresponding ASTNode.