Skip to content

RV32: active data-segment initializers are silently dropped — ship them (linker-script placement + startup copy) and hard-decline until then #798

Description

@avrabe

Found by the VCR-VER-003 phase-2 probe (#777, PR #797)

The RV32 backend uses a single-base scheme (s11 = __linear_memory_base, provided by the generated linker script at _bss_end, zeroed at reset). The relocatable object ships .text only — neither the object, the generated startup.c, nor linker.ld carries the wasm module's active data segments. A module like

(module
  (memory 1)
  (data (i32.const 16) "\01\02\03\04")
  (func (export "get") (result i32) i32.const 16 i32.load))

compiles clean, and get returns 0 at runtime instead of 0x04030201 — the #757-family silent drop (worse: unconditional, not overlap-dependent).

What phase 2 landed (PR #797)

validate_served_image(segments, &[]) runs unconditionally on the RV32 emit path and WARNS LOUDLY per nonzero un-served initializer byte (later-wins semantics: all-zero / zero-overwritten runtime images are genuinely served by zeroed RAM and stay silent).

Why it is a warning, not a hard decline (yet)

The CI-pinned RV32 frozen fixture (control_step.wasm, frozen_fixtures_rv32_text_is_bit_identical_oracle_001) carries a nonzero active segment (11 B at 65536) that its differential never reads — a hard decline would break the frozen compile-success gate. Flipping to a decline needs the refreeze ritual (or the real fix below) in its own evidence-gated PR.

The real fix (RV32 analogue of #758)

  1. Emit the packed initializer image into the object (e.g. .wasm_data PROGBITS, later-wins dense image or per-segment with offsets),
  2. place it via the generated linker script at __linear_memory_base + off (load address in flash),
  3. copy ROM→RAM in the generated startup (the existing _data_load/_data_start pattern),
  4. validate the shipped image with the existing validate_served_image (turn the warning into the mixed-split-style hard error on mismatch),
  5. differential: an RV32 module that READS its data segment vs wasmtime.

Until then the honest end-state per the #615 expand-or-loud-reject rule is a hard decline for nonzero-initializer modules on -b riscv.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions