Skip to content

Commit 93f6548

Browse files
committed
[Textual SIL] Explicit function arg lifetimes.
Print and parse @_eagerMove and @_lexical on function arguments.
1 parent 8074ce0 commit 93f6548

File tree

4 files changed

+102
-13
lines changed

4 files changed

+102
-13
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,9 @@ ERROR(silfunc_and_silarg_have_incompatible_sil_value_ownership,none,
517517
"SILFunction and SILArgument have mismatching ValueOwnershipKinds. "
518518
"Function type specifies: '@%0'. SIL argument specifies: '@%1'.",
519519
(StringRef, StringRef))
520+
ERROR(sil_arg_both_lexical_and_eagerMove,none,
521+
"Function argument is annotated both @_eagerMove and @_lexical, "
522+
"but these are incompatible alternatives", ())
520523
ERROR(expected_sil_colon,none,
521524
"expected ':' before %0", (StringRef))
522525
ERROR(expected_sil_tuple_index,none,

lib/SIL/IR/SILPrinter.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "swift/Demangling/Demangle.h"
2929
#include "swift/SIL/ApplySite.h"
3030
#include "swift/SIL/CFG.h"
31+
#include "swift/SIL/SILArgument.h"
3132
#include "swift/SIL/SILCoverageMap.h"
3233
#include "swift/SIL/SILDebugScope.h"
3334
#include "swift/SIL/SILDeclRef.h"
@@ -157,6 +158,7 @@ struct SILValuePrinterInfo {
157158
SILType Type;
158159
Optional<ValueOwnershipKind> OwnershipKind;
159160
bool IsNoImplicitCopy = false;
161+
LifetimeAnnotation Lifetime = LifetimeAnnotation::None;
160162

161163
SILValuePrinterInfo(ID ValueID) : ValueID(ValueID), Type(), OwnershipKind() {}
162164
SILValuePrinterInfo(ID ValueID, SILType Type)
@@ -165,12 +167,14 @@ struct SILValuePrinterInfo {
165167
ValueOwnershipKind OwnershipKind)
166168
: ValueID(ValueID), Type(Type), OwnershipKind(OwnershipKind) {}
167169
SILValuePrinterInfo(ID ValueID, SILType Type,
168-
ValueOwnershipKind OwnershipKind, bool IsNoImplicitCopy)
170+
ValueOwnershipKind OwnershipKind, bool IsNoImplicitCopy,
171+
LifetimeAnnotation Lifetime)
169172
: ValueID(ValueID), Type(Type), OwnershipKind(OwnershipKind),
170-
IsNoImplicitCopy(IsNoImplicitCopy) {}
171-
SILValuePrinterInfo(ID ValueID, SILType Type, bool IsNoImplicitCopy)
173+
IsNoImplicitCopy(IsNoImplicitCopy), Lifetime(Lifetime) {}
174+
SILValuePrinterInfo(ID ValueID, SILType Type, bool IsNoImplicitCopy,
175+
LifetimeAnnotation Lifetime)
172176
: ValueID(ValueID), Type(Type), OwnershipKind(),
173-
IsNoImplicitCopy(IsNoImplicitCopy) {}
177+
IsNoImplicitCopy(IsNoImplicitCopy), Lifetime(Lifetime) {}
174178
};
175179

176180
/// Return the fully qualified dotted path for DeclContext.
@@ -639,6 +643,16 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
639643
*this << " : ";
640644
if (i.IsNoImplicitCopy)
641645
*this << "@noImplicitCopy ";
646+
switch (i.Lifetime) {
647+
case LifetimeAnnotation::EagerMove:
648+
*this << "@_eagerMove ";
649+
break;
650+
case LifetimeAnnotation::None:
651+
break;
652+
case LifetimeAnnotation::Lexical:
653+
*this << "@_lexical ";
654+
break;
655+
}
642656
if (i.OwnershipKind && *i.OwnershipKind != OwnershipKind::None) {
643657
*this << "@" << i.OwnershipKind.getValue() << " ";
644658
}
@@ -672,14 +686,15 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
672686
return {Ctx.getID(V), V ? V->getType() : SILType()};
673687
}
674688
SILValuePrinterInfo getIDAndType(SILFunctionArgument *arg) {
675-
return {Ctx.getID(arg), arg->getType(), arg->isNoImplicitCopy()};
689+
return {Ctx.getID(arg), arg->getType(), arg->isNoImplicitCopy(),
690+
arg->getLifetimeAnnotation()};
676691
}
677692
SILValuePrinterInfo getIDAndTypeAndOwnership(SILValue V) {
678693
return {Ctx.getID(V), V ? V->getType() : SILType(), V->getOwnershipKind()};
679694
}
680695
SILValuePrinterInfo getIDAndTypeAndOwnership(SILFunctionArgument *arg) {
681696
return {Ctx.getID(arg), arg->getType(), arg->getOwnershipKind(),
682-
arg->isNoImplicitCopy()};
697+
arg->isNoImplicitCopy(), arg->getLifetimeAnnotation()};
683698
}
684699

685700
//===--------------------------------------------------------------------===//

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -310,19 +310,19 @@ namespace swift {
310310
return parseASTType(result, genericSig, genericParams);
311311
}
312312

