Skip to content

Commit c1e0be1

Browse files
committed
Detailed debug-info (DWARF) support in new backends (initially x64).
This PR propagates "value labels" all the way from CLIF to DWARF metadata on the emitted machine code. The key idea is as follows: - Translate value-label metadata on the input into "value_label" pseudo-instructions when lowering into VCode. These pseudo-instructions take a register as input, denote a value label, and semantically are like a "move into value label" -- i.e., they update the current value (as seen by debugging tools) of the given local. These pseudo-instructions emit no machine code. - Perform a dataflow analysis *at the machine-code level*, tracking value-labels that propagate into registers and into [SP+constant] stack storage. This is a forward dataflow fixpoint analysis where each storage location can contain a *set* of value labels, and each value label can reside in a *set* of storage locations. (Meet function is pairwise intersection by storage location.) This analysis traces value labels symbolically through loads and stores and reg-to-reg moves, so it will naturally handle spills and reloads without knowing anything special about them. - When this analysis converges, we have, at each machine-code offset, a mapping from value labels to some number of storage locations; for each offset for each label, we choose the best location (prefer registers). Note that we can choose any location, as the symbolic dataflow analysis is sound and guarantees that the value at the value_label instruction propagates to all of the named locations. - Then we can convert this mapping into a format that the DWARF generation code (wasmtime's debug crate) can use. This PR also adds the new-backend variant to the gdb tests on CI.
1 parent cacebfb commit c1e0be1

File tree

21 files changed

+841
-92
lines changed

21 files changed

+841
-92
lines changed

.github/workflows/main.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,14 @@ jobs:
292292
env:
293293
RUST_BACKTRACE: 1
294294
295+
# Test debug (DWARF) related functionality on new backend.
296+
- run: |
297+
sudo apt-get update && sudo apt-get install -y gdb
298+
cargo test --features experimental_x64 test_debug_dwarf -- --ignored --test-threads 1
299+
if: matrix.target == 'x86_64-unknown-linux-gnu'
300+
env:
301+
RUST_BACKTRACE: 1
302+
295303
# Build and test lightbeam. Note that
296304
# Lightbeam tests fail right now, but we don't want to block on that.
297305
- run: cargo build --package lightbeam

cranelift/codegen/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ all-arch = [
7474
]
7575

7676
# For dependent crates that want to serialize some parts of cranelift
77-
enable-serde = ["serde"]
77+
enable-serde = ["serde", "regalloc/enable-serde"]
7878

7979
# Allow snapshotting regalloc test cases. Useful only to report bad register
8080
# allocation failures, or for regalloc.rs developers.

cranelift/codegen/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ impl Context {
473473
Ok(build_value_labels_ranges::<ComparableSourceLoc>(
474474
&self.func,
475475
&self.regalloc,
476+
self.mach_compile_result.as_ref(),
476477
isa,
477478
))
478479
}

cranelift/codegen/src/ir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub use crate::ir::table::TableData;
5858
pub use crate::ir::trapcode::TrapCode;
5959
pub use crate::ir::types::Type;
6060
pub use crate::ir::valueloc::{ArgumentLoc, ValueLoc};
61+
pub use crate::value_label::LabelValueLoc;
6162
pub use cranelift_codegen_shared::condcodes;
6263

6364
use crate::binemit;

cranelift/codegen/src/isa/aarch64/inst/emit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2365,6 +2365,9 @@ impl MachInstEmit for Inst {
23652365
sink.bind_label(jump_around_label);
23662366
}
23672367
}
2368+
&Inst::ValueLabelMarker { .. } => {
2369+
// Nothing; this is only used to compute debug info.
2370+
}
23682371
}
23692372

23702373
let end_off = sink.cur_offset();

