Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,19 @@ serde = [
]
tracing = ["serde"]
debug-print = []
# Floating point support. NOT officially supported and NOT for production builds: this exists only
# for the e2e testing suite and the fuzzer, which need real float semantics for the wasm spec tests
# and for wasmtime differential runs.
#
# WARNING: this feature changes emitted bytecode, not just runtime behaviour. Without it every
# float instruction is compiled to `Trap(IllegalOpcode)`, so an `fpu` build and a default build
# produce different modules (and different module hashes) for the same wasm input. See
# `impl_fpu_opcode!` in `src/isa/mod.rs` and `CompilationConfig::codegen_identity`.
fpu = []
wasmtime = ["dep:wasmtime", "dep:lru"]
cache-compiled-artifacts = ["wasmtime", "dep:directories"]
# Relaxations required by the e2e testing suite (spectest globals, funcref/externref values).
# Test-only, never for production builds.
e2e = []
pooling-allocator = []
full-wasm-mode = ["wasmtime?/full-wasm-mode"]
Expand Down
30 changes: 30 additions & 0 deletions docs/module-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,36 @@ After header, fields are encoded in this exact order:
- Feature combinations (`fpu`, etc.) alter executable surface and should be pinned.
- Legacy support currently handles missing `source_pc` by defaulting to `0`.

## Codegen determinism

The header version (`0x01`) identifies the *wire format*, not the compiler configuration. The same
wasm input does not compile to the same bytes under every build, and the encoded module records
nothing about the build that produced it.

Inputs that change emitted bytecode:

- **`CompilationConfig` flags** — `code_snippets` decides which functions are emitted and therefore
shifts every downstream instruction offset; `consume_fuel`, `consume_fuel_for_bulk_ops`,
`consume_fuel_for_params_and_locals`, and `builtins_consume_fuel` decide where fuel charges are
injected; `max_allowed_memory_pages` and `default_imported_global_value` are baked into the
emitted code; `state_router`, `entrypoint_name`, and `import_linker` shape the entrypoint and the
syscall mapping. The `allow_*` flags relax validation and decide which inputs compile at all.
- **The `fpu` cargo feature** — off (the default), every float instruction is compiled to
`Trap(IllegalOpcode)`; on, real float opcodes are emitted. Floating point is not officially
supported: `fpu` exists for the e2e suite and the fuzzer only and must not be enabled in a
production build.

Features that only change the host-side surface (`std`, `serde`, `wasmtime`, `debug-print`, …) do
not affect the emitted bytes.

`CompilationConfig::codegen_identity()` hashes all of the above — the codegen-relevant config fields
plus the compile-time feature set of the compiling binary — into a 32-byte fingerprint. Compilers
agreeing on this value produce identical bytecode for a given wasm input. The fingerprint is **not**
part of the wire format, so a host that addresses modules by hash must carry the identity alongside
the bytecode and reject a module whose producer identity does not match its own. Embedding the
identity in the header would require a `RWASM_VERSION_V2` bump and would change the bytes (and
hashes) of every module.

## Constructor/custom-section note

Constructor parameter conventions are handled in `src/types/constructor_params.rs`.
Expand Down
Loading
Loading