Skip to content

Commit 1aafbed

Browse files
Merge pull request #39050 from nate-chandler/lexical_lifetimes/borrow_scope_instruction_flag
[SIL] Added defined flag to begin_borrow.
2 parents 1f9fbed + f3b7706 commit 1aafbed

File tree

11 files changed

+91
-8
lines changed

11 files changed

+91
-8
lines changed

docs/SIL.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3652,7 +3652,7 @@ begin_borrow
36523652

36533653
::
36543654

3655-
sil-instruction ::= 'begin_borrow' sil-operand
3655+
sil-instruction ::= 'begin_borrow' '[defined]'? sil-operand
36563656

36573657
%1 = begin_borrow %0 : $T
36583658

@@ -3665,6 +3665,10 @@ region in between this borrow and its lifetime ending use, ``%0`` must be
36653665
live. This makes sense semantically since ``%1`` is modeling a new value with a
36663666
dependent lifetime on ``%0``.
36673667

3668+
The optional ``defined`` attribute specifies that the operand corresponds to a
3669+
local variable in the Swift source, so special care must be taken when moving
3670+
the end_borrow.
3671+
36683672
This instruction is only valid in functions in Ownership SSA form.
36693673

36703674
end_borrow

include/swift/SIL/SILBuilder.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -713,10 +713,11 @@ class SILBuilder {
713713
LoadBorrowInst(getSILDebugLocation(Loc), LV));
714714
}
715715

716-
BeginBorrowInst *createBeginBorrow(SILLocation Loc, SILValue LV) {
716+
BeginBorrowInst *createBeginBorrow(SILLocation Loc, SILValue LV,
717+
bool defined = false) {
717718
assert(!LV->getType().isAddress());
718719
return insert(new (getModule())
719-
BeginBorrowInst(getSILDebugLocation(Loc), LV));
720+
BeginBorrowInst(getSILDebugLocation(Loc), LV, defined));
720721
}
721722

722723
/// Convenience function for creating a load_borrow on non-trivial values and

include/swift/SIL/SILCloner.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,8 @@ void SILCloner<ImplClass>::visitBeginBorrowInst(BeginBorrowInst *Inst) {
10831083

10841084
recordClonedInstruction(
10851085
Inst, getBuilder().createBeginBorrow(getOpLocation(Inst->getLoc()),
1086-
getOpValue(Inst->getOperand())));
1086+
getOpValue(Inst->getOperand()),
1087+
Inst->isDefined()));
10871088
}
10881089

10891090
template <typename ImplClass>

include/swift/SIL/SILInstruction.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4027,14 +4027,21 @@ class BeginBorrowInst
40274027
SingleValueInstruction> {
40284028
friend class SILBuilder;
40294029

4030-
BeginBorrowInst(SILDebugLocation DebugLoc, SILValue LValue)
4030+
bool defined;
4031+
4032+
BeginBorrowInst(SILDebugLocation DebugLoc, SILValue LValue, bool defined)
40314033
: UnaryInstructionBase(DebugLoc, LValue,
4032-
LValue->getType().getObjectType()) {}
4034+
LValue->getType().getObjectType()),
4035+
defined(defined) {}
40334036

40344037
public:
40354038
using EndBorrowRange =
40364039
decltype(std::declval<ValueBase>().getUsersOfType<EndBorrowInst>());
40374040

4041+
/// Whether the borrow scope defined by this instruction corresponds to a
4042+
/// source-level VarDecl.
4043+
bool isDefined() const { return defined; }
4044+
40384045
/// Return a range over all EndBorrow instructions for this BeginBorrow.
40394046
EndBorrowRange getEndBorrows() const;
40404047

lib/SIL/IR/SILPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,9 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
14571457
}
14581458

14591459
void visitBeginBorrowInst(BeginBorrowInst *LBI) {
1460+
if (LBI->isDefined()) {
1461+
*this << "[defined] ";
1462+
}
14601463
*this << getIDAndType(LBI->getOperand());
14611464
}
14621465

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3278,11 +3278,21 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
32783278
case SILInstructionKind::BeginBorrowInst: {
32793279
SourceLoc AddrLoc;
32803280

3281+
bool defined = false;
3282+
StringRef attributeName;
3283+
3284+
if (parseSILOptional(attributeName, *this)) {
3285+
if (attributeName.equals("defined"))
3286+
defined = true;
3287+
else
3288+
return true;
3289+
}
3290+
32813291
if (parseTypedValueRef(Val, AddrLoc, B) ||
32823292
parseSILDebugLocation(InstLoc, B))
32833293
return true;
32843294

3285-
ResultVal = B.createBeginBorrow(InstLoc, Val);
3295+
ResultVal = B.createBeginBorrow(InstLoc, Val, defined);
32863296
break;
32873297
}
32883298

