Skip to content

Commit e73396b

Browse files
committed
[sil] Add the ability to mark a function with isolation just so we can write more concurrency tests in SIL.
Specifically, we write a string out like: sil [isolation "$REPRESENTATION OF ISOLATION"] @function : $@convention(thin) ... The idea is that by using a string, we avoid parsing issues of the isolation and have flexibility. I left in the way we put isolation into the comment above functions so I did not break any tests that rely on it. I also made it so that we only accept this with sil tests that pass in the flag "sil-print-function-isolation-info". I am going to for the next release put in a full real implementation of this that allows for actor isolation to become a true first class citizen in SIL. But for now this at least lets us write tests in the short term. Since this is temporary and behind a flag, I did not add support for serialization since this is just for writing textual SIL tests. (cherry picked from commit ee3027c) Conflicts: lib/SIL/Parser/ParseSIL.cpp
1 parent 5ba72f2 commit e73396b

File tree

3 files changed

+93
-16
lines changed

3 files changed

+93
-16
lines changed

lib/SIL/IR/SILPrinter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ llvm::cl::opt<bool> SILPrintGenericSpecializationInfo(
9595
llvm::cl::desc("Include generic specialization"
9696
"information info in SIL output"));
9797

98+
llvm::cl::opt<bool> SILPrintFunctionIsolationInfo(
99+
"sil-print-function-isolation-info", llvm::cl::init(false),
100+
llvm::cl::desc("Print out isolation info on functions in a manner that SIL "
101+
"understands [e.x.: not in comments]"));
102+
98103
static std::string demangleSymbol(StringRef Name) {
99104
if (SILFullDemangle)
100105
return Demangle::demangleSymbolAsString(Name);
@@ -3627,6 +3632,15 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
36273632
OS << "[available " << availability.getVersionString() << "] ";
36283633
}
36293634

3635+
// This is here only for testing purposes.
3636+
if (SILPrintFunctionIsolationInfo) {
3637+
if (auto isolation = getActorIsolation()) {
3638+
OS << "[isolation \"";
3639+
isolation->printForSIL(OS);
3640+
OS << "\"] ";
3641+
}
3642+
}
3643+
36303644
switch (getInlineStrategy()) {
36313645
case NoInline: OS << "[noinline] "; break;
36323646
case AlwaysInline: OS << "[always_inline] "; break;

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,8 @@ static bool parseDeclSILOptional(
685685
AvailabilityRange *availability, bool *isWithoutActuallyEscapingThunk,
686686
SmallVectorImpl<std::string> *Semantics,
687687
SmallVectorImpl<ParsedSpecAttr> *SpecAttrs, ValueDecl **ClangDecl,
688-
EffectsKind *MRK, SILParser &SP, SILModule &M) {
688+
EffectsKind *MRK, ActorIsolation *actorIsolation, SILParser &SP,
689+
SILModule &M) {
689690
while (SP.P.consumeIf(tok::l_square)) {
690691
if (isLet && SP.P.Tok.is(tok::kw_let)) {
691692
*isLet = true;
@@ -784,7 +785,27 @@ static bool parseDeclSILOptional(
784785
*isPerformanceConstraint = true;
785786
else if (markedAsUsed && SP.P.Tok.getText() == "used")
786787
*markedAsUsed = true;
787-
else if (section && SP.P.Tok.getText() == "section") {
788+
else if (actorIsolation && SP.P.Tok.getText() == "isolation") {
789+
SP.P.consumeToken(tok::identifier);
790+
if (SP.P.Tok.getKind() != tok::string_literal) {
791+
SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
792+
return true;
793+
}
794+
StringRef rawString = SP.P.Tok.getText().drop_front().drop_back();
795+
// TODO: By using a raw string here, we can perhaps put in a simple string
796+
// representation of an actor that can be parsed back. For now this is
797+
// just a quick hack so we can write tests.
798+
auto optIsolation = ActorIsolation::forSILString(
799+
SP.P.Context.getIdentifier(rawString).str());
800+
if (!optIsolation) {
801+
SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
802+
return true;
803+
}
804+
*actorIsolation = *optIsolation;
805+
SP.P.consumeToken(tok::string_literal);
806+
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
807+
continue;
808+
} else if (section && SP.P.Tok.getText() == "section") {
788809
SP.P.consumeToken(tok::identifier);
789810
if (SP.P.Tok.getKind() != tok::string_literal) {
790811
SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
@@ -798,8 +819,7 @@ static bool parseDeclSILOptional(
798819

799820
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
800821
continue;
801-
}
802-
else if (inlineStrategy && SP.P.Tok.getText() == "always_inline")
822+
} else if (inlineStrategy && SP.P.Tok.getText() == "always_inline")
803823
*inlineStrategy = AlwaysInline;
804824
else if (MRK && SP.P.Tok.getText() == "readnone")
805825
*MRK = EffectsKind::ReadNone;
@@ -7333,6 +7353,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
73337353
SILFunction *DynamicallyReplacedFunction = nullptr;
73347354
SILFunction *AdHocWitnessFunction = nullptr;
73357355
Identifier objCReplacementFor;
7356+
ActorIsolation actorIsolation;
73367357
if (parseSILLinkage(FnLinkage, P) ||
73377358
parseDeclSILOptional(
73387359
&isTransparent, &isSerialized, &isCanonical, &hasOwnershipSSA,
@@ -7344,7 +7365,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
73447365
&optimizationMode, &perfConstr, &isPerformanceConstraint,
73457366
&markedAsUsed, &section, nullptr, &isWeakImported,
73467367
&needStackProtection, &availability, &isWithoutActuallyEscapingThunk,
7347-
&Semantics, &SpecAttrs, &ClangDecl, &MRK, FunctionState, M) ||
7368+
&Semantics, &SpecAttrs, &ClangDecl, &MRK, &actorIsolation, FunctionState, M) ||
73487369
P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
73497370
P.parseIdentifier(FnName, FnNameLoc, /*diagnoseDollarPrefix=*/false,
73507371
diag::expected_sil_function_name) ||
@@ -7404,6 +7425,8 @@ bool SILParserState::parseDeclSIL(Parser &P) {
74047425
for (auto &Attr : Semantics) {
74057426
FunctionState.F->addSemanticsAttr(Attr);
74067427
}
7428+
if (actorIsolation)
7429+
FunctionState.F->setActorIsolation(actorIsolation);
74077430
// Now that we have a SILFunction parse the body, if present.
74087431

74097432
bool isDefinition = false;
@@ -7593,11 +7616,11 @@ bool SILParserState::parseSILGlobal(Parser &P) {
75937616

75947617
SILParser State(P);
75957618
if (parseSILLinkage(GlobalLinkage, P) ||
7596-
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
7619+
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
75977620
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
75987621
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7622+
nullptr, nullptr, nullptr, nullptr, nullptr, &isLet,
75997623
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7600-
&isLet, nullptr, nullptr, nullptr, nullptr, nullptr,
76017624
nullptr, nullptr, nullptr, State, M) ||
76027625
P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
76037626
P.parseIdentifier(GlobalName, NameLoc, /*diagnoseDollarPrefix=*/false,
@@ -7651,7 +7674,7 @@ bool SILParserState::parseSILProperty(Parser &P) {
76517674
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
76527675
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
76537676
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7654-
nullptr, nullptr, SP, M))
7677+
nullptr, nullptr, nullptr, SP, M))
76557678
return true;
76567679

76577680
ValueDecl *VD;
@@ -7721,7 +7744,7 @@ bool SILParserState::parseSILVTable(Parser &P) {
77217744
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
77227745
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
77237746
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7724-
nullptr, nullptr, VTableState, M))
7747+
nullptr, nullptr, nullptr, VTableState, M))
77257748
return true;
77267749

77277750

@@ -7844,7 +7867,8 @@ bool SILParserState::parseSILMoveOnlyDeinit(Parser &parser) {
78447867
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
78457868
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
78467869
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7847-
nullptr, nullptr, moveOnlyDeinitTableState, M))
7870+
nullptr, nullptr, nullptr,
7871+
moveOnlyDeinitTableState, M))
78487872
return true;
78497873

78507874
// Parse the class name.
@@ -8373,12 +8397,12 @@ bool SILParserState::parseSILWitnessTable(Parser &P) {
83738397
parseSILLinkage(Linkage, P);
83748398

83758399
SerializedKind_t isSerialized = IsNotSerialized;
8376-
if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
8377-
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8378-
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8379-
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8380-
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8381-
nullptr, nullptr, WitnessState, M))
8400+
if (parseDeclSILOptional(
8401+
nullptr, &isSerialized, nullptr, nullptr, nullptr, nullptr, nullptr,
8402+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8403+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8404+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8405+
nullptr, nullptr, nullptr, nullptr, nullptr, WitnessState, M))
83828406
return true;
83838407

