pub struct FunctionOps {
pub index: u32,
pub export_name: Option<String>,
pub debug_name: Option<String>,
pub ops: Vec<WasmOp>,
pub op_offsets: Vec<u32>,
pub unsupported: Option<String>,
pub block_arity: Vec<(u8, u8)>,
pub declared_i64_locals: Vec<bool>,
}Expand description
Decoded function with its WasmOp sequence
Fields§
§index: u32Function index in the module (includes imported functions)
export_name: Option<String>Export name if this function is exported
debug_name: Option<String>#394 Tier-1.x: the function’s developer-facing name from the wasm name
custom section (function-names subsection), e.g.
core::panicking::panic_fmt::h6651313c3e2c6c2f — present for INTERNAL
(non-exported) functions too, unlike export_name. DEBUG METADATA only:
consumed by the --debug-line DW_TAG_subprogram emit (name priority:
name-section > export name > func_N); no codegen or symbol-table path
reads it, so emitted .text/.symtab are unchanged (frozen-safe).
None when the module has no name section or no entry for this index.
ops: Vec<WasmOp>The WASM operations in this function body
op_offsets: Vec<u32>VCR-DBG-001 step 1 (#394): module-relative wasm byte offset of each op in
ops (same index → same op). This is the address space DWARF-for-wasm
.debug_line keys on, so it is the bridge from synth’s op-index
source_line to the input wasm’s DWARF (wasm-offset → source). PURELY
ADDITIVE metadata: no codegen path reads it, so emitted .text is
unchanged and the frozen fixtures stay bit-identical. Empty until consumed
by the DWARF emitter (Tier 1).
unsupported: Option<String>Some(reason) when the body contained a value-affecting operator the
decoder cannot lower (e.g. scalar f32/f64 — #369, bulk-memory
memory.copy/fill). Such an op would otherwise be silently dropped
(convert_operator → None), leaving the operand stack wrong and the
function a silent miscompile. The compile path LOUD-SKIPS a flagged
function (diagnostic + symbol absent → link error names it) instead —
the #180/#185 “unsupported op must Err, never silently continue”
contract. None once every op decoded or was intentionally ignorable
(Nop).
block_arity: Vec<(u8, u8)>#509: blocktype arity side-table — (param_count, result_count) of the
k-th Block/Loop/If op in ops, in order of appearance.
ORDINAL-keyed, not op-index-keyed, on purpose: the backend may rewrite
the op stream before selection (e.g. the #539 i32.const 0; memory.grow
→ memory.size fold), which shifts op indices but never adds/removes
control ops, so the ordinal stays aligned. BlockType::Empty → (0,0),
ValType → (0,1), FuncType(i) → counts from the type section
(saturated to u8; an unresolvable type index records (u8::MAX, u8::MAX) so the selector declines loudly instead of miscompiling).
This is what lets the direct selector land a value carried by
br/br_if/br_table in the target block’s designated result
register instead of dropping it — WasmOp::Block/Loop/If stay bare
unit variants (zero ripple through the backends’ match sites), and an
empty table (hand-built op streams in unit tests) keeps the legacy
void-block lowering.
declared_i64_locals: Vec<bool>#1214: which of this function’s DECLARED non-parameter locals are i64
(8-byte), by declaration order (index 0 = the first local after the
signature’s parameters) — independent of how, or whether, the op
stream ever WRITES it. infer_i64_locals (the dataflow pass every
selector otherwise relies on for local width) can only learn a
local’s width from a local.set/local.tee that stores a known-i64
value; a local that is read before ANY write and never written at
all — the exact #1214 shape, (local i64) (local.get 0) with no
local.set anywhere in the function — never gets a dataflow-inferred
width and silently defaults to i32, leaving its upper word un-zeroed.
This is the one place the WASM binary format states a local’s width
outright; compute_local_layout ORs it into the dataflow-inferred
set, so every OTHER function (where inference and declaration
necessarily agree, or the module would not validate) is unaffected
byte-for-byte. Empty on the lighter decode_wasm_functions callers
that build the same vector — never hand-omitted.
Trait Implementations§
Source§impl Clone for FunctionOps
impl Clone for FunctionOps
Source§fn clone(&self) -> FunctionOps
fn clone(&self) -> FunctionOps
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more