lib/Serialization/DeserializeSIL.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1852,7 +1852,6 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
18521852
UNARY_INSTRUCTION(EndLifetime)
18531853
UNARY_INSTRUCTION(CopyBlock)
18541854
UNARY_INSTRUCTION(LoadBorrow)
1855-
UNARY_INSTRUCTION(BeginBorrow)
18561855
REFCOUNTING_INSTRUCTION(StrongRetain)
18571856
REFCOUNTING_INSTRUCTION(StrongRelease)
18581857
UNARY_INSTRUCTION(IsUnique)
@@ -1862,6 +1861,17 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
18621861
#undef UNARY_INSTRUCTION
18631862
#undef REFCOUNTING_INSTRUCTION
18641863

1864+
case SILInstructionKind::BeginBorrowInst: {
1865+
assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");
1866+
unsigned defined = Attr;
1867+
ResultInst = Builder.createBeginBorrow(
1868+
Loc,
1869+
getLocalValue(ValID, getSILType(MF->getType(TyID),
1870+
(SILValueCategory)TyCategory, Fn)),
1871+
defined == 1);
1872+
break;
1873+
}
1874+
18651875
case SILInstructionKind::IsEscapingClosureInst: {
18661876
assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand.");
18671877
unsigned verificationType = Attr;

lib/Serialization/SerializeSIL.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,8 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
14121412
Attr = BCMI->isNative();
14131413
} else if (auto *ECMI = dyn_cast<EndCOWMutationInst>(&SI)) {
14141414
Attr = ECMI->doKeepUnique();
1415+
} else if (auto *BBI = dyn_cast<BeginBorrowInst>(&SI)) {
1416+
Attr = BBI->isDefined();
14151417
}
14161418
writeOneOperandLayout(SI.getKind(), Attr, SI.getOperand(0));
14171419
break;

test/SIL/Parser/borrow.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,17 @@ bb0(%0 : $*Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObject):
2727
%4 = tuple()
2828
return %4 : $()
2929
}
30+
31+
class C {}
32+
33+
// CHECK-LABEL: sil [ossa] @foo
34+
// CHECK: begin_borrow [defined] {{%[^,]+}}
35+
// CHECK-LABEL: } // end sil function 'foo'
36+
sil [ossa] @foo : $@convention(thin) () -> () {
37+
%instance = alloc_ref $C
38+
%guaranteed_c = begin_borrow [defined] %instance : $C
39+
end_borrow %guaranteed_c : $C
40+
destroy_value %instance : $C
41+
%res = tuple ()
42+
return %res : $()
43+
}

test/SIL/Serialization/borrow.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,17 @@ bb0(%0 : $*Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObject):
2929
%4 = tuple()
3030
return %4 : $()
3131
}
32+
33+
class C {}
34+
35+
// CHECK-LABEL: sil [ossa] @defined_borrow_test
36+
// CHECK: begin_borrow [defined] {{%[^,]+}}
37+
// CHECK-LABEL: } // end sil function 'defined_borrow_test'
38+
sil [ossa] @defined_borrow_test : $@convention(thin) () -> () {
39+
%instance = alloc_ref $C
40+
%guaranteed_c = begin_borrow [defined] %instance : $C
41+
end_borrow %guaranteed_c : $C
42+
destroy_value %instance : $C
43+
%res = tuple ()
44+
return %res : $()
45+
}

test/SIL/cloning.sil

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,20 @@ bb0:
2828
return %2 : $()
2929
}
3030

31+
sil [ossa] [always_inline] @callee_begin_borrow_defined : $@convention(thin) () -> () {
32+
%instance = alloc_ref $X
33+
%guaranteed_c = begin_borrow [defined] %instance : $X
34+
end_borrow %guaranteed_c : $X
35+
destroy_value %instance : $X
36+
%res = tuple ()
37+
return %res : $()
38+
}
39+
40+
// CHECK-LABEL: sil [ossa] @caller_begin_borrow_defined
41+
// CHECK: begin_borrow [defined]
42+
// CHECK-LABEL: } // end sil function 'caller_begin_borrow_defined'
43+
sil [ossa] @caller_begin_borrow_defined : $@convention(thin) () -> () {
44+
%callee_begin_borrow_defined = function_ref @callee_begin_borrow_defined : $@convention(thin) () -> ()
45+
%res = apply %callee_begin_borrow_defined() : $@convention(thin) () -> ()
46+
return %res : $()
47+
}

0 commit comments

Comments
 (0)