Skip to content

fix: WAST validation improvements v3 — SIMD, GC refs, section ordering, const exprs#145

Merged
avrabe merged 14 commits intomainfrom
fix/wast-validation-improvements-v3
Mar 8, 2026
Merged

fix: WAST validation improvements v3 — SIMD, GC refs, section ordering, const exprs#145
avrabe merged 14 commits intomainfrom
fix/wast-validation-improvements-v3

Conversation

@avrabe
Copy link
Collaborator

@avrabe avrabe commented Mar 8, 2026

Summary

Improves WAST test conformance pass rate from ~93% to ~94.6% (61,100 → 62,081 assertions passing out of ~65,624).

Changes by commit

  1. RefType::Gc and SIMD types — Added GC reference types, SIMD instruction variants, and table64 support to foundation types
  2. Compilation fixes — Resolved cascading compilation errors from the new types
  3. SIMD opcode parsing — Added SIMD 0xFD prefix opcode parsing and GC reference type support in the parser
  4. SIMD memory operations — Implemented v128.load/store/splat/lane operations in the engine
  5. SIMD instruction dispatch — Added comprehensive SIMD instruction dispatch (comparison, arithmetic, conversion)
  6. Test fixes — Fixed 4 test failures and reduced production panics
  7. SIMD validation — Fixed SIMD unary/binary classification and memory64/table64 type checking
  8. Encoded reference types — Handle 0x63/0x64 (ref/ref null) in table and element sections in decoder
  9. Unreachable code validation — Improved alignment checking, const expr validation
  10. SIMD lane/export/segment/tag validation — Additional validator checks
  11. Type reference validation — Validate type indices are in bounds, GC reference compatibility in tables
  12. Section ordering — Validate non-custom sections appear in spec order, reject duplicates
  13. Const expr subtyping — Use is_subtype_of() for const expr end checks, proper ref.func/ref.null typing
  14. ref.null LEB128 parsing — Use proper signed LEB128 for heap type in function bodies (not single byte)

Test results

  • 62,081 assertions passing (up from ~61,100)
  • 132 test files fully passing (up from ~125)
  • 3,543 assertions still failing

What's NOT included (see follow-up issues)

  • Unreachable code excess value detection (needs polymorphic stack tracking)
  • GC structural subtyping validation
  • Additional assert_malformed decoder improvements
  • Runtime execution fixes (linking, call_indirect, exception handling)

avrabe and others added 14 commits March 1, 2026 19:33
- Add Gc(GcRefType) variant to RefType enum with full conversion support
- Add GcRefType::to_value_type() for GC heap type to ValueType mapping
- Add 6 SIMD instruction variants to Instruction enum (V128Const, SimdOp,
  SimdMemOp, SimdShuffle, SimdLaneOp, SimdMemLaneOp)
- Add table64 bool field to TableType for Table64 extension support
- Add simd_ops.rs with SIMD computation helpers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add execution dispatch for all SIMD (V128) instruction variants in the
stackless engine, connecting parsed SIMD instructions to the existing
simd_ops computation helpers. Covers v128 bitwise ops, splat, swizzle,
shuffle, all integer/float lane comparisons, arithmetic, shifts,
min/max, conversions, lane extract/replace, and memory stubs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…/lane)

Implements all SIMD memory instructions:
- v128.load/store (16 bytes)
- v128.load8x8_s/u, load16x4_s/u, load32x2_s/u (extending loads)
- v128.load8/16/32/64_splat (splatting loads)
- v128.load32/64_zero (zero-extending loads)
- v128.load8/16/32/64_lane (lane-targeted loads)
- v128.store8/16/32/64_lane (lane-targeted stores)

Also fixes parser to correctly parse load_lane/store_lane ops (0x54-0x5B)
as SimdMemLaneOp with memarg + lane index, not SimdMemOp.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ction panics

- Replace BoundedVec with fixed arrays in kiln-debug (file_table, parameter, strings)
  to fix serialization failures with zero-size and variable-length types
- Convert From<ComponentTypeDefinition> to TryFrom (eliminates 2 panics)
- Change get_type() to return Result instead of panicking (6 panics removed)
- Replace panic in FuelChain with Poll::Ready(Err(...))
- Replace panics in component.rs with error returns and unreachable!
- Remove dead force_push() method from allocator/collections
- Replace unwrap_or_else(|| panic!()) with .expect() in safe_memory

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… type checking

- Fix SIMD validator to correctly classify f64x2.ceil/floor/trunc/nearest as
  unary operations (were missing from unary list causing validation failures)
- Remove incorrect 0xD4..=0xDB range from unary list (i64x2 comparisons are
  binary operations, not unary)
- Add is_table64() helper function for table64 index type checking
- Fix memory.init/copy/fill to use i64 operands when memory is memory64
- Fix table.init/copy/get/set/grow/size/fill to use i64 when table is table64

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… element sections

Adds support for multi-byte reference type encoding (ref null ht / ref ht)
in the table section, import section table types, and element segment
types (flags 5, 6, 7). Previously these caused "Unknown table element type"
errors that cascaded to ~482 test failures across 8 WAST files.

Also adds decode_heap_type() helper for converting s33 LEB128 heap type
values to HeapType enum variants.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ment, and const expr validation

Major validator improvements raising WAST pass rate from ~93.3% to ~94.1% (+500 tests):