313-
bool parseIsNoImplicitCopy() {
313+
Optional<StringRef> parseOptionalAttribute(ArrayRef<StringRef> expected) {
314314
// We parse here @ <identifier>.
315315
if (P.Tok.getKind() != tok::at_sign)
316-
return false;
316+
return llvm::None;
317317

318-
// Make sure our text is no implicit copy.
319-
if (P.peekToken().getText() != "noImplicitCopy")
320-
return false;
318+
auto name = P.peekToken().getText();
319+
if (!is_contained(expected, name))
320+
return llvm::None;
321321

322322
// Ok, we can do this.
323323
P.consumeToken(tok::at_sign);
324324
P.consumeToken(tok::identifier);
325-
return true;
325+
return name;
326326
}
327327

328328
bool parseSILOwnership(ValueOwnershipKind &OwnershipKind) {
@@ -6369,7 +6369,31 @@ bool SILParser::parseSILBasicBlock(SILBuilder &B) {
63696369
P.parseToken(tok::colon, diag::expected_sil_colon_value_ref))
63706370
return true;
63716371

6372-
bool foundNoImplicitCopy = parseIsNoImplicitCopy();
6372+
bool foundNoImplicitCopy = false;
6373+
bool foundLexical = false;
6374+
bool foundEagerMove = false;
6375+
while (auto attributeName = parseOptionalAttribute(
6376+
{"noImplicitCopy", "_lexical", "_eagerMove"})) {
6377+
if (*attributeName == "noImplicitCopy")
6378+
foundNoImplicitCopy = true;
6379+
else if (*attributeName == "_lexical")
6380+
foundLexical = true;
6381+
else if (*attributeName == "_eagerMove")
6382+
foundEagerMove = true;
6383+
else {
6384+
llvm_unreachable("Unexpected attribute!");
6385+
}
6386+
}
6387+
6388+
LifetimeAnnotation lifetime = LifetimeAnnotation::None;
6389+
if (foundEagerMove && foundLexical) {
6390+
P.diagnose(NameLoc, diag::sil_arg_both_lexical_and_eagerMove);
6391+
return true;
6392+
} else if (foundEagerMove) {
6393+
lifetime = LifetimeAnnotation::EagerMove;
6394+
} else if (foundLexical) {
6395+
lifetime = LifetimeAnnotation::Lexical;
6396+
}
63736397

63746398
// If SILOwnership is enabled and we are not assuming that we are
63756399
// parsing unqualified SIL, look for printed value ownership kinds.
@@ -6384,6 +6408,7 @@ bool SILParser::parseSILBasicBlock(SILBuilder &B) {
63846408
if (IsEntry) {
63856409
auto *fArg = BB->createFunctionArgument(Ty);
63866410
fArg->setNoImplicitCopy(foundNoImplicitCopy);
6411+
fArg->setLifetimeAnnotation(lifetime);
63876412
Arg = fArg;
63886413

63896414
// Today, we construct the ownership kind straight from the function
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %target-sil-opt -enable-objc-interop -enable-lexical-lifetimes=true -enable-sil-verify-all=true %s | %target-sil-opt -enable-objc-interop -enable-lexical-lifetimes=true -enable-sil-verify-all=true | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
class C {}
6+
7+
// CHECK-LABEL: sil [ossa] @one_arg_eager_move : {{.*}} {
8+
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove @owned $C):
9+
// CHECK-LABEL: } // end sil function 'one_arg_eager_move'
10+
sil [ossa] @one_arg_eager_move : $@convention(thin) (@owned C) -> () {
11+
bb0(%instance : @_eagerMove @owned $C):
12+
destroy_value %instance : $C
13+
%retval = tuple()
14+
return %retval : $()
15+
}
16+
17+
// CHECK-LABEL: sil [ossa] @one_arg_eager_move_and_no_implicit_copy : {{.*}} {
18+
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @noImplicitCopy @_eagerMove @owned $C):
19+
// CHECK-LABEL: } // end sil function 'one_arg_eager_move_and_no_implicit_copy'
20+
sil [ossa] @one_arg_eager_move_and_no_implicit_copy : $(@owned C) -> () {
21+
bb0(%instance : @noImplicitCopy @_eagerMove @owned $C):
22+
destroy_value %instance : $C
23+
%retval = tuple()
24+
return %retval : $()
25+
}
26+
27+
// CHECK-LABEL: sil [ossa] @one_arg_lexical : {{.*}} {
28+
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_lexical @owned $C):
29+
// CHECK-LABEL: } // end sil function 'one_arg_lexical'
30+
sil [ossa] @one_arg_lexical : $@convention(thin) (@owned C) -> () {
31+
bb0(%instance : @_lexical @owned $C):
32+
destroy_value %instance : $C
33+
%retval = tuple()
34+
return %retval : $()
35+
}
36+
37+
// CHECK-LABEL: sil [ossa] @one_arg_lexical_and_no_implicit_copy : {{.*}} {
38+
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @noImplicitCopy @_lexical @owned $C):
39+
// CHECK-LABEL: } // end sil function 'one_arg_lexical_and_no_implicit_copy'
40+
sil [ossa] @one_arg_lexical_and_no_implicit_copy : $@convention(thin) (@owned C) -> () {
41+
bb0(%instance : @noImplicitCopy @_lexical @owned $C):
42+
destroy_value %instance : $C
43+
%retval = tuple()
44+
return %retval : $()
45+
}
46+

0 commit comments

Comments
 (0)