Skip to content

Commit 0a103d7

Browse files
committed
Draft: detailed debug-info (DWARF) support in new backends (initially x64).
This PR is an initial attempt at propagating "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. Unfortunately, it doesn't *quite* work yet with the gdb tests in tests/all/debug/gdb.rs. Strangely, these tests are marked `#[ignore]`. Needs more debugging, I'd like to publish this draft now as-is to share the design and get feedback / bringup help on the tests.
1 parent cacebfb commit 0a103d7

20 files changed

Lines changed: 805 additions & 91 deletions

File tree

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: 37 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,17 @@ 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 { size: 8, src, dst: SyntheticAmode::NominalSPOffset { simm32 } } =>
2493+
Some(MachInstStackOpInfo::StoreNomSPOff(*src, *simm32 as i64)),
2494+
Self::Mov64MR { src: SyntheticAmode::NominalSPOffset { simm32 }, dst } =>
2495+
Some(MachInstStackOpInfo::LoadNomSPOff(dst.to_reg(), *simm32 as i64)),
2496+
_ => None,
2497+
}
2498+
}
2499+
24762500
fn gen_move(dst_reg: Writable<Reg>, src_reg: Reg, ty: Type) -> Inst {
24772501
let rc_dst = dst_reg.to_reg().get_class();
24782502
let rc_src = src_reg.get_class();
@@ -2636,6 +2660,17 @@ impl MachInst for Inst {
26362660
RegClass::I64
26372661
}
26382662

2663+
fn gen_value_label_marker(label: ValueLabel, reg: Reg) -> Self {
2664+
Inst::ValueLabelMarker { label, reg }
2665+
}
2666+
2667+
fn defines_value_label(&self) -> Option<(ValueLabel, Reg)> {
2668+
match self {
2669+
Inst::ValueLabelMarker { label, reg } => Some((*label, *reg)),
2670+
_ => None,
2671+
}
2672+
}
2673+
26392674
type LabelUse = LabelUse;
26402675
}
26412676

0 commit comments

Comments
 (0)