cranelift/codegen/src/isa/aarch64/inst/mod.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::binemit::CodeOffset;
77
use crate::ir::types::{
88
B1, B128, B16, B32, B64, B8, F32, F64, FFLAGS, I128, I16, I32, I64, I8, I8X16, IFLAGS, R32, R64,
99
};
10-
use crate::ir::{ExternalName, MemFlags, Opcode, SourceLoc, TrapCode, Type};
10+
use crate::ir::{ExternalName, MemFlags, Opcode, SourceLoc, TrapCode, Type, ValueLabel};
1111
use crate::isa::CallConv;
1212
use crate::machinst::*;
1313
use crate::{settings, CodegenError, CodegenResult};
@@ -1208,6 +1208,12 @@ pub enum Inst {
12081208
/// The needed space before the next deadline.
12091209
needed_space: CodeOffset,
12101210
},
1211+
1212+
/// A definition of a value label.
1213+
ValueLabelMarker {
1214+
reg: Reg,
1215+
label: ValueLabel,
1216+
},
12111217
}
12121218

12131219
fn count_zero_half_words(mut value: u64, num_half_words: u8) -> usize {
@@ -2015,6 +2021,9 @@ fn aarch64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
20152021
memarg_regs(mem, collector);
20162022
}
20172023
&Inst::VirtualSPOffsetAdj { .. } => {}
2024+
&Inst::ValueLabelMarker { reg, .. } => {
2025+
collector.add_use(reg);
2026+
}
20182027
&Inst::EmitIsland { .. } => {}
20192028
}
20202029
}
@@ -2765,6 +2774,9 @@ fn aarch64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
27652774
}
27662775
&mut Inst::VirtualSPOffsetAdj { .. } => {}
27672776
&mut Inst::EmitIsland { .. } => {}
2777+
&mut Inst::ValueLabelMarker { ref mut reg, .. } => {
2778+
map_use(mapper, reg);
2779+
}
27682780
}
27692781
}
27702782

@@ -2960,6 +2972,17 @@ impl MachInst for Inst {
29602972
fn ref_type_regclass(_: &settings::Flags) -> RegClass {
29612973
RegClass::I64
29622974
}
2975+
2976+
fn gen_value_label_marker(label: ValueLabel, reg: Reg) -> Self {
2977+
Inst::ValueLabelMarker { label, reg }
2978+
}
2979+
2980+
fn defines_value_label(&self) -> Option<(ValueLabel, Reg)> {
2981+
match self {
2982+
Inst::ValueLabelMarker { label, reg } => Some((*label, *reg)),
2983+
_ => None,
2984+
}
2985+
}
29632986
}
29642987

29652988
//=============================================================================
@@ -4068,6 +4091,10 @@ impl Inst {
40684091
format!("virtual_sp_offset_adjust {}", offset)
40694092
}
40704093
&Inst::EmitIsland { needed_space } => format!("emit_island {}", needed_space),
4094+
4095+
&Inst::ValueLabelMarker { label, reg } => {
4096+
format!("value_label {:?}, {}", label, reg.show_rru(mb_rru))
4097+
}
40714098
}
40724099
}
40734100
}

cranelift/codegen/src/isa/aarch64/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ impl MachBackend for AArch64Backend {
7979
frame_size,
8080
disasm,
8181
unwind_info,
82+
value_labels_ranges: None,
8283
})
8384
}
8485

cranelift/codegen/src/isa/arm32/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ impl MachBackend for Arm32Backend {
7474
frame_size,
7575
disasm,
7676
unwind_info: None,
77+
value_labels_ranges: None,
7778
})
7879
}
7980

cranelift/codegen/src/isa/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,12 @@ pub trait TargetIsa: fmt::Display + Send + Sync {
325325
Err(RegisterMappingError::UnsupportedArchitecture)
326326
}
327327

328+
#[cfg(feature = "unwind")]
329+
/// Map a regalloc::Reg to its corresponding DWARF register.
330+
fn map_regalloc_reg_to_dwarf(&self, _: ::regalloc::Reg) -> Result<u16, RegisterMappingError> {
331+
Err(RegisterMappingError::UnsupportedArchitecture)
332+
}
333+
328334
/// Returns an iterator over legal encodings for the instruction.
329335
fn legal_encodings<'a>(
330336
&'a self,