83848408
// Parse the protocol conformance.

test/SIL/Parser/actor_isolation.sil

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %target-sil-opt -sil-print-function-isolation-info -enable-objc-interop -enable-sil-verify-all=true %s | %target-sil-opt -sil-print-function-isolation-info -enable-objc-interop -enable-sil-verify-all=true | %FileCheck %s
2+
3+
// REQUIRES: asserts
4+
5+
// CHECK: // func_with_caller_isolation_inheriting
6+
// CHECK: // Isolation: caller_isolation_inheriting
7+
// CHECK: sil [isolation "caller_isolation_inheriting"] @func_with_caller_isolation_inheriting : $@convention(thin) () -> () {
8+
sil [isolation "caller_isolation_inheriting"] @func_with_caller_isolation_inheriting : $@convention(thin) () -> () {
9+
bb0:
10+
%0 = tuple ()
11+
return %0 : $()
12+
}
13+
14+
// CHECK: // func_with_global_actor_isolation
15+
// CHECK: // Isolation: global_actor. type: <null>
16+
// CHECK: sil [isolation "global_actor"] @func_with_global_actor_isolation : $@convention(thin) () -> () {
17+
sil [isolation "global_actor"] @func_with_global_actor_isolation : $@convention(thin) () -> () {
18+
bb0:
19+
%0 = tuple ()
20+
return %0 : $()
21+
}
22+
23+
// CHECK: // func_with_actor_instance_isolation
24+
// CHECK: // Isolation: actor_instance
25+
// CHECK: sil [isolation "actor_instance"] @func_with_actor_instance_isolation : $@convention(thin) () -> () {
26+
sil [isolation "actor_instance"] @func_with_actor_instance_isolation : $@convention(thin) () -> () {
27+
bb0:
28+
%0 = tuple ()
29+
return %0 : $()
30+
}
31+
32+
// CHECK: // func_with_nonisolated_isolation
33+
// CHECK: // Isolation: nonisolated
34+
// CHECK: sil [isolation "nonisolated"] @func_with_nonisolated_isolation : $@convention(thin) () -> () {
35+
sil [isolation "nonisolated"] @func_with_nonisolated_isolation : $@convention(thin) () -> () {
36+
bb0:
37+
%0 = tuple ()
38+
return %0 : $()
39+
}

0 commit comments

Comments
 (0)