From cf70053368d6cec6eccb3fc93e29b636620a6e95 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Sun, 1 Feb 2026 15:44:56 +1000 Subject: [PATCH] cranelift: improve debug value locations around cold blocks If a debug range started or ended on an instruction from a cold block, we omitted the entire range. Fix by skipping the instructions in the cold block to find the next valid offset. --- cranelift/codegen/src/machinst/vcode.rs | 22 ++++++----- .../test-programs/src/bin/dwarf_cold_block.c | 20 ++++++++++ tests/all/native_debug/lldb.rs | 39 +++++++++++++++++++ 3 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 crates/test-programs/src/bin/dwarf_cold_block.c diff --git a/cranelift/codegen/src/machinst/vcode.rs b/cranelift/codegen/src/machinst/vcode.rs index 5a1aa71b9761..b3d0a641930f 100644 --- a/cranelift/codegen/src/machinst/vcode.rs +++ b/cranelift/codegen/src/machinst/vcode.rs @@ -1253,21 +1253,23 @@ impl VCode { } inst.index() }; - let from_inst_index = prog_point_to_inst(from); - let to_inst_index = prog_point_to_inst(to); - let from_offset = inst_offsets[from_inst_index]; - let to_offset = if to_inst_index == inst_offsets.len() { + let inst_to_offset = |inst_index: usize| { + // Skip over cold blocks. + for offset in &inst_offsets[inst_index..] { + if *offset != NO_INST_OFFSET { + return *offset; + } + } func_body_len - } else { - inst_offsets[to_inst_index] }; + let from_inst_index = prog_point_to_inst(from); + let to_inst_index = prog_point_to_inst(to); + let from_offset = inst_to_offset(from_inst_index); + let to_offset = inst_to_offset(to_inst_index); // Empty ranges or unavailable offsets can happen // due to cold blocks and branch removal (see above). - if from_offset == NO_INST_OFFSET - || to_offset == NO_INST_OFFSET - || from_offset == to_offset - { + if from_offset == to_offset { continue; } diff --git a/crates/test-programs/src/bin/dwarf_cold_block.c b/crates/test-programs/src/bin/dwarf_cold_block.c new file mode 100644 index 000000000000..45604299c224 --- /dev/null +++ b/crates/test-programs/src/bin/dwarf_cold_block.c @@ -0,0 +1,20 @@ +struct myfile { + int data; + void (*f)(); +} myfile; + +void f() {} + +int foo(struct myfile *f1) { + f1->f(); + if (f1->data == 42) + return 0; + return 1; +} + +int main() { + struct myfile f1; + f1.f = &f; + f1.data = 42; + return foo(&f1); +} diff --git a/tests/all/native_debug/lldb.rs b/tests/all/native_debug/lldb.rs index 700f113bb160..d70112751d87 100644 --- a/tests/all/native_debug/lldb.rs +++ b/tests/all/native_debug/lldb.rs @@ -554,3 +554,42 @@ check: exited with status = 0 } Ok(()) } + +#[test] +#[ignore] +pub fn dwarf_cold_block() -> Result<()> { + let output = lldb_with_script( + &[ + "-Ccache=n", + "-Oopt-level=0", + "-Ddebug-info", + DWARF_COLD_BLOCK, + ], + r#"b foo +r +p __vmctx->set(),*f1 +n +p __vmctx->set(),*f1 +n +p __vmctx->set(),*f1 +n +p __vmctx->set(),*f1 +c"#, + )?; + + check_lldb_output( + &output, + r#" +check: Breakpoint 1: no locations (pending) +check: stop reason = breakpoint 1.1 +check: frame #0 +sameln: foo(f1=(__ptr = +check: data = 42 +check: data = 42 +check: data = 42 +check: data = 42 +check: resuming +"#, + )?; + Ok(()) +}