#[repr(C)]pub struct DebugLocalMeta {
pub source_name: *const u8,
pub name_len: u32,
pub symbol_id: u32,
pub descriptor: *const TypeDescriptor,
pub type_id: u32,
pub kind: u8,
pub span_start: u32,
pub span_end: u32,
pub callee_name: *const u8,
pub callee_name_len: u32,
pub slot_kind: DebugSlotKind,
}Expand description
One local’s metadata at frame construction: the source name (ptr + len),
the compiler-assigned symbol id, the local’s static type descriptor, the
full static Type id, the user-vs-temp classification, the source span, and
what its value slot’s word means.
Flattened for FFI.
Fields§
§source_name: *const u8§name_len: u32§symbol_id: u32§descriptor: *const TypeDescriptorThe local’s static type descriptor (§9.3). The backend embeds the
'static TypeDescriptor resolved from the MIR local’s Type.
type_id: u32The full static Type id (praxis_typeck::Type(u32) handle). Lets the
debugger reconstruct the exact local type (incl. collection element
types / record shapes) the runtime descriptor alone loses.
kind: u8The debugger classification: LOCAL_KIND_USER (a binding the programmer
wrote) or LOCAL_KIND_TEMP (a compiler intermediate). The split is
structural, not a name convention.
span_start: u32The local’s source span [start, end) (byte offsets into program
source) for debugger provenance. User locals carry their binding’s span;
temps carry the expression they materialize (rendered as @ "expr").
(0, 0) means “no span” (the return slot, span-less captures).
span_end: u32§callee_name: *const u8The function a direct call defines this local from (a 'static
embedded string), or null with a zero callee_name_len for every local
that is not one.
It is what places a caller frame’s line: a frame below the innermost is stopped in a call, and the call is the one whose callee is the frame above it. Static, because it is a fact about the program — the live slots cannot answer it, since a loop leaves an earlier pass’s value in the call’s temp.
Null for a CallIndirect: a closure’s target is a value, and the name
this would hold does not exist until the call runs.
callee_name_len: u32§slot_kind: DebugSlotKindWhat this local’s value slot holds (ADR-120 part 2). DebugSlotKind::Reference
for every local whose box the compiler kept; a scalar kind for a temp
whose box the block-local forwarding deleted and whose payload the
definition stores raw.
A real enum, not the u8 its neighbours kind and type_id are,
because nothing outside Rust ever writes this struct: #[repr(C)] is
here so crate::crash_snapshot reads a stable layout, and generated code
only ever stores the address of the enclosing FunctionDebugMeta. So
there is no bit pattern to validate and no “unknown tag” case to decide
what to do with — which is one fewer place the answer could be
Reference by accident.
Implementations§
Source§impl DebugLocalMeta
impl DebugLocalMeta
Sourcepub unsafe fn read(&self, word: Option<GcRef>) -> Option<DebugValue>
pub unsafe fn read(&self, word: Option<GcRef>) -> Option<DebugValue>
Decode one value slot’s word under this local’s slot_kind.
The only place a slot word becomes something typed, and therefore the
only place the reference/scalar question is asked. None is “nothing has
been written here yet”; DebugValue::Reclaimed is the third state, a
reference slot whose object the collector took after it was written.
§The zero word, and the one thing a scalar slot cannot say
A claim zeroes its run, so an all-zero word is “no value yet” — which for
a DebugSlotKind::Reference slot is exact, because a GcRef is
NonNull and can never be zero (F18, the niche this module’s header
describes).
For a scalar slot it cannot be exact — 2^64 payloads do not fit in 2^64
words beside an “unwritten” state — so exactly one payload per kind reads
back as <uninit>. Which one is DebugSlotKind::store_bias’s
choice: three kinds lose nothing, Float loses one NaN, and Int
loses i64::MIN. The direction of the error is the safe one — a slot
under-reports a value it holds and never reports a value it does not.
an_int_slot_holding_i64_min_reads_as_uninit_and_zero_does_not pins both
halves.
§Safety
word must be the current content of a live value slot belonging to a
frame whose metadata is this one — that is, values[i] paired with
locals[i] of the same FunctionDebugMeta. Pairing a word with
another local’s metadata is exactly the mistake this function exists to
make impossible to write by hand, and the two callers
(DebugFrameStackHeader::clear_reclaimed and
crash_snapshot::copy_stack) both zip the two arrays.