Skip to content

Commit 6b28c2f

Browse files
committed
[SIL] Add flag to SILFunction to indicate async.
Includes boilerplate to parse and print as well as to serialize and deserialize.
1 parent b647245 commit 6b28c2f

File tree

12 files changed

+82
-24
lines changed

12 files changed

+82
-24
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ class SILFunction
274274
/// that it may have unboxed capture (i.e. @inout_aliasable parameters).
275275
unsigned IsWithoutActuallyEscapingThunk : 1;
276276

277+
/// True if this function is an async function.
278+
unsigned IsAsync : 1;
279+
277280
/// If != OptimizationMode::NotSet, the optimization mode specified with an
278281
/// function attribute.
279282
unsigned OptMode : NumOptimizationModeBits;
@@ -501,6 +504,10 @@ class SILFunction
501504
IsWithoutActuallyEscapingThunk = val;
502505
}
503506

507+
bool isAsync() const { return IsAsync; }
508+
509+
void setAsync(bool val = true) { IsAsync = val; }
510+
504511
/// Returns the calling convention used by this entry point.
505512
SILFunctionTypeRepresentation getRepresentation() const {
506513
return getLoweredFunctionType()->getRepresentation();

lib/SIL/IR/SILFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, StringRef Name,
107107
ExactSelfClass(isExactSelfClass),
108108
Inlined(false), Zombie(false), HasOwnership(true),
109109
WasDeserializedCanonical(false), IsWithoutActuallyEscapingThunk(false),
110-
OptMode(unsigned(OptimizationMode::NotSet)),
110+
IsAsync(false), OptMode(unsigned(OptimizationMode::NotSet)),
111111
EffectsKindAttr(unsigned(E)) {
112112
assert(!Transparent || !IsDynamicReplaceable);
113113
validateSubclassScope(classSubclassScope, isThunk, nullptr);

lib/SIL/IR/SILFunctionBuilder.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ SILFunction *SILFunctionBuilder::getOrCreateFunction(
217217
}
218218
addFunctionAttributes(F, decl->getAttrs(), mod, getOrCreateDeclaration,
219219
constant);
220+
221+
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(decl)) {
222+
F->setAsync(funcDecl->hasAsync());
223+
}
220224
}
221225

222226
return F;

lib/SIL/IR/SILPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2599,6 +2599,9 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
25992599
if (isWithoutActuallyEscapingThunk())
26002600
OS << "[without_actually_escaping] ";
26012601

2602+
if (isAsync())
2603+
OS << "[async] ";
2604+
26022605
switch (getSpecialPurpose()) {
26032606
case SILFunction::Purpose::None:
26042607
break;

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,7 @@ static bool parseDeclSILOptional(bool *isTransparent,
919919
bool *isWeakImported,
920920
AvailabilityContext *availability,
921921
bool *isWithoutActuallyEscapingThunk,
922+
bool *isAsync,
922923
SmallVectorImpl<std::string> *Semantics,
923924
SmallVectorImpl<ParsedSpecAttr> *SpecAttrs,
924925
ValueDecl **ClangDecl,
@@ -957,6 +958,8 @@ static bool parseDeclSILOptional(bool *isTransparent,
957958
else if (isWithoutActuallyEscapingThunk
958959
&& SP.P.Tok.getText() == "without_actually_escaping")
959960
*isWithoutActuallyEscapingThunk = true;
961+
else if (isAsync && SP.P.Tok.getText() == "async")
962+
*isAsync = true;
960963
else if (specialPurpose && SP.P.Tok.getText() == "global_init")
961964
*specialPurpose = SILFunction::Purpose::GlobalInit;
962965
else if (specialPurpose && SP.P.Tok.getText() == "lazy_getter")
@@ -5681,6 +5684,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
56815684
bool isWeakImported = false;
56825685
AvailabilityContext availability = AvailabilityContext::alwaysAvailable();
56835686
bool isWithoutActuallyEscapingThunk = false;
5687+
bool isAsync = false;
56845688
Inline_t inlineStrategy = InlineDefault;
56855689
OptimizationMode optimizationMode = OptimizationMode::NotSet;
56865690
SmallVector<std::string, 1> Semantics;
@@ -5695,8 +5699,8 @@ bool SILParserState::parseDeclSIL(Parser &P) {
56955699
&isThunk, &isDynamic, &isExactSelfClass, &DynamicallyReplacedFunction,
56965700
&objCReplacementFor, &specialPurpose, &inlineStrategy,
56975701
&optimizationMode, nullptr, &isWeakImported, &availability,
5698-
&isWithoutActuallyEscapingThunk, &Semantics,
5699-
&SpecAttrs, &ClangDecl, &MRK, FunctionState, M) ||
5702+
&isWithoutActuallyEscapingThunk, &isAsync, &Semantics, &SpecAttrs,
5703+
&ClangDecl, &MRK, FunctionState, M) ||
57005704
P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
57015705
P.parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
57025706
P.parseToken(tok::colon, diag::expected_sil_type))
@@ -5734,6 +5738,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
57345738
FunctionState.F->setAvailabilityForLinkage(availability);
57355739
FunctionState.F->setWithoutActuallyEscapingThunk(
57365740
isWithoutActuallyEscapingThunk);
5741+
FunctionState.F->setAsync(isAsync);
57375742
FunctionState.F->setInlineStrategy(inlineStrategy);
57385743
FunctionState.F->setOptimizationMode(optimizationMode);
57395744
FunctionState.F->setEffectsKind(MRK);
@@ -5919,10 +5924,9 @@ bool SILParserState::parseSILGlobal(Parser &P) {
59195924
SILParser State(P);
59205925
if (parseSILLinkage(GlobalLinkage, P) ||
59215926
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
5922-
nullptr, nullptr, nullptr, nullptr, nullptr,
5923-
nullptr, nullptr,
5924-
&isLet, nullptr, nullptr, nullptr, nullptr, nullptr,
5925-
nullptr, nullptr, State, M) ||
5927+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
5928+
nullptr, &isLet, nullptr, nullptr, nullptr, nullptr,
5929+
nullptr, nullptr, nullptr, nullptr, State, M) ||
59265930
P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
59275931
P.parseIdentifier(GlobalName, NameLoc, diag::expected_sil_value_name) ||
59285932
P.parseToken(tok::colon, diag::expected_sil_type))
@@ -5971,7 +5975,7 @@ bool SILParserState::parseSILProperty(Parser &P) {
59715975
if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr, nullptr,
59725976
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
59735977
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
5974-
nullptr, nullptr, nullptr, SP, M))
5978+
nullptr, nullptr, nullptr, nullptr, SP, M))
59755979
return true;
59765980