cranelift/codegen/src/isa/x64/inst/emit.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,6 +2962,10 @@ pub(crate) fn emit(
29622962
Inst::EpiloguePlaceholder => {
29632963
// Generate no code.
29642964
}
2965+
2966+
Inst::ValueLabelMarker { .. } => {
2967+
// Nothing; this is only used to compute debug info.
2968+
}
29652969
}
29662970

29672971
state.clear_post_insn();

cranelift/codegen/src/isa/x64/inst/mod.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This module defines x86_64-specific machine instruction types.
22
33
use crate::binemit::{CodeOffset, StackMap};
4-
use crate::ir::{types, ExternalName, Opcode, SourceLoc, TrapCode, Type};
4+
use crate::ir::{types, ExternalName, Opcode, SourceLoc, TrapCode, Type, ValueLabel};
55
use crate::isa::x64::settings as x64_settings;
66
use crate::machinst::*;
77
use crate::{settings, settings::Flags, CodegenError, CodegenResult};
@@ -474,6 +474,9 @@ pub enum Inst {
474474
/// reports its own `def`s/`use`s/`mod`s; this adds complexity (the instruction list is no
475475
/// longer flat) and requires knowledge about semantics and initial-value independence anyway.
476476
XmmUninitializedValue { dst: Writable<Reg> },
477+
478+
/// A definition of a value label.
479+
ValueLabelMarker { reg: Reg, label: ValueLabel },
477480
}
478481

479482
pub(crate) fn low32_will_sign_extend_to_64(x: u64) -> bool {
@@ -532,7 +535,8 @@ impl Inst {
532535
| Inst::XmmCmpRmR { .. }
533536
| Inst::XmmLoadConst { .. }
534537
| Inst::XmmMinMaxSeq { .. }
535-
| Inst::XmmUninitializedValue { .. } => None,
538+
| Inst::XmmUninitializedValue { .. }
539+
| Inst::ValueLabelMarker { .. } => None,
536540

537541
// These use dynamic SSE opcodes.
538542
Inst::GprToXmm { op, .. }
@@ -1762,6 +1766,10 @@ impl PrettyPrint for Inst {
17621766
Inst::Hlt => "hlt".into(),
17631767

17641768
Inst::Ud2 { trap_code } => format!("ud2 {}", trap_code),
1769+
1770+
Inst::ValueLabelMarker { label, reg } => {
1771+
format!("value_label {:?}, {}", label, reg.show_rru(mb_rru))
1772+
}
17651773
}
17661774
}
17671775
}
@@ -2021,6 +2029,9 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
20212029
| Inst::Fence { .. } => {
20222030
// No registers are used.
20232031
}
2032+
Inst::ValueLabelMarker { reg, .. } => {
2033+
collector.add_use(*reg);
2034+
}
20242035
}
20252036
}
20262037

@@ -2385,6 +2396,8 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
23852396
dst.map_uses(mapper);
23862397
}
23872398

2399+
Inst::ValueLabelMarker { ref mut reg, .. } => map_use(mapper, reg),
2400+
23882401
Inst::Ret
23892402
| Inst::EpiloguePlaceholder
23902403
| Inst::JmpKnown { .. }
@@ -2473,6 +2486,25 @@ impl MachInst for Inst {
24732486
}
24742487
}
24752488