- Fix unreachable code stack handling: after terminating instructions (br, br_table,
  return, unreachable, throw, throw_ref, rethrow), truncate stack to frame base and
  set unreachable_height correctly. This makes the stack properly polymorphic per spec.
- Add memory alignment validation: check that load/store alignment doesn't exceed
  natural alignment for both standard and SIMD memory operations.
- Add data/element segment offset expression validation: verify offset expressions
  use only constant instructions and immutable globals.
- Wire table64 flag through kiln-decoder: both sections.rs and streaming_decoder.rs
  now propagate the table64 flag from the limits flags byte.
- Add GC constant expression support in runtime evaluator (ref.i31, struct/array ops).
- Fix SIMD dot product overflow with wrapping_add.
- Fix memory.init/table.init stack types (source and length always i32).
- Add I31Ref/StructRef/ArrayRef type matching in table validation.
- Add WastRetCore::RefI31 handling in test value comparison.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add several missing validation checks that improve WAST conformance:

- SIMD lane index bounds: extract_lane, replace_lane validate lane < lane_count
  (i8x16: 16, i16x8: 8, i32x4/f32x4: 4, i64x2/f64x2: 2)
- i8x16.shuffle lane validation: all 16 lane indices must be < 32
- Load/store lane validation: load8_lane through store64_lane check lane bounds
- Export index bounds: validate function/table/memory/global/tag export indices
- Table limits: reject tables where min > max
- Tag validation: reject tags with non-empty result types
- Bulk memory index bounds: memory.init, data.drop, memory.fill, memory.copy
  validate memory and data segment indices
- Table operation index bounds: table.init, elem.drop, table.copy validate
  table and element segment indices

Files reaching 100%: simd_lane.wast (475/475), exports.wast (185/185),
memory_init.wast (240/240), memory_fill.wast (100/100),
simd_load8_lane.wast (52/52), proposals/threads/exports.wast (88/88)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ibility

- Fix from_ref_type() to handle HeapType::Concrete(idx) → TypedFuncRef(idx, nullable)
  instead of incorrectly mapping to ExternRef
- Fix from_ref_type() to handle HeapType::Exn → ExnRef and HeapType::NoFunc → NullFuncRef
- Add validate_type_references() checking all type index references in:
  - Type section params/results
  - Function locals
  - Table element types
  - Global value types
  - Import table/global types
  - Element segment types
- Add type index bounds checking in parse_block_type for GC typed references
- Add GC reference handling in typed select (0x1C) value type parsing
- Fix table element type compatibility: allow FuncRef values in Gc-typed tables
  (for tables with typed function references like (ref null $t))
- Map unknown GC heap types to Unknown instead of ExternRef for better fallback

Test results: 62,023 passed (+142 from last commit), 133 files fully passing (+1)
New fully passing: ref.wast, ref_is_null.wast

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WebAssembly spec requires non-custom sections to appear in a defined order,
with each non-custom section appearing at most once. Add section ordering
validation to the streaming decoder:

- Track last non-custom section ID seen during decoding
- Map section IDs to spec ordering indices (handles data count section ID 12
  appearing before code section ID 10 in the spec order)
- Reject duplicate sections with "unexpected content after last section"
- Reject unknown section IDs > 13 with "malformed section id"
- Custom sections (ID 0) can still appear anywhere

This fixes 36+ assert_malformed tests in binary.wast that expected
"unexpected content after last section" or "malformed section id" errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…yped refs

- Use subtype checking instead of strict equality in const expr end validation
- Fix ref.func to push TypedFuncRef(type_idx, false) instead of generic FuncRef,
  allowing it to match typed function reference expectations
- Fix ref.null to push correct bottom types:
  - ref.null func → NullFuncRef (bottom of funcref hierarchy)
  - ref.null nofunc → NullFuncRef
  - ref.null $t → TypedFuncRef(t, true) (nullable typed reference)
  - ref.null exn → ExnRef
- These changes fix false validation failures for modules with typed globals
  initialized by ref.func or ref.null expressions

Test results: 62,072 passed (+49 from last commit), 133 files fully passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… bodies

Previously ref.null in function body validation read a single byte for the
heap type, which fails for type indices >= 128. Now uses parse_varint64 for
proper signed LEB128 (s33) parsing and pushes correct typed references
matching the const expr handler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Mar 8, 2026

🔍 Build Diagnostics Report

Summary

Metric Base Branch This PR Change
Errors 0 0 0
Warnings 2 2 0

🎯 Impact Analysis

Issues in Files You Modified

  • 0 new errors introduced by your changes
  • 0 new warnings introduced by your changes
  • 0 total errors in modified files
  • 0 total warnings in modified files
  • 0 files you modified

Cascading Issues (Your Changes Breaking Other Files)

  • 0 new errors in unchanged files
  • 0 new warnings in unchanged files
  • 0 unchanged files now affected

Note: "Cascading issues" are errors in files you didn't modify, caused by your changes (e.g., breaking API changes, dependency issues).

✅ No Issues Detected

Perfect! Your changes don't introduce any new errors or warnings, and don't break any existing code.


📊 Full diagnostic data available in workflow artifacts

🔧 To reproduce locally:

# Install cargo-kiln
cargo install --path cargo-kiln

# Analyze your changes
cargo-kiln build --output json --filter-severity error
cargo-kiln check --output json --filter-severity warning

@avrabe avrabe merged commit 32a67a1 into main Mar 8, 2026
16 checks passed
@avrabe avrabe deleted the fix/wast-validation-improvements-v3 branch March 8, 2026 16:25
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