59775981
ValueDecl *VD;
@@ -6041,8 +6045,7 @@ bool SILParserState::parseSILVTable(Parser &P) {
60416045
if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr, nullptr,
60426046
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
60436047
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
6044-
nullptr, nullptr, nullptr,
6045-
VTableState, M))
6048+
nullptr, nullptr, nullptr, nullptr, VTableState, M))
60466049
return true;
60476050

60486051
// Parse the class name.
@@ -6578,8 +6581,7 @@ bool SILParserState::parseSILWitnessTable(Parser &P) {
65786581
if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
65796582
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
65806583
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
6581-
nullptr, nullptr, nullptr,
6582-
WitnessState, M))
6584+
nullptr, nullptr, nullptr, nullptr, WitnessState, M))
65836585
return true;
65846586

65856587
Scope S(&P, ScopeKind::TopLevel);

lib/Serialization/DeserializeSIL.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -511,14 +511,14 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn,
511511
IdentifierID replacedFunctionID;
512512
GenericSignatureID genericSigID;
513513
unsigned rawLinkage, isTransparent, isSerialized, isThunk,
514-
isWithoutactuallyEscapingThunk, specialPurpose, inlineStrategy,
514+
isWithoutactuallyEscapingThunk, isAsync, specialPurpose, inlineStrategy,
515515
optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership,
516516
isWeakImported, LIST_VER_TUPLE_PIECES(available),
517517
isDynamic, isExactSelfClass;
518518
ArrayRef<uint64_t> SemanticsIDs;
519519
SILFunctionLayout::readRecord(
520520
scratch, rawLinkage, isTransparent, isSerialized, isThunk,
521-
isWithoutactuallyEscapingThunk, specialPurpose, inlineStrategy,
521+
isWithoutactuallyEscapingThunk, isAsync, specialPurpose, inlineStrategy,
522522
optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership,
523523
isWeakImported, LIST_VER_TUPLE_PIECES(available),
524524
isDynamic, isExactSelfClass,
@@ -627,6 +627,11 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn,
627627
MF->fatal();
628628
}
629629

630+
if (fn->isAsync() != isAsync) {
631+
LLVM_DEBUG(llvm::dbgs() << "SILFunction type mismatch.\n");
632+
MF->fatal();
633+
}
634+
630635
} else {
631636
// Otherwise, create a new function.
632637
fn = builder.createDeclaration(name, ty, loc);
@@ -635,6 +640,7 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn,
635640
fn->setSerialized(IsSerialized_t(isSerialized));
636641
fn->setThunk(IsThunk_t(isThunk));
637642
fn->setWithoutActuallyEscapingThunk(bool(isWithoutactuallyEscapingThunk));
643+
fn->setAsync((bool)isAsync);
638644
fn->setInlineStrategy(Inline_t(inlineStrategy));
639645
fn->setSpecialPurpose(SILFunction::Purpose(specialPurpose));
640646
fn->setEffectsKind(EffectsKind(effect));
@@ -2824,14 +2830,14 @@ bool SILDeserializer::hasSILFunction(StringRef Name,
28242830
IdentifierID replacedFunctionID;
28252831
GenericSignatureID genericSigID;
28262832
unsigned rawLinkage, isTransparent, isSerialized, isThunk,
2827-
isWithoutactuallyEscapingThunk, isGlobal, inlineStrategy,
2833+
isWithoutactuallyEscapingThunk, isAsync, isGlobal, inlineStrategy,
28282834
optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership,
28292835
isWeakImported, LIST_VER_TUPLE_PIECES(available),
28302836
isDynamic, isExactSelfClass;
28312837
ArrayRef<uint64_t> SemanticsIDs;
28322838
SILFunctionLayout::readRecord(
28332839
scratch, rawLinkage, isTransparent, isSerialized, isThunk,
2834-
isWithoutactuallyEscapingThunk, isGlobal, inlineStrategy,
2840+
isWithoutactuallyEscapingThunk, isAsync, isGlobal, inlineStrategy,
28352841
optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership,
28362842
isWeakImported, LIST_VER_TUPLE_PIECES(available),
28372843
isDynamic, isExactSelfClass,

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t SWIFTMODULE_VERSION_MINOR = 566; // async
58+
const uint16_t SWIFTMODULE_VERSION_MINOR = 567; // async sil modifier
5959

6060
/// A standard hash seed used for all string hashes in a serialized module.
6161
///

lib/Serialization/SILFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ namespace sil_block {
278278
BCFixed<2>, // serialized
279279
BCFixed<2>, // thunks: signature optimized/reabstraction
280280
BCFixed<1>, // without_actually_escaping
281+
BCFixed<1>, // async
281282
BCFixed<3>, // specialPurpose
282283
BCFixed<2>, // inlineStrategy
283284
BCFixed<2>, // optimizationMode

lib/Serialization/SerializeSIL.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -434,13 +434,13 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
434434
Out, ScratchRecord, abbrCode, toStableSILLinkage(Linkage),
435435
(unsigned)F.isTransparent(), (unsigned)F.isSerialized(),
436436
(unsigned)F.isThunk(), (unsigned)F.isWithoutActuallyEscapingThunk(),
437-
(unsigned)F.getSpecialPurpose(), (unsigned)F.getInlineStrategy(),
438-
(unsigned)F.getOptimizationMode(), (unsigned)F.getEffectsKind(),
439-
(unsigned)numSpecAttrs, (unsigned)F.hasOwnership(),
440-
F.isAlwaysWeakImported(), LIST_VER_TUPLE_PIECES(available),
441-
(unsigned)F.isDynamicallyReplaceable(),
442-
(unsigned)F.isExactSelfClass(),
443-
FnID, replacedFunctionID, genericSigID, clangNodeOwnerID, SemanticsIDs);
437+
(unsigned)F.isAsync(), (unsigned)F.getSpecialPurpose(),
438+
(unsigned)F.getInlineStrategy(), (unsigned)F.getOptimizationMode(),
439+
(unsigned)F.getEffectsKind(), (unsigned)numSpecAttrs,
440+
(unsigned)F.hasOwnership(), F.isAlwaysWeakImported(),
441+
LIST_VER_TUPLE_PIECES(available), (unsigned)F.isDynamicallyReplaceable(),
442+
(unsigned)F.isExactSelfClass(), FnID, replacedFunctionID, genericSigID,
443+
clangNodeOwnerID, SemanticsIDs);
444444

445445
if (NoBody)
446446
return;

test/SIL/Parser/async.sil

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all=true %s | %target-sil-opt -enable-sil-verify-all=true | %FileCheck %s
2+
3+
// CHECK: sil [async] @async_test
4+
sil [async] @async_test : $() -> () {
5+
bb0:
6+
%0 = tuple ()
7+
return %0 : $()
8+
}

test/SIL/Serialization/basic.sil

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ bb0(%0 : @guaranteed $Builtin.NativeObject):
1515
return undef : $()
1616
}
1717

18+
// CHECK-LABEL: sil [async] @async_test
19+
sil [async] @async_test : $() -> () {
20+
bb0:
21+
%0 = tuple ()
22+
return %0 : $()
23+
}
24+
1825
// CHECK-LABEL: sil [serialized] [ossa] @test_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
1926
// CHECK: end_lifetime {{%.*}} : $Builtin.NativeObject
2027
sil [serialized] [ossa] @test_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {

test/SILGen/async.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-swift-frontend -emit-silgen -enable-experimental-concurrency -module-name Async -Xllvm -sil-full-demangle -parse-as-library %s | %FileCheck %s
2+
3+
import Swift
4+
5+
// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async04testA0yyYF : $@convention(thin) () -> () {
6+
func testAsync() async {}
7+
// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async11testAsyncp1SiyYF : $@convention(thin) () -> Int {
8+
func testAsyncp1() async -> Int { return 0 }
9+
10+
// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async5test2yyYKF : $@convention(thin) () -> @error Error {
11+
func test2() async throws {}
12+
// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async7test2p1SiyYKF : $@convention(thin) () -> (Int, @error Error) {
13+
func test2p1() async throws -> Int { return 0 }
14+
15+
// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async5test3yyyyKXEYKF : $@convention(thin) (@noescape @callee_guaranteed () -> @error Error) -> @error Error {
16+
func test3(_ cl: () throws -> ()) async rethrows {}
17+
// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async7test3p1yS2iyKXEYKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error) {
18+
func test3p1(_ cl: () throws -> Int) async rethrows -> Int { return try cl() }
19+
20+

0 commit comments

Comments
 (0)