Skip to content

Commit 91a23de

Browse files
authored
Merge pull request swiftlang#58508 from gottesmm/pr-fa9ad2bd442ef675706f04dfe85e40f894aacd00
[move-function-addr] When inserting compensating destroy_addr, insert debug_value undef before the destroy_addr.
2 parents 936a4e0 + 107bb16 commit 91a23de

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

lib/SILOptimizer/Mandatory/MoveKillsCopyableAddressesChecker.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,10 @@ bool GatherLexicalLifetimeUseVisitor::visitUse(Operand *op,
13631363
if (isa<DeallocStackInst>(op->getUser()))
13641364
return true;
13651365

1366+
// Ignore end_access.
1367+
if (isa<EndAccessInst>(op->getUser()))
1368+
return true;
1369+
13661370
LLVM_DEBUG(llvm::dbgs() << "Found liveness use: " << *op->getUser());
13671371
useState.livenessUses.insert(op->getUser());
13681372

@@ -1507,6 +1511,24 @@ bool DataflowState::cleanupAllDestroyAddr(
15071511
SILBuilderWithScope builder(iter);
15081512
auto *dvi = builder.createDestroyAddr(
15091513
RegularLocation::getAutoGeneratedLocation(), address);
1514+
// Create a debug_value undef if we have debug info to stop the async dbg
1515+
// info propagation from creating debug info for an already destroyed
1516+
// value. We use a separate builder since we need to control the debug
1517+
// scope/location to get llvm to do the right thing.
1518+
if (addressDebugInst) {
1519+
if (auto varInfo = addressDebugInst.getVarInfo()) {
1520+
// We need to always insert /after/ the reinit since the value will
1521+
// not be defined before the value.
1522+
SILBuilderWithScope dbgValueInsertBuilder(dvi);
1523+
dbgValueInsertBuilder.setCurrentDebugScope(
1524+
addressDebugInst->getDebugScope());
1525+
dbgValueInsertBuilder.createDebugValue(
1526+
addressDebugInst.inst->getLoc(),
1527+
SILUndef::get(address->getType(), dvi->getModule()), *varInfo,
1528+
false,
1529+
/*was moved*/ true);
1530+
}
1531+
}
15101532
useState.destroys.insert(dvi);
15111533
continue;
15121534
}

test/SILOptimizer/move_function_kills_addresses_dbginfo.sil

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,28 @@
55
sil_stage raw
66

77
import Builtin
8+
import Swift
9+
10+
//////////////////
11+
// Declarations //
12+
//////////////////
13+
14+
public protocol P {
15+
static var value: P { get }
16+
func doSomething()
17+
}
18+
19+
sil @forceSplit : $@convention(thin) @async () -> ()
20+
sil @genericUse : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
21+
22+
enum Optional<T> {
23+
case some(T)
24+
case none
25+
}
26+
27+
///////////
28+
// Tests //
29+
///////////
830

931
// Make sure that when we process a move_addr on an alloc_stack/debug_value that
1032
// we properly put the [moved] marker on them.
@@ -71,3 +93,63 @@ bb3:
7193
%9999 = tuple()
7294
return %9999 : $()
7395
}
96+
97+
// Make sure that we insert a debug_value undef after the destroy_addr that we
98+
// place in block bb2.
99+
// CHECK-LABEL: sil [ossa] @dbg_undef_in_inserted_destroy_addr : $@convention(thin) @async <T where T : P> (@inout T) -> () {
100+
// CHECK: bb2:
101+
// CHECK-NEXT: // function_ref forceSplit
102+
// CHECK-NEXT: function_ref @forceSplit
103+
// CHECK-NEXT: apply
104+
// CHECK-NEXT: debug_value [moved] undef
105+
// CHECK-NEXT: destroy_addr
106+
// CHECK-NEXT: hop_to_executor
107+
// CHECK-NEXT: br bb3
108+
sil [ossa] @dbg_undef_in_inserted_destroy_addr : $@convention(thin) @async <T where T : P> (@inout T) -> () {
109+
bb0(%0 : $*T):
110+
debug_value %0 : $*T, var, name "msg", argno 1, expr op_deref
111+
%2 = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
112+
hop_to_executor %2 : $Optional<Builtin.Executor>
113+
%4 = function_ref @forceSplit : $@convention(thin) @async () -> ()
114+
%5 = apply %4() : $@convention(thin) @async () -> ()
115+
hop_to_executor %2 : $Optional<Builtin.Executor>
116+
cond_br undef, bb1, bb2
117+
118+
bb1:
119+
%11 = alloc_stack $T
120+
%12 = begin_access [modify] [static] %0 : $*T
121+
mark_unresolved_move_addr %12 to %11 : $*T
122+
end_access %12 : $*T
123+
%21 = function_ref @genericUse : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
124+
%22 = apply %21<T>(%11) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
125+
destroy_addr %11 : $*T
126+
dealloc_stack %11 : $*T
127+
%25 = function_ref @forceSplit : $@convention(thin) @async () -> ()
128+
%26 = apply %25() : $@convention(thin) @async () -> ()
129+
hop_to_executor %2 : $Optional<Builtin.Executor>
130+
br bb3
131+
132+
bb2:
133+
%29 = function_ref @forceSplit : $@convention(thin) @async () -> ()
134+
%30 = apply %29() : $@convention(thin) @async () -> ()
135+
hop_to_executor %2 : $Optional<Builtin.Executor>
136+
br bb3
137+
138+
bb3:
139+
%33 = alloc_stack $P
140+
%34 = metatype $@thick T.Type
141+
%35 = witness_method $T, #P.value!getter : <Self where Self : P> (Self.Type) -> () -> P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out P
142+
%36 = apply %35<T>(%33, %34) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out P
143+
%37 = alloc_stack $T
144+
unconditional_checked_cast_addr P in %33 : $*P to T in %37 : $*T
145+
%39 = begin_access [modify] [static] %0 : $*T
146+
copy_addr [take] %37 to %39 : $*T
147+
end_access %39 : $*T
148+
dealloc_stack %37 : $*T
149+
dealloc_stack %33 : $*P
150+
%44 = function_ref @forceSplit : $@convention(thin) @async () -> ()
151+
%45 = apply %44() : $@convention(thin) @async () -> ()
152+
hop_to_executor %2 : $Optional<Builtin.Executor>
153+
%47 = tuple ()
154+
return %47 : $()
155+
}

0 commit comments

Comments
 (0)