@@ -93,19 +93,19 @@ class SILValueOwnershipChecker {
93
93
94
94
// / The list of lifetime ending users that we found. Only valid if check is
95
95
// / successful.
96
- SmallVector<BranchPropagatedUser , 16 > lifetimeEndingUsers;
96
+ SmallVector<Operand * , 16 > lifetimeEndingUsers;
97
97
98
98
// / The list of non lifetime ending users that we found. Only valid if check
99
99
// / is successful.
100
- SmallVector<BranchPropagatedUser , 16 > regularUsers;
100
+ SmallVector<Operand * , 16 > regularUsers;
101
101
102
102
// / The list of implicit non lifetime ending users that we found. This
103
103
// / consists of instructions like end_borrow that end a scoped lifetime. We
104
104
// / must treat those as regular uses and ensure that our value is not
105
105
// / destroyed while that sub-scope is valid.
106
106
// /
107
107
// / TODO: Rename to SubBorrowScopeUsers?
108
- SmallVector<BranchPropagatedUser , 4 > implicitRegularUsers;
108
+ SmallVector<Operand * , 4 > implicitRegularUsers;
109
109
110
110
// / The set of blocks that we have visited.
111
111
SmallPtrSetImpl<SILBasicBlock *> &visitedBlocks;
@@ -133,22 +133,25 @@ class SILValueOwnershipChecker {
133
133
if (!result.getValue ())
134
134
return false ;
135
135
136
+ SmallVector<BranchPropagatedUser, 32 > allLifetimeEndingUsers;
137
+ llvm::copy (lifetimeEndingUsers, std::back_inserter (allLifetimeEndingUsers));
136
138
SmallVector<BranchPropagatedUser, 32 > allRegularUsers;
137
139
llvm::copy (regularUsers, std::back_inserter (allRegularUsers));
138
140
llvm::copy (implicitRegularUsers, std::back_inserter (allRegularUsers));
141
+
139
142
LinearLifetimeChecker checker (visitedBlocks, deadEndBlocks);
140
143
auto linearLifetimeResult = checker.checkValue (
141
- value, lifetimeEndingUsers , allRegularUsers, errorBehavior);
144
+ value, allLifetimeEndingUsers , allRegularUsers, errorBehavior);
142
145
result = !linearLifetimeResult.getFoundError ();
143
146
144
147
return result.getValue ();
145
148
}
146
149
147
150
private:
148
151
bool checkUses ();
149
- bool gatherUsers (SmallVectorImpl<BranchPropagatedUser > &lifetimeEndingUsers,
150
- SmallVectorImpl<BranchPropagatedUser > ®ularUsers,
151
- SmallVectorImpl<BranchPropagatedUser > &implicitRegularUsers);
152
+ bool gatherUsers (SmallVectorImpl<Operand * > &lifetimeEndingUsers,
153
+ SmallVectorImpl<Operand * > ®ularUsers,
154
+ SmallVectorImpl<Operand * > &implicitRegularUsers);
152
155
153
156
bool checkValueWithoutLifetimeEndingUses ();
154
157
@@ -157,10 +160,10 @@ class SILValueOwnershipChecker {
157
160
158
161
bool isGuaranteedFunctionArgWithLifetimeEndingUses (
159
162
SILFunctionArgument *arg,
160
- const SmallVectorImpl<BranchPropagatedUser > &lifetimeEndingUsers) const ;
163
+ const SmallVectorImpl<Operand * > &lifetimeEndingUsers) const ;
161
164
bool isSubobjectProjectionWithLifetimeEndingUses (
162
165
SILValue value,
163
- const SmallVectorImpl<BranchPropagatedUser > &lifetimeEndingUsers) const ;
166
+ const SmallVectorImpl<Operand * > &lifetimeEndingUsers) const ;
164
167
165
168
// / Depending on our initialization, either return false or call Func and
166
169
// / throw an error.
@@ -181,9 +184,9 @@ class SILValueOwnershipChecker {
181
184
} // end anonymous namespace
182
185
183
186
bool SILValueOwnershipChecker::gatherUsers (
184
- SmallVectorImpl<BranchPropagatedUser > &lifetimeEndingUsers,
185
- SmallVectorImpl<BranchPropagatedUser > &nonLifetimeEndingUsers,
186
- SmallVectorImpl<BranchPropagatedUser > &implicitRegularUsers) {
187
+ SmallVectorImpl<Operand * > &lifetimeEndingUsers,
188
+ SmallVectorImpl<Operand * > &nonLifetimeEndingUsers,
189
+ SmallVectorImpl<Operand * > &implicitRegularUsers) {
187
190
188
191
// See if Value is guaranteed. If we are guaranteed and not forwarding, then
189
192
// we need to look through subobject uses for more uses. Otherwise, if we are
@@ -198,19 +201,7 @@ bool SILValueOwnershipChecker::gatherUsers(
198
201
199
202
// Then gather up our initial list of users.
200
203
SmallVector<Operand *, 8 > users;
201
- std::copy (value->use_begin (), value->use_end (), std::back_inserter (users));
202
-
203
- auto addCondBranchToList = [](SmallVectorImpl<BranchPropagatedUser> &list,
204
- CondBranchInst *cbi, unsigned operandIndex) {
205
- if (cbi->isConditionOperandIndex (operandIndex)) {
206
- list.emplace_back (cbi);
207
- return ;
208
- }
209
-
210
- bool isTrueOperand = cbi->isTrueOperandIndex (operandIndex);
211
- list.emplace_back (cbi, isTrueOperand ? CondBranchInst::TrueIdx
212
- : CondBranchInst::FalseIdx);
213
- };
204
+ llvm::copy (value->getUses (), std::back_inserter (users));
214
205
215
206
bool foundError = false ;
216
207
while (!users.empty ()) {
@@ -267,19 +258,10 @@ bool SILValueOwnershipChecker::gatherUsers(
267
258
opOwnershipKindMap.getLifetimeConstraint (ownershipKind);
268
259
if (lifetimeConstraint == UseLifetimeConstraint::MustBeInvalidated) {
269
260
LLVM_DEBUG (llvm::dbgs () << " Lifetime Ending User: " << *user);
270
- if (auto *cbi = dyn_cast<CondBranchInst>(user)) {
271
- addCondBranchToList (lifetimeEndingUsers, cbi, op->getOperandNumber ());
272
- } else {
273
- lifetimeEndingUsers.emplace_back (user);
274
- }
261
+ lifetimeEndingUsers.push_back (op);
275
262
} else {
276
263
LLVM_DEBUG (llvm::dbgs () << " Regular User: " << *user);
277
- if (auto *cbi = dyn_cast<CondBranchInst>(user)) {
278
- addCondBranchToList (nonLifetimeEndingUsers, cbi,
279
- op->getOperandNumber ());
280
- } else {
281
- nonLifetimeEndingUsers.emplace_back (user);
282
- }
264
+ nonLifetimeEndingUsers.push_back (op);
283
265
}
284
266
285
267
// If our base value is not guaranteed, we do not to try to visit
@@ -296,12 +278,14 @@ bool SILValueOwnershipChecker::gatherUsers(
296
278
// For correctness reasons we use indices to make sure that we can
297
279
// append to NonLifetimeEndingUsers without needing to deal with
298
280
// iterator invalidation.
299
- SmallVector<SILInstruction *, 4 > endBorrowInsts;
300
281
for (unsigned i : indices (nonLifetimeEndingUsers)) {
301
282
if (auto *bbi = dyn_cast<BeginBorrowInst>(
302
- nonLifetimeEndingUsers[i].getInst ())) {
303
- llvm::copy (bbi->getEndBorrows (),
304
- std::back_inserter (implicitRegularUsers));
283
+ nonLifetimeEndingUsers[i]->getUser ())) {
284
+ for (auto *use : bbi->getUses ()) {
285
+ if (isa<EndBorrowInst>(use->getUser ())) {
286
+ implicitRegularUsers.push_back (use);
287
+ }
288
+ }
305
289
}
306
290
}
307
291
}
@@ -381,8 +365,8 @@ bool SILValueOwnershipChecker::gatherUsers(
381
365
// them to ensure that all of BBArg's uses are completely
382
366
// enclosed within the end_borrow of this argument.
383
367
for (auto *op : succArg->getUses ()) {
384
- if (auto *ebi = dyn_cast <EndBorrowInst>(op->getUser ())) {
385
- implicitRegularUsers.push_back (ebi );
368
+ if (isa <EndBorrowInst>(op->getUser ())) {
369
+ implicitRegularUsers.push_back (op );
386
370
}
387
371
}
388
372
}
@@ -493,33 +477,31 @@ bool SILValueOwnershipChecker::checkValueWithoutLifetimeEndingUses() {
493
477
494
478
bool SILValueOwnershipChecker::isGuaranteedFunctionArgWithLifetimeEndingUses (
495
479
SILFunctionArgument *arg,
496
- const llvm::SmallVectorImpl<BranchPropagatedUser> &lifetimeEndingUsers)
497
- const {
480
+ const llvm::SmallVectorImpl<Operand *> &lifetimeEndingUsers) const {
498
481
if (arg->getOwnershipKind () != ValueOwnershipKind::Guaranteed)
499
482
return true ;
500
483
501
484
return handleError ([&] {
502
485
llvm::errs () << " Function: '" << arg->getFunction ()->getName () << " '\n "
503
486
<< " Guaranteed function parameter with life ending uses!\n "
504
487
<< " Value: " << *arg;
505
- for (const auto &user : lifetimeEndingUsers) {
506
- llvm::errs () << " Lifetime Ending User: " << *user ;
488
+ for (const auto *use : lifetimeEndingUsers) {
489
+ llvm::errs () << " Lifetime Ending User: " << *use-> getUser () ;
507
490
}
508
491
llvm::errs () << ' \n ' ;
509
492
});
510
493
}
511
494
512
495
bool SILValueOwnershipChecker::isSubobjectProjectionWithLifetimeEndingUses (
513
496
SILValue value,
514
- const llvm::SmallVectorImpl<BranchPropagatedUser> &lifetimeEndingUsers)
515
- const {
497
+ const llvm::SmallVectorImpl<Operand *> &lifetimeEndingUsers) const {
516
498
return handleError ([&] {
517
499
llvm::errs () << " Function: '" << value->getFunction ()->getName ()
518
500
<< " '\n "
519
501
<< " Subobject projection with life ending uses!\n "
520
502
<< " Value: " << *value;
521
- for (const auto &user : lifetimeEndingUsers) {
522
- llvm::errs () << " Lifetime Ending User: " << *user ;
503
+ for (const auto *use : lifetimeEndingUsers) {
504
+ llvm::errs () << " Lifetime Ending User: " << *use-> getUser () ;
523
505
}
524
506
llvm::errs () << ' \n ' ;
525
507
});
0 commit comments