Skip to content

Commit 5fcac08

Browse files
Merge pull request #40793 from nate-chandler/silgen/emit-borrow-scopes-for-alloc_boxes
[SIL] Added borrow scopes to alloc_boxes.
2 parents e1de391 + f19e413 commit 5fcac08

File tree

78 files changed

+736
-323
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+736
-323
lines changed

lib/SIL/IR/SILBuilder.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,10 @@ SILBuilder::emitDestroyAddr(SILLocation Loc, SILValue Operand) {
285285
if (isa<DeallocStackInst>(Inst))
286286
continue;
287287

288+
// end_borrow insts also don't affect take-ability
289+
if (isa<EndBorrowInst>(Inst))
290+
continue;
291+
288292
// An end_access of the same address may be able to be rewritten as a
289293
// [deinit] access.
290294
if (auto endAccess = dyn_cast<EndAccessInst>(Inst)) {

lib/SILGen/ResultPlan.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,13 @@ class IndirectOpenedSelfCleanup final : public Cleanup {
6666
void emit(SILGenFunction &SGF, CleanupLocation loc, ForUnwind_t forUnwind)
6767
override {
6868
assert(box && "buffer never emitted before activating cleanup?!");
69-
SGF.B.createDeallocBox(loc, box);
69+
auto theBox = box;
70+
if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) {
71+
auto *bbi = cast<BeginBorrowInst>(theBox);
72+
SGF.B.createEndBorrow(loc, bbi);
73+
theBox = bbi->getOperand();
74+
}
75+
SGF.B.createDeallocBox(loc, theBox);
7076
}
7177

7278
void dump(SILGenFunction &SGF) const override {
@@ -160,7 +166,10 @@ class IndirectOpenedSelfResultPlan final : public ResultPlan {
160166
SILBoxType::get(SGF.getASTContext(),
161167
boxLayout,
162168
layoutSubs));
163-
169+
if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) {
170+
resultBox = SGF.B.createBeginBorrow(loc, resultBox, /*isLexical=*/true);
171+
}
172+
164173
// Complete the cleanup to deallocate this buffer later, after we're
165174
// finished with the argument.
166175
static_cast<IndirectOpenedSelfCleanup&>(SGF.Cleanups.getCleanup(handle))

lib/SILGen/SILGenApply.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3505,7 +3505,13 @@ class DeallocateUninitializedBox : public Cleanup {
35053505
DeallocateUninitializedBox(SILValue box) : box(box) {}
35063506

35073507
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
3508-
SGF.B.createDeallocBox(l, box);
3508+
auto theBox = box;
3509+
if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) {
3510+
auto *bbi = cast<BeginBorrowInst>(theBox);
3511+
SGF.B.createEndBorrow(l, bbi);
3512+
theBox = bbi->getOperand();
3513+
}
3514+
SGF.B.createDeallocBox(l, theBox);
35093515
}
35103516

35113517
void dump(SILGenFunction &SGF) const override {

lib/SILGen/SILGenDecl.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,13 @@ class DeallocateUninitializedLocalVariable : public Cleanup {
297297

298298
void emit(SILGenFunction &SGF, CleanupLocation l,
299299
ForUnwind_t forUnwind) override {
300-
SGF.B.createDeallocBox(l, Box);
300+
auto box = Box;
301+
if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) {
302+
auto *bbi = cast<BeginBorrowInst>(box);
303+
SGF.B.createEndBorrow(l, bbi);
304+
box = bbi->getOperand();
305+
}
306+
SGF.B.createDeallocBox(l, box);
301307
}
302308

303309
void dump(SILGenFunction &) const override {
@@ -360,6 +366,10 @@ class LocalVariableInitialization : public SingleBufferInitialization {
360366
if (kind)
361367
Box = SGF.B.createMarkUninitialized(decl, Box, kind.getValue());
362368

369+
if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) {
370+
Box = SGF.B.createBeginBorrow(decl, Box, /*isLexical=*/true);
371+
}
372+
363373
Addr = SGF.B.createProjectBox(decl, Box, 0);
364374

365375
// Push a cleanup to destroy the local variable. This has to be
@@ -1751,7 +1761,15 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
17511761
// For a heap variable, the box is responsible for the value. We just need
17521762
// to give up our retain count on it.
17531763
if (loc.box) {
1754-
B.emitDestroyValueOperation(silLoc, loc.box);
1764+
if (!getASTContext().SILOpts.supportsLexicalLifetimes(getModule())) {
1765+
B.emitDestroyValueOperation(silLoc, loc.box);
1766+
return;
1767+
}
1768+
1769+
auto *bbi = cast<BeginBorrowInst>(loc.box);
1770+
B.createEndBorrow(silLoc, bbi);
1771+
B.emitDestroyValueOperation(silLoc, bbi->getOperand());
1772+
17551773
return;
17561774
}
17571775

lib/SILGen/Scope.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ static void lifetimeExtendAddressOnlyRValueSubValues(
5757
"addresses must be address only.");
5858
auto boxTy = SILBoxType::get(v->getType().getASTType());
5959
SILValue box = SGF.B.createAllocBox(loc, boxTy);
60+
if (SGF.getASTContext().SILOpts.supportsLexicalLifetimes(SGF.getModule())) {
61+
box = SGF.B.createBeginBorrow(loc, box, /*isLexical=*/true);
62+
}
6063
SILValue addr = SGF.B.createProjectBox(loc, box, 0);
6164
SGF.B.createCopyAddr(loc, v, addr, IsTake, IsInitialization);
6265

lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,11 @@ void SelectEnforcement::analyzeUsesOfBox(SingleValueInstruction *source) {
227227
for (auto use : source->getUses()) {
228228
auto user = use->getUser();
229229

230+
if (auto BBI = dyn_cast<BeginBorrowInst>(user)) {
231+
analyzeUsesOfBox(BBI);
232+
continue;
233+
}
234+
230235
if (auto MUI = dyn_cast<MarkUninitializedInst>(user)) {
231236
analyzeUsesOfBox(MUI);
232237
continue;
@@ -238,10 +243,9 @@ void SelectEnforcement::analyzeUsesOfBox(SingleValueInstruction *source) {
238243
}
239244

240245
// Ignore certain other uses that do not capture the value.
241-
if (isa<StrongRetainInst>(user) ||
242-
isa<StrongReleaseInst>(user) ||
243-
isa<DestroyValueInst>(user) ||
244-
isa<DeallocBoxInst>(user))
246+
if (isa<StrongRetainInst>(user) || isa<StrongReleaseInst>(user) ||
247+
isa<DestroyValueInst>(user) || isa<DeallocBoxInst>(user) ||
248+
isa<EndBorrowInst>(user))
245249
continue;
246250

247251
// Treat everything else as an escape.
@@ -667,6 +671,8 @@ void AccessEnforcementSelection::processFunction(SILFunction *F) {
667671
SourceAccess
668672
AccessEnforcementSelection::getAccessKindForBox(ProjectBoxInst *projection) {
669673
SILValue source = projection->getOperand();
674+
if (auto *BBI = dyn_cast<BeginBorrowInst>(source))
675+
source = BBI->getOperand();
670676
if (auto *MUI = dyn_cast<MarkUninitializedInst>(source))
671677
source = MUI->getOperand();
672678

lib/SILOptimizer/Mandatory/CapturePromotion.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,7 @@ class NonEscapingUserVisitor
10401040
ALWAYS_NON_ESCAPING_INST(Load)
10411041
ALWAYS_NON_ESCAPING_INST(StrongRelease)
10421042
ALWAYS_NON_ESCAPING_INST(DestroyValue)
1043+
ALWAYS_NON_ESCAPING_INST(EndBorrow)
10431044
#undef ALWAYS_NON_ESCAPING_INST
10441045

10451046
bool visitDeallocBoxInst(DeallocBoxInst *dbi) {
@@ -1213,7 +1214,8 @@ static bool findEscapeOrMutationUses(Operand *op,
12131214
// we want to be more conservative around non-top level copies (i.e. a copy
12141215
// derived from a projection like instruction). In fact such a thing may not
12151216
// even make any sense!
1216-
if (isa<CopyValueInst>(user) || isa<MarkUninitializedInst>(user)) {
1217+
if (isa<CopyValueInst>(user) || isa<MarkUninitializedInst>(user) ||
1218+
isa<BeginBorrowInst>(user)) {
12171219
bool foundSomeMutations = false;
12181220
for (auto *use : cast<SingleValueInstruction>(user)->getUses()) {
12191221
foundSomeMutations |= findEscapeOrMutationUses(use, state);

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ static void gatherDestroysOfContainer(const DIMemoryObjectInfo &memoryInfo,
5151
// TODO: This should really be tracked separately from other destroys so that
5252
// we distinguish the lifetime of the container from the value itself.
5353
assert(isa<ProjectBoxInst>(uninitMemory));
54-
auto *mui = cast<MarkUninitializedInst>(uninitMemory->getOperand(0));
54+
auto value = uninitMemory->getOperand(0);
55+
if (auto *bbi = dyn_cast<BeginBorrowInst>(value)) {
56+
value = bbi->getOperand();
57+
}
58+
auto *mui = cast<MarkUninitializedInst>(value);
5559
for (auto *user : mui->getUsersOfType<DestroyValueInst>()) {
5660
useInfo.trackDestroy(user);
5761
}
@@ -114,6 +118,12 @@ DIMemoryObjectInfo::DIMemoryObjectInfo(MarkUninitializedInst *MI)
114118
auto &Module = MI->getModule();
115119

116120
SILValue Address = MemoryInst;
121+
if (auto BBI = MemoryInst->getSingleUserOfType<BeginBorrowInst>()) {
122+
if (auto PBI = BBI->getSingleUserOfType<ProjectBoxInst>()) {
123+
IsBox = true;
124+
Address = PBI;
125+
}
126+
}
117127
if (auto PBI = MemoryInst->getSingleUserOfType<ProjectBoxInst>()) {
118128
IsBox = true;
119129
Address = PBI;

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,14 @@ class DIMemoryObjectInfo {
102102
/// with the memory info.
103103
SingleValueInstruction *getUninitializedValue() const {
104104
if (IsBox) {
105+
SILValue inst = MemoryInst;
106+
if (auto *bbi = MemoryInst->getSingleUserOfType<BeginBorrowInst>()) {
107+
inst = bbi;
108+
}
105109
// TODO: consider just storing the ProjectBoxInst in this case.
106-
auto *pbi = MemoryInst->getSingleUserOfType<ProjectBoxInst>();
107-
assert(pbi);
108-
return pbi;
110+
SingleValueInstruction *svi = inst->getSingleUserOfType<ProjectBoxInst>();
111+
assert(svi);
112+
return svi;
109113
}
110114
return MemoryInst;
111115
}

lib/SILOptimizer/Mandatory/DiagnoseInvalidEscapingCaptures.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,11 @@ const ParamDecl *getParamDeclFromOperand(SILValue value) {
157157

158158
bool isUseOfSelfInInitializer(Operand *oper) {
159159
if (auto *PBI = dyn_cast<ProjectBoxInst>(oper->get())) {
160-
if (auto *MUI = dyn_cast<MarkUninitializedInst>(PBI->getOperand())) {
160+
SILValue value = PBI->getOperand();
161+
if (auto *bbi = dyn_cast<BeginBorrowInst>(value)) {
162+
value = bbi->getOperand();
163+
}
164+
if (auto *MUI = dyn_cast<MarkUninitializedInst>(value)) {
161165
switch (MUI->getMarkUninitializedKind()) {
162166
case MarkUninitializedInst::Kind::Var:
163167
return false;

lib/SILOptimizer/Transforms/AllocBoxToStack.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ static bool getFinalReleases(SILValue Box,
172172

173173
// If we have a copy value or a mark_uninitialized, add its uses to the work
174174
// list and continue.
175-
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
175+
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User) ||
176+
isa<BeginBorrowInst>(User)) {
176177
llvm::copy(cast<SingleValueInstruction>(User)->getUses(),
177178
std::back_inserter(Worklist));
178179
continue;
@@ -385,12 +386,14 @@ static SILInstruction *recursivelyFindBoxOperandsPromotableToAddress(
385386
// Projections are fine as well.
386387
if (isa<StrongRetainInst>(User) || isa<StrongReleaseInst>(User) ||
387388
isa<ProjectBoxInst>(User) || isa<DestroyValueInst>(User) ||
388-
(!inAppliedFunction && isa<DeallocBoxInst>(User)))
389+
(!inAppliedFunction && isa<DeallocBoxInst>(User)) ||
390+
isa<EndBorrowInst>(User))
389391
continue;
390392

391393
// If our user instruction is a copy_value or a mark_uninitialized, visit
392394
// the users recursively.
393-
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
395+
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User) ||
396+
isa<BeginBorrowInst>(User)) {
394397
llvm::copy(cast<SingleValueInstruction>(User)->getUses(),
395398
std::back_inserter(Worklist));
396399
continue;
@@ -502,10 +505,12 @@ static void replaceProjectBoxUsers(SILValue HeapBox, SILValue StackBox) {
502505
continue;
503506
}
504507

505-
auto *CVI = dyn_cast<CopyValueInst>(Op->getUser());
506-
if (!CVI)
507-
continue;
508-
llvm::copy(CVI->getUses(), std::back_inserter(Worklist));
508+
auto *User = Op->getUser();
509+
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User) ||
510+
isa<BeginBorrowInst>(User)) {
511+
llvm::copy(cast<SingleValueInstruction>(User)->getUses(),
512+
std::back_inserter(Worklist));
513+
}
509514
}
510515
}
511516

@@ -578,8 +583,9 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
578583
while (!Worklist.empty()) {
579584
auto *User = Worklist.pop_back_val();
580585

581-
// Look through any mark_uninitialized, copy_values.
582-
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
586+
// Look through any mark_uninitialized, copy_values, begin_borrow.
587+
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User) ||
588+
isa<BeginBorrowInst>(User)) {
583589
auto Inst = cast<SingleValueInstruction>(User);
584590
llvm::transform(Inst->getUses(), std::back_inserter(Worklist),
585591
[](Operand *Op) -> SILInstruction * {
@@ -592,7 +598,7 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
592598

593599
assert(isa<StrongReleaseInst>(User) || isa<StrongRetainInst>(User) ||
594600
isa<DeallocBoxInst>(User) || isa<ProjectBoxInst>(User) ||
595-
isa<DestroyValueInst>(User));
601+
isa<DestroyValueInst>(User) || isa<EndBorrowInst>(User));
596602

597603
User->eraseFromParent();
598604
}
@@ -936,6 +942,7 @@ specializeApplySite(SILOptFunctionBuilder &FuncBuilder, ApplySite Apply,
936942
assert((isa<SingleValueInstruction>(Box) && isa<AllocBoxInst>(Box) ||
937943
isa<CopyValueInst>(Box) ||
938944
isa<MarkUninitializedInst>(Box) ||
945+
isa<BeginBorrowInst>(Box) ||
939946
isa<SILFunctionArgument>(Box)) &&
940947
"Expected either an alloc box or a copy of an alloc box or a "
941948
"function argument");

test/SILGen/access_marker_gen.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ public struct S {
1212
// CHECK: bb0(%0 : @guaranteed $Optional<AnyObject>):
1313
// CHECK: [[BOX:%.*]] = alloc_box ${ var S }, var, name "s"
1414
// CHECK: [[MARKED_BOX:%.*]] = mark_uninitialized [var] [[BOX]] : ${ var S }
15-
// CHECK: [[ADDR:%.*]] = project_box [[MARKED_BOX]] : ${ var S }, 0
15+
// CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[MARKED_BOX]]
16+
// CHECK: [[ADDR:%.*]] = project_box [[BOX_LIFETIME]] : ${ var S }, 0
1617
// CHECK: cond_br %{{.*}}, bb1, bb2
1718
// CHECK: bb1:
1819
// CHECK: [[ACCESS1:%.*]] = begin_access [modify] [unknown] [[ADDR]] : $*S
@@ -45,7 +46,8 @@ func takeS(_ s: S) {}
4546
// CHECK-LABEL: sil [ossa] @$s17access_marker_gen14modifyAndReadSyyF : $@convention(thin) () -> () {
4647
// CHECK: bb0:
4748
// CHECK: %[[BOX:.*]] = alloc_box ${ var S }, var, name "s"
48-
// CHECK: %[[ADDRS:.*]] = project_box %[[BOX]] : ${ var S }, 0
49+
// CHECK: %[[BOX_LIFETIME:[^,]+]] = begin_borrow [lexical] %[[BOX]]
50+
// CHECK: %[[ADDRS:.*]] = project_box %[[BOX_LIFETIME]] : ${ var S }, 0
4951
// CHECK: %[[ACCESS1:.*]] = begin_access [modify] [unknown] %[[ADDRS]] : $*S
5052
// CHECK: %[[ADDRI:.*]] = struct_element_addr %[[ACCESS1]] : $*S, #S.i
5153
// CHECK: assign %{{.*}} to %[[ADDRI]] : $*Int

test/SILGen/address_only_types.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ func address_only_assignment_from_lv(_ dest: inout Unloadable, v: Unloadable) {
166166
var v = v
167167
// CHECK: bb0([[DEST:%[0-9]+]] : $*Unloadable, [[VARG:%[0-9]+]] : $*Unloadable):
168168
// CHECK: [[VBOX:%.*]] = alloc_box ${ var Unloadable }
169-
// CHECK: [[PBOX:%[0-9]+]] = project_box [[VBOX]]
169+
// CHECK: [[V_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[VBOX]]
170+
// CHECK: [[PBOX:%[0-9]+]] = project_box [[V_LIFETIME]]
170171
// CHECK: copy_addr [[VARG]] to [initialization] [[PBOX]] : $*Unloadable
171172
dest = v
172173
// CHECK: [[READBOX:%.*]] = begin_access [read] [unknown] [[PBOX]] :
@@ -211,7 +212,8 @@ func address_only_var() -> Unloadable {
211212
// CHECK: bb0([[RET:%[0-9]+]] : $*Unloadable):
212213
var x = some_address_only_function_1()
213214
// CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Unloadable }
214-
// CHECK: [[XPB:%.*]] = project_box [[XBOX]]
215+
// CHECK: [[XBOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[XBOX]]
216+
// CHECK: [[XPB:%.*]] = project_box [[XBOX_LIFETIME]]
215217
// CHECK: apply {{%.*}}([[XPB]])
216218
return x
217219
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[XPB]] :

test/SILGen/auto_generated_super_init_call.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class SomeDerivedClass : Parent {
5050
// CHECK-NEXT: [[SELFAGAIN:%.*]] = unchecked_ref_cast [[PARENT]]
5151
// CHECK-NEXT: store [[SELFAGAIN]] to [init] [[SELF]]
5252
// CHECK-NEXT: [[SELFLOAD:%.*]] = load [copy] [[SELF]]
53+
// CHECK-NEXT: end_borrow
5354
// CHECK-NEXT: destroy_value
5455
// CHECK-NEXT: return [[SELFLOAD]]
5556
}

test/SILGen/borrow.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ func useD(_ d: D) {}
1818
// CHECK-LABEL: sil hidden [ossa] @$s6borrow44lvalueBorrowShouldBeAtEndOfFormalAccessScope{{.*}} : $@convention(thin) () -> () {
1919
// CHECK: bb0:
2020
// CHECK: [[BOX:%.*]] = alloc_box ${ var C }, var, name "c"
21-
// CHECK: [[PB_BOX:%.*]] = project_box [[BOX]]
21+
// CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[BOX]]
22+
// CHECK: [[PB_BOX:%.*]] = project_box [[BOX_LIFETIME]]
2223
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB_BOX]] : $*C
2324
// CHECK: [[CLASS:%.*]] = load [copy] [[ACCESS]]
2425
// CHECK: [[BORROWED_CLASS:%.*]] = begin_borrow [[CLASS]]
@@ -29,6 +30,7 @@ func useD(_ d: D) {}
2930
// CHECK: destroy_value [[CLASS]]
3031
// CHECK: [[FUNC:%.*]] = function_ref @$s6borrow4useD{{.*}} : $@convention(thin) (@guaranteed D) -> ()
3132
// CHECK: apply [[FUNC]]([[LOADED_VALUE]])
33+
// CHECK: end_borrow [[BOX_LIFETIME]]
3234
// CHECK: destroy_value [[BOX]]
3335
// CHECK: } // end sil function '$s6borrow44lvalueBorrowShouldBeAtEndOfFormalAccessScope{{.*}}'
3436
func lvalueBorrowShouldBeAtEndOfFormalAccessScope() {

test/SILGen/boxed_existentials.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ func test_property_of_lvalue(_ x: Error) -> String {
8282
// CHECK-LABEL: sil hidden [ossa] @$s18boxed_existentials23test_property_of_lvalueySSs5Error_pF :
8383
// CHECK: bb0([[ARG:%.*]] : @guaranteed $Error):
8484
// CHECK: [[VAR:%.*]] = alloc_box ${ var Error }
85-
// CHECK: [[PVAR:%.*]] = project_box [[VAR]]
85+
// CHECK: [[VAR_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[VAR]]
86+
// CHECK: [[PVAR:%.*]] = project_box [[VAR_LIFETIME]]
8687
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] : $Error
8788
// CHECK: store [[ARG_COPY]] to [init] [[PVAR]]
8889
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PVAR]] : $*Error
@@ -98,6 +99,7 @@ func test_property_of_lvalue(_ x: Error) -> String {
9899
// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<[[VALUE_TYPE]]>([[BORROW]])
99100
// CHECK: destroy_addr [[COPY]]
100101
// CHECK: dealloc_stack [[COPY]]
102+
// CHECK: end_borrow [[VAR_LIFETIME]]
101103
// CHECK: destroy_value [[VAR]]
102104
// CHECK-NOT: destroy_value [[ARG]]
103105
// CHECK: return [[RESULT]]
@@ -131,9 +133,11 @@ func test_open_existential_semantics(_ guaranteed: Error,
131133
_ immediate: Error) {
132134
var immediate = immediate
133135
// CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var Error }
134-
// CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_BOX]]
136+
// CHECK: [[IMMEDIATE_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[IMMEDIATE_BOX]]
137+
// CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_LIFETIME]]
135138
// GUARANTEED: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var Error }
136-
// GUARANTEED: [[PB:%.*]] = project_box [[IMMEDIATE_BOX]]
139+
// GUARANTEED: [[IMMEDIATE_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[IMMEDIATE_BOX]]
140+
// GUARANTEED: [[PB:%.*]] = project_box [[IMMEDIATE_LIFETIME]]
137141

138142
// CHECK-NOT: copy_value [[ARG0]]
139143
// CHECK: [[VALUE:%.*]] = open_existential_box [[ARG0]]
@@ -200,7 +204,8 @@ func test_open_existential_semantics(_ guaranteed: Error,
200204
func erasure_to_any(_ guaranteed: Error, _ immediate: Error) -> Any {
201205
var immediate = immediate
202206
// CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var Error }
203-
// CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_BOX]]
207+
// CHECK: [[IMMEDIATE_LIFETIME:%[^,]+]] = begin_borrow [lexical] [[IMMEDIATE_BOX]]
208+
// CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_LIFETIME]]
204209
if true {
205210
// CHECK-NOT: copy_value [[GUAR]]
206211
// CHECK: [[FROM_VALUE:%.*]] = open_existential_box [[GUAR:%.*]]

0 commit comments

Comments
 (0)