2489+
fn stack_op_info(&self) -> Option<MachInstStackOpInfo> {
2490+
match self {
2491+
Self::VirtualSPOffsetAdj { offset } => Some(MachInstStackOpInfo::NomSPAdj(*offset)),
2492+
Self::MovRM {
2493+
size: 8,
2494+
src,
2495+
dst: SyntheticAmode::NominalSPOffset { simm32 },
2496+
} => Some(MachInstStackOpInfo::StoreNomSPOff(*src, *simm32 as i64)),
2497+
Self::Mov64MR {
2498+
src: SyntheticAmode::NominalSPOffset { simm32 },
2499+
dst,
2500+
} => Some(MachInstStackOpInfo::LoadNomSPOff(
2501+
dst.to_reg(),
2502+
*simm32 as i64,
2503+
)),
2504+
_ => None,
2505+
}
2506+
}
2507+
24762508
fn gen_move(dst_reg: Writable<Reg>, src_reg: Reg, ty: Type) -> Inst {
24772509
let rc_dst = dst_reg.to_reg().get_class();
24782510
let rc_src = src_reg.get_class();
@@ -2636,6 +2668,17 @@ impl MachInst for Inst {
26362668
RegClass::I64
26372669
}
26382670

2671+
fn gen_value_label_marker(label: ValueLabel, reg: Reg) -> Self {
2672+
Inst::ValueLabelMarker { label, reg }
2673+
}
2674+
2675+
fn defines_value_label(&self) -> Option<(ValueLabel, Reg)> {
2676+
match self {
2677+
Inst::ValueLabelMarker { label, reg } => Some((*label, *reg)),
2678+
_ => None,
2679+
}
2680+
}
2681+
26392682
type LabelUse = LabelUse;
26402683
}
26412684

cranelift/codegen/src/isa/x64/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ use self::inst::EmitInfo;
44

55
use super::TargetIsa;
66
use crate::ir::{condcodes::IntCC, Function};
7+
use crate::isa::unwind::systemv::RegisterMappingError;
78
use crate::isa::x64::{inst::regs::create_reg_universe_systemv, settings as x64_settings};
89
use crate::isa::Builder as IsaBuilder;
910
use crate::machinst::{compile, MachBackend, MachCompileResult, TargetIsaAdapter, VCode};
1011
use crate::result::CodegenResult;
1112
use crate::settings::{self as shared_settings, Flags};
1213
use alloc::boxed::Box;
13-
use regalloc::{PrettyPrint, RealRegUniverse};
14+
use regalloc::{PrettyPrint, RealRegUniverse, Reg};
1415
use target_lexicon::Triple;
1516

1617
mod abi;
@@ -60,6 +61,7 @@ impl MachBackend for X64Backend {
6061
let buffer = buffer.finish();
6162
let frame_size = vcode.frame_size();
6263
let unwind_info = vcode.unwind_info()?;
64+
let value_labels_ranges = vcode.value_labels_ranges()?;
6365

6466
let disasm = if want_disasm {
6567
Some(vcode.show_rru(Some(&create_reg_universe_systemv(flags))))
@@ -72,6 +74,7 @@ impl MachBackend for X64Backend {
7274
frame_size,
7375
disasm,
7476
unwind_info,
77+
value_labels_ranges,
7578
})
7679
}
7780

@@ -127,6 +130,11 @@ impl MachBackend for X64Backend {
127130
fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
128131
Some(inst::unwind::systemv::create_cie())
129132
}
133+
134+
#[cfg(feature = "unwind")]
135+
fn map_reg_to_dwarf(&self, reg: Reg) -> Result<u16, RegisterMappingError> {
136+
inst::unwind::systemv::map_reg(reg).map(|reg| reg.0)
137+
}
130138
}
131139

132140
/// Create a new `isa::Builder`.

cranelift/codegen/src/machinst/adapter.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ use crate::settings::Flags;
1010
#[cfg(feature = "testing_hooks")]
1111
use crate::regalloc::RegDiversions;
1212

13+
#[cfg(feature = "unwind")]
14+
use crate::isa::unwind::systemv::RegisterMappingError;
15+
1316
use core::any::Any;
1417
use std::borrow::Cow;
1518
use std::fmt;
@@ -134,6 +137,11 @@ impl TargetIsa for TargetIsaAdapter {
134137
self.backend.create_systemv_cie()
135138
}
136139

140+
#[cfg(feature = "unwind")]
141+
fn map_regalloc_reg_to_dwarf(&self, r: Reg) -> Result<u16, RegisterMappingError> {
142+
self.backend.map_reg_to_dwarf(r)
143+
}
144+
137145
fn as_any(&self) -> &dyn Any {
138146
self as &dyn Any
139147
}

0 commit comments

Comments
 (0)