Skip to content

Commit 59a57ed

Browse files
committed
[ownership] Introduce a new BorrowScopeIntroducingOperand that is used to work with implicit uses of owned parameters implied by their use by a borrow scope introducing value.
For now this only is used for ensuring that an owned value that has a begin_borrow use, adds the end_borrows matched to the begin_borrow to the owned values implicit regular user list. I am going to use this same functionality to model the requirements around begin_apply and mark_dependence (when I add an end_mark_dependence instruction).
1 parent dd7d925 commit 59a57ed

File tree

3 files changed

+106
-40
lines changed

3 files changed

+106
-40
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 88 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,76 @@ bool isOwnershipForwardingInst(SILInstruction *i);
200200

201201
bool isGuaranteedForwardingInst(SILInstruction *i);
202202

203-
struct BorrowScopeIntroducerKind {
203+
struct BorrowScopeOperandKind {
204+
using UnderlyingKindTy = std::underlying_type<SILInstructionKind>::type;
205+
206+
enum Kind : UnderlyingKindTy {
207+
BeginBorrow = UnderlyingKindTy(SILInstructionKind::BeginBorrowInst),
208+
};
209+
210+
Kind value;
211+
212+
BorrowScopeOperandKind(Kind newValue) : value(newValue) {}
213+
BorrowScopeOperandKind(const BorrowScopeOperandKind &other)
214+
: value(other.value) {}
215+
operator Kind() const { return value; }
216+
217+
static Optional<BorrowScopeOperandKind> get(SILInstructionKind kind) {
218+
switch (kind) {
219+
default:
220+
return None;
221+
case SILInstructionKind::BeginBorrowInst:
222+
return BorrowScopeOperandKind(BeginBorrow);
223+
}
224+
}
225+
226+
void print(llvm::raw_ostream &os) const;
227+
LLVM_ATTRIBUTE_DEPRECATED(void dump() const, "only for use in the debugger");
228+
};
229+
230+
/// An operand whose user instruction introduces a new borrow scope for the
231+
/// operand's value. The value of the operand must be considered as implicitly
232+
/// borrowed until the user's corresponding end scope instruction.
233+
struct BorrowScopeOperand {
234+
BorrowScopeOperandKind kind;
235+
Operand *op;
236+
237+
BorrowScopeOperand(Operand *op)
238+
: kind(*BorrowScopeOperandKind::get(op->getUser()->getKind())), op(op) {}
239+
240+
/// If value is a borrow introducer return it after doing some checks.
241+
static Optional<BorrowScopeOperand> get(Operand *op) {
242+
auto *user = op->getUser();
243+
auto kind = BorrowScopeOperandKind::get(user->getKind());
244+
if (!kind)
245+
return None;
246+
return BorrowScopeOperand(*kind, op);
247+
}
248+
249+
void visitEndScopeInstructions(function_ref<void(Operand *)> func) const {
250+
switch (kind) {
251+
case BorrowScopeOperandKind::BeginBorrow:
252+
for (auto *use : cast<BeginBorrowInst>(op->getUser())->getUses()) {
253+
if (isa<EndBorrowInst>(use->getUser())) {
254+
func(use);
255+
}
256+
}
257+
return;
258+
}
259+
llvm_unreachable("Covered switch isn't covered");
260+
}
261+
262+
private:
263+
/// Internal constructor for failable static constructor. Please do not expand
264+
/// its usage since it assumes the code passed in is well formed.
265+
BorrowScopeOperand(BorrowScopeOperandKind kind, Operand *op)
266+
: kind(kind), op(op) {}
267+
};
268+
269+
llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
270+
BorrowScopeOperandKind kind);
271+
272+
struct BorrowScopeIntroducingValueKind {
204273
using UnderlyingKindTy = std::underlying_type<ValueKind>::type;
205274

206275
/// Enum we use for exhaustive pattern matching over borrow scope introducers.
@@ -210,23 +279,23 @@ struct BorrowScopeIntroducerKind {
210279
SILFunctionArgument = UnderlyingKindTy(ValueKind::SILFunctionArgument),
211280
};
212281

213-
static Optional<BorrowScopeIntroducerKind> get(ValueKind kind) {
282+
static Optional<BorrowScopeIntroducingValueKind> get(ValueKind kind) {
214283
switch (kind) {
215284
default:
216285
return None;
217286
case ValueKind::LoadBorrowInst:
218-
return BorrowScopeIntroducerKind(LoadBorrow);
287+
return BorrowScopeIntroducingValueKind(LoadBorrow);
219288
case ValueKind::BeginBorrowInst:
220-
return BorrowScopeIntroducerKind(BeginBorrow);
289+
return BorrowScopeIntroducingValueKind(BeginBorrow);
221290
case ValueKind::SILFunctionArgument:
222-
return BorrowScopeIntroducerKind(SILFunctionArgument);
291+
return BorrowScopeIntroducingValueKind(SILFunctionArgument);
223292
}
224293
}
225294

226295
Kind value;
227296

228-
BorrowScopeIntroducerKind(Kind newValue) : value(newValue) {}
229-
BorrowScopeIntroducerKind(const BorrowScopeIntroducerKind &other)
297+
BorrowScopeIntroducingValueKind(Kind newValue) : value(newValue) {}
298+
BorrowScopeIntroducingValueKind(const BorrowScopeIntroducingValueKind &other)
230299
: value(other.value) {}
231300
operator Kind() const { return value; }
232301

@@ -238,10 +307,10 @@ struct BorrowScopeIntroducerKind {
238307
/// of the scope.
239308
bool isLocalScope() const {
240309
switch (value) {
241-
case BorrowScopeIntroducerKind::BeginBorrow:
242-
case BorrowScopeIntroducerKind::LoadBorrow:
310+
case BorrowScopeIntroducingValueKind::BeginBorrow:
311+
case BorrowScopeIntroducingValueKind::LoadBorrow:
243312
return true;
244-
case BorrowScopeIntroducerKind::SILFunctionArgument:
313+
case BorrowScopeIntroducingValueKind::SILFunctionArgument:
245314
return false;
246315
}
247316
llvm_unreachable("Covered switch isnt covered?!");
@@ -252,7 +321,7 @@ struct BorrowScopeIntroducerKind {
252321
};
253322

254323
llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
255-
BorrowScopeIntroducerKind kind);
324+
BorrowScopeIntroducingValueKind kind);
256325

257326
/// A higher level construct for working with values that represent the
258327
/// introduction of a new borrow scope.
@@ -271,26 +340,26 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
271340
/// borrow introducers can not have guaranteed results that are not creating a
272341
/// new borrow scope. No such instructions exist today.
273342
struct BorrowScopeIntroducingValue {
274-
BorrowScopeIntroducerKind kind;
343+
BorrowScopeIntroducingValueKind kind;
275344
SILValue value;
276345

277346
BorrowScopeIntroducingValue(LoadBorrowInst *lbi)
278-
: kind(BorrowScopeIntroducerKind::LoadBorrow), value(lbi) {}
347+
: kind(BorrowScopeIntroducingValueKind::LoadBorrow), value(lbi) {}
279348
BorrowScopeIntroducingValue(BeginBorrowInst *bbi)
280-
: kind(BorrowScopeIntroducerKind::BeginBorrow), value(bbi) {}
349+
: kind(BorrowScopeIntroducingValueKind::BeginBorrow), value(bbi) {}
281350
BorrowScopeIntroducingValue(SILFunctionArgument *arg)
282-
: kind(BorrowScopeIntroducerKind::SILFunctionArgument), value(arg) {
351+
: kind(BorrowScopeIntroducingValueKind::SILFunctionArgument), value(arg) {
283352
assert(arg->getOwnershipKind() == ValueOwnershipKind::Guaranteed);
284353
}
285354

286355
BorrowScopeIntroducingValue(SILValue v)
287-
: kind(*BorrowScopeIntroducerKind::get(v->getKind())), value(v) {
356+
: kind(*BorrowScopeIntroducingValueKind::get(v->getKind())), value(v) {
288357
assert(v.getOwnershipKind() == ValueOwnershipKind::Guaranteed);
289358
}
290359

291360
/// If value is a borrow introducer return it after doing some checks.
292361
static Optional<BorrowScopeIntroducingValue> get(SILValue value) {
293-
auto kind = BorrowScopeIntroducerKind::get(value->getKind());
362+
auto kind = BorrowScopeIntroducingValueKind::get(value->getKind());
294363
if (!kind || value.getOwnershipKind() != ValueOwnershipKind::Guaranteed)
295364
return None;
296365
return BorrowScopeIntroducingValue(*kind, value);
@@ -334,7 +403,8 @@ struct BorrowScopeIntroducingValue {
334403
private:
335404
/// Internal constructor for failable static constructor. Please do not expand
336405
/// its usage since it assumes the code passed in is well formed.
337-
BorrowScopeIntroducingValue(BorrowScopeIntroducerKind kind, SILValue value)
406+
BorrowScopeIntroducingValue(BorrowScopeIntroducingValueKind kind,
407+
SILValue value)
338408
: kind(kind), value(value) {}
339409
};
340410

lib/SIL/OwnershipUtils.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,22 +81,22 @@ bool swift::isOwnershipForwardingInst(SILInstruction *i) {
8181
// Borrow Introducers
8282
//===----------------------------------------------------------------------===//
8383

84-
void BorrowScopeIntroducerKind::print(llvm::raw_ostream &os) const {
84+
void BorrowScopeIntroducingValueKind::print(llvm::raw_ostream &os) const {
8585
switch (value) {
86-
case BorrowScopeIntroducerKind::SILFunctionArgument:
86+
case BorrowScopeIntroducingValueKind::SILFunctionArgument:
8787
os << "SILFunctionArgument";
8888
return;
89-
case BorrowScopeIntroducerKind::BeginBorrow:
89+
case BorrowScopeIntroducingValueKind::BeginBorrow:
9090
os << "BeginBorrowInst";
9191
return;
92-
case BorrowScopeIntroducerKind::LoadBorrow:
92+
case BorrowScopeIntroducingValueKind::LoadBorrow:
9393
os << "LoadBorrowInst";
9494
return;
9595
}
9696
llvm_unreachable("Covered switch isn't covered?!");
9797
}
9898

99-
void BorrowScopeIntroducerKind::dump() const {
99+
void BorrowScopeIntroducingValueKind::dump() const {
100100
#ifndef NDEBUG
101101
print(llvm::dbgs());
102102
#endif
@@ -107,13 +107,13 @@ void BorrowScopeIntroducingValue::getLocalScopeEndingInstructions(
107107
assert(isLocalScope() && "Should only call this given a local scope");
108108

109109
switch (kind) {
110-
case BorrowScopeIntroducerKind::SILFunctionArgument:
110+
case BorrowScopeIntroducingValueKind::SILFunctionArgument:
111111
llvm_unreachable("Should only call this with a local scope");
112-
case BorrowScopeIntroducerKind::BeginBorrow:
112+
case BorrowScopeIntroducingValueKind::BeginBorrow:
113113
llvm::copy(cast<BeginBorrowInst>(value)->getEndBorrows(),
114114
std::back_inserter(scopeEndingInsts));
115115
return;
116-
case BorrowScopeIntroducerKind::LoadBorrow:
116+
case BorrowScopeIntroducingValueKind::LoadBorrow:
117117
llvm::copy(cast<LoadBorrowInst>(value)->getEndBorrows(),
118118
std::back_inserter(scopeEndingInsts));
119119
return;
@@ -125,17 +125,17 @@ void BorrowScopeIntroducingValue::visitLocalScopeEndingUses(
125125
function_ref<void(Operand *)> visitor) const {
126126
assert(isLocalScope() && "Should only call this given a local scope");
127127
switch (kind) {
128-
case BorrowScopeIntroducerKind::SILFunctionArgument:
128+
case BorrowScopeIntroducingValueKind::SILFunctionArgument:
129129
llvm_unreachable("Should only call this with a local scope");
130-
case BorrowScopeIntroducerKind::BeginBorrow:
131-
for (auto *use : cast<BeginBorrowInst>(value)->getUses()) {
130+
case BorrowScopeIntroducingValueKind::BeginBorrow:
131+
for (auto *use : value->getUses()) {
132132
if (isa<EndBorrowInst>(use->getUser())) {
133133
visitor(use);
134134
}
135135
}
136136
return;
137-
case BorrowScopeIntroducerKind::LoadBorrow:
138-
for (auto *use : cast<LoadBorrowInst>(value)->getUses()) {
137+
case BorrowScopeIntroducingValueKind::LoadBorrow:
138+
for (auto *use : value->getUses()) {
139139
if (isa<EndBorrowInst>(use->getUser())) {
140140
visitor(use);
141141
}
@@ -182,7 +182,7 @@ bool swift::getUnderlyingBorrowIntroducingValues(
182182
}
183183

184184
llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
185-
BorrowScopeIntroducerKind kind) {
185+
BorrowScopeIntroducingValueKind kind) {
186186
kind.print(os);
187187
return os;
188188
}

lib/SIL/SILOwnershipVerifier.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,10 @@ bool SILValueOwnershipChecker::gatherUsers(
278278
// For correctness reasons we use indices to make sure that we can
279279
// append to NonLifetimeEndingUsers without needing to deal with
280280
// iterator invalidation.
281-
for (unsigned i : indices(nonLifetimeEndingUsers)) {
282-
if (auto *bbi = dyn_cast<BeginBorrowInst>(
283-
nonLifetimeEndingUsers[i]->getUser())) {
284-
for (auto *use : bbi->getUses()) {
285-
if (isa<EndBorrowInst>(use->getUser())) {
286-
implicitRegularUsers.push_back(use);
287-
}
288-
}
281+
for (auto *op : nonLifetimeEndingUsers) {
282+
if (auto scopedOperand = BorrowScopeOperand::get(op)) {
283+
scopedOperand->visitEndScopeInstructions(
284+
[&](Operand *op) { implicitRegularUsers.push_back(op); });
289285
}
290286
}
291287
}

0 commit comments

Comments
 (0)