Skip to content

safety: initial STPA analysis - #40

Merged
avrabe merged 1 commit into
mainfrom
safety/stpa-initial
Mar 16, 2026
Merged

safety: initial STPA analysis#40
avrabe merged 1 commit into
mainfrom
safety/stpa-initial

Conversation

@avrabe

@avrabe avrabe commented Mar 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds STPA (System-Theoretic Process Analysis) for Synth as a WebAssembly-to-ARM AOT compiler
  • 6 losses, 10 hazards (3 sub-hazards)
  • Follows the same schema as Meld's STPA (pulseengine/meld/safety/schema/stpa.schema.json)

Key coverage areas:

  • Instruction selection correctness
  • Peephole optimization safety
  • Bounds check generation
  • ARM encoding validity (ISA variant matching)
  • Control flow translation (block/loop/if → labels/branches)
  • Register allocation correctness
  • ELF generation (vector table, relocations, sections)
  • Meld dispatch ABI compatibility (__meld_dispatch_import)
  • Verification gap (52 Admitted Rocq proofs, Z3 spec vs implementation)
  • Cross-toolchain canonical ABI consistency with Meld and Kiln (H-10)

Context

Motivated by BA RFC #46 analysis. Synth provides an alternative execution path (AOT) to the RFC's runtime-based approach. The STPA identifies hazards specific to the compilation path that the RFC doesn't cover.

Cross-toolchain consistency analysis in pulseengine/meld at safety/stpa/cross-toolchain-consistency.yaml.

Next steps

  • Add control structure and controlled processes (Step 2)
  • Add UCAs (Step 3)
  • Add loss scenarios (Step 4)
  • Add safety requirements
  • Connect to existing Rocq proof coverage

🤖 Generated with Claude Code

Adds system-theoretic process analysis for Synth as a WebAssembly-to-ARM
AOT compiler. Covers 6 losses and 10 hazards (with 3 sub-hazards).

Key areas: instruction selection correctness, bounds check generation,
ARM encoding validity, control flow translation, register allocation,
ELF generation, Meld dispatch ABI compatibility, and verification gap
between proofs and implementation.

Follows the same STPA schema as Meld (pulseengine/meld/safety/schema/stpa.schema.json).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@avrabe
avrabe merged commit f5676df into main Mar 16, 2026
5 checks passed
@avrabe
avrabe deleted the safety/stpa-initial branch March 16, 2026 19:27
avrabe added a commit that referenced this pull request Jul 15, 2026
…st_poll 724→716 B (#765)

VCR-PERF-001 Lane D (v0.44): extend the forward_stack_reloads holder lattice
with redundant-store elimination. A `str rd,[sp,#N]` whose slot #N the lattice
PROVES already holds rd's value (a caller-save value re-spilled unchanged
between two calls) writes bytes the slot already has — a no-op. Delete it.

gust_poll: one redundant `str.w r0,[sp,#40]` removed between the func_0 reload
and the func_1 call (r0 unchanged since the reload, slot #40 still holding it
from the pre-func_0 spill). 722→716 B machine code (−6, one str.w + 2 B
realignment); 724→716 B by the size oracle's symbol-delta method (−8).
Only gust_poll's bytes change — func_0/func_1/gust_mix byte-identical.

SOUNDNESS:
- Same #606 frozen-span guard as reload-deletion: a deletion inside a resolved
  branch→target span would shift the pre-resolved displacement, so a frozen
  candidate is kept (re-writes the same value; state below identical).
- On deletion the holder set is left UNCHANGED — the slot content is unaltered
  by removing a redundant write, so every co-holder register stays valid;
  collapsing to {rd} would only lose precision.
- OVERWRITE-ONLY / sub-word-hole invariants untouched: this deletes a full-word
  store the lattice already tracks; sub-word sp accesses still clear holders.

Correctness evidence on the new bytes BEFORE re-pinning the size oracle:
- gust_spill_fwd_390_differential.py PASS — gust_poll return value AND post-call
  state struct match wasmtime in all three configs (default, SYNTH_NO_STACK_FWD,
  SYNTH_SPILL_REALLOC=0).
- full scripts/repro/*_differential.py sweep: 90 PASS; the 6 failures fail
  IDENTICALLY on the pristine origin/main binary (5 fact_spec_* need
  --features verify; 1 u64_unpack_riscv a pre-existing RISC-V unicorn harness
  issue) — none are regressions.
- full synth-cli + synth-synthesis test suites green (frozen anchors unchanged).

Also fixes gust_spill_fwd_390_differential.py: post-#758 (v0.43.1) the
self-contained image carries the ~1 MB data ROM image inside `.text`, so
`text.data()` overflowed the 64 KB unicorn code window (UC_ERR_WRITE_UNMAPPED)
on ANY binary. Write only the code prefix that fits — every reachable
instruction lives in the first few KB.

Size oracle re-pinned 724→716; artifacts/size_attribution_390.md regenerated
(gust_poll 3.55x→3.44x vs cited LLVM). Two new unit tests cover the delete and
the reg-reloaded-between keep.


Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant