Skip to content

Commit 14a0bff

Browse files
committed
Fix AllocBoxToStack to handle mark_dependence[_addr]
Handle the easy case in which the promoted box is the base operand of a mark_dep. This requires nothing more than setting the base operand to the new stack address. Required for move-only checking. Otherwise, we get an incredibly bizarre compiler error: noncopyable 'foo' cannot be consumed when captured by an escaping closure Fixes rdar://150398673 ([nonescapable] allocbox-to-stack fails causing lifetime diagnostics to fail)
1 parent 5528cf1 commit 14a0bff

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8964,6 +8964,21 @@ class MarkDependenceInstruction {
89648964
return SILValue();
89658965
}
89668966

8967+
void setBase(SILValue newVal) {
8968+
if (inst) {
8969+
switch (inst->getKind()) {
8970+
case SILInstructionKind::MarkDependenceInst:
8971+
cast<MarkDependenceInst>(inst)->setBase(newVal);
8972+
break;
8973+
case SILInstructionKind::MarkDependenceAddrInst:
8974+
cast<MarkDependenceAddrInst>(inst)->setBase(newVal);
8975+
break;
8976+
default:
8977+
break;
8978+
}
8979+
}
8980+
}
8981+
89678982
SILValue getDependent() const {
89688983
if (inst) {
89698984
switch (inst->getKind()) {

lib/SILOptimizer/Transforms/AllocBoxToStack.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,13 @@ static SILInstruction *recursivelyFindBoxOperandsPromotableToAddress(
400400
isa<EndBorrowInst>(User))
401401
continue;
402402

403+
// mark_dependence base value uses will be directly converted to base
404+
// address uses.
405+
if (auto mdi = MarkDependenceInstruction(User)) {
406+
if (Op->get() == mdi.getBase())
407+
continue;
408+
}
409+
403410
// If our user instruction is a copy_value or a mark_uninitialized, visit
404411
// the users recursively.
405412
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User) ||
@@ -738,6 +745,12 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
738745
Inst->eraseFromParent();
739746
continue;
740747
}
748+
// mark_dependence base value uses will be directly converted to base
749+
// address uses.
750+
if (auto mdi = MarkDependenceInstruction(User)) {
751+
mdi.setBase(StackBox);
752+
continue;
753+
}
741754

742755
assert(isa<StrongReleaseInst>(User) || isa<StrongRetainInst>(User) ||
743756
isa<DeallocBoxInst>(User) || isa<ProjectBoxInst>(User) ||
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// RUN: %target-sil-opt -enable-experimental-feature LifetimeDependence -allocbox-to-stack %s | %FileCheck %s
2+
3+
// REQUIRES: swift_feature_LifetimeDependence
4+
5+
import Swift
6+
import Builtin
7+
8+
public struct View : ~Escapable {
9+
let _ptr: UnsafeRawPointer
10+
}
11+
12+
sil [ossa] @initFn : $@convention(method) (UnsafeRawPointer, @thin View.Type) -> @lifetime(borrow 0) @owned View
13+
sil [ossa] @initFnAddr : $@convention(thin) (UnsafeRawPointer, @thin View.Type) -> @lifetime(borrow 0) @out View
14+
15+
// CHECK-LABEL: sil [ossa] @testBoxedParam :
16+
// CHECK-NOT: alloc_box
17+
// CHECK-LABEL: } // end sil function 'testBoxedParam'
18+
sil [ossa] @testBoxedParam : $@convention(thin) (@owned View) -> @lifetime(copy 0) @owned View {
19+
bb0(%0 : @noImplicitCopy @_eagerMove @owned $View):
20+
%1 = alloc_box ${ var @moveOnly View }, var, name "that"
21+
%2 = begin_borrow [var_decl] %1
22+
%3 = project_box %2, 0
23+
%4 = moveonlywrapper_to_copyable_addr %3
24+
store %0 to [init] %4
25+
%6 = metatype $@thin View.Type
26+
%7 = begin_access [read] [static] %3
27+
%8 = mark_unresolved_non_copyable_value [no_consume_or_assign] %7
28+
%9 = struct_element_addr %8, #View._ptr
29+
%10 = load_borrow %9
30+
%11 = moveonlywrapper_to_copyable [guaranteed] %10
31+
end_borrow %10
32+
end_access %7
33+
%14 = function_ref @initFn : $@convention(method) (UnsafeRawPointer, @thin View.Type) -> @lifetime(borrow 0) @owned View
34+
%15 = apply %14(%11, %6) : $@convention(method) (UnsafeRawPointer, @thin View.Type) -> @lifetime(borrow 0) @owned View
35+
%16 = mark_dependence [unresolved] %15 on %2
36+
end_borrow %2
37+
destroy_value %1
38+
return %16
39+
}
40+
41+
// CHECK-LABEL: sil [ossa] @testBoxedParamAddr :
42+
// CHECK-NOT: alloc_box
43+
// CHECK-LABEL: } // end sil function 'testBoxedParamAddr'
44+
sil [ossa] @testBoxedParamAddr : $@convention(thin) (@owned View) -> () {
45+
bb0(%0 : @noImplicitCopy @_eagerMove @owned $View):
46+
%1 = alloc_box ${ var @moveOnly View }, var, name "that"
47+
%2 = begin_borrow [var_decl] %1
48+
%3 = project_box %2, 0
49+
%4 = moveonlywrapper_to_copyable_addr %3
50+
store %0 to [init] %4
51+
%6 = metatype $@thin View.Type
52+
%7 = begin_access [read] [static] %3
53+
%8 = mark_unresolved_non_copyable_value [no_consume_or_assign] %7
54+
%9 = struct_element_addr %8, #View._ptr
55+
%10 = load_borrow %9
56+
%11 = moveonlywrapper_to_copyable [guaranteed] %10
57+
end_borrow %10
58+
end_access %7
59+
%14 = alloc_stack $View
60+
%15 = function_ref @initFnAddr : $@convention(thin) (UnsafeRawPointer, @thin View.Type) -> @lifetime(borrow 0) @out View
61+
%16 = apply %15(%14, %11, %6) : $@convention(thin) (UnsafeRawPointer, @thin View.Type) -> @lifetime(borrow 0) @out View
62+
mark_dependence_addr [unresolved] %14 on %2
63+
dealloc_stack %14
64+
end_borrow %2
65+
destroy_value %1
66+
%99 = tuple ()
67+
return %99
68+
}

0 commit comments

Comments
 (0)