Files
wasm2go/internal/codegen/helpers/helpers_m64_smoke_test.go
zandGitHub c45b8a7eeb Fix Memory64 scalar overflow traps and require real >4 GiB AOT certification (#1)
* Trap memory64 scalar out-of-bounds/overflow before native pointer use: internal/codegen/emit_memops.go

* Trap memory64 scalar out-of-bounds/overflow before native pointer use: internal/codegen/helpers/helpers.go

* Regression: memory64 scalar loads/stores must trap on u64 overflow

* Make greater-than-4GiB memory certification fail closed when required

* Add required real >4 GiB Memory64 CI gate

* Repair Memory64 CI workflow YAML after broken replacement

* CLI: add strict -require-memory64 mode for native AOT builds

* Test strict memory64 CLI accepts wasm64 and refuses wasm32

* Document strict Memory64 AOT mode and real 4 GiB proof requirements

* Register memory64 bounds helper in generator dependency closure

* Test memory64 bounds helper and keep extractor-only function referenced

* Align compiler-source lint/vet with generated benchmark policy (Makefile)

* Align compiler-source lint/vet with generated benchmark policy (internal/testfixture/fixture.go)

* Correct Memory64 scalar boundary regression to actually test out-of-range address

* Fix Go formatting of memory64 bounds test table

* Fix escaped newline expectations in Memory64 scalar runtime regression

* Fix trailing comma in Memory64 test composite literal
2026-10-08 19:21:51 -07:00

84 lines
4.0 KiB
Go

package helpers
// Exhaustive smoke coverage for the memory64 helper family: every
// simd_m64_* / simd_p_m64_* helper is executed once over a live
// module with in-bounds arguments. The mem-op semantics are already
// specified by the wasm32 twins' behavioral tests (the m64 bodies
// differ only in address width); this drives the 64-bit
// address-computation paths, which nothing in-package referenced
// statically before.
import (
"testing"
)
func anyOf(vs ...any) any { return vs }
func call(f func() any) any { return f() }
func TestM64HelperSmoke(t *testing.T) {
m := memTestModule(t, 4096)
v := [2]uint64{0x1122334455667788, 0x99aabbccddeeff00}
_ = v
_ = call(func() any { return anyOf(simd_m64_scalar_i32_load16_u(m, 40)) })
_ = call(func() any { return anyOf(simd_m64_scalar_f32_load(m, 40)) })
_ = call(func() any { return anyOf(simd_m64_scalar_i32_shl(8, 8)) })
_ = call(func() any { return anyOf(simd_m64_scalar_i32_add(8, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load_rng(m, 40, 8, 8, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load_nc(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_store(m, 40, 8, v)) })
_ = call(func() any { return anyOf(simd_m64_v128_f16x4_cvt_store(m, 40, 8, v)) })
_ = call(func() any { return anyOf(simd_p_m64_v128_f16x4_cvt_store(m, 40, 8, 0 /*v0*/, 7)) })
_ = call(func() any { return anyOf(simd_m64_v128_load32_zero(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load64_zero(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load8_splat(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load16_splat(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load32_splat(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load64_splat(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_widen(m, 40, 8, 8, true)) })
_ = call(func() any { return anyOf(simd_m64_v128_load8x8_s(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load8x8_u(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load16x4_s(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load16x4_u(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load32x2_s(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load32x2_u(m, 40, 8)) })
_ = call(func() any { return anyOf(simd_m64_v128_load8_lane(m, 40, 8, 1, v)) })
_ = call(func() any { return anyOf(simd_m64_v128_load16_lane(m, 40, 8, 1, v)) })
_ = call(func() any { return anyOf(simd_m64_v128_load32_lane(m, 40, 8, 1, v)) })
_ = call(func() any { return anyOf(simd_m64_v128_load64_lane(m, 40, 8, 1, v)) })
_ = call(func() any { return anyOf(simd_m64_v128_store8_lane(m, 40, 8, 1, v)) })
_ = call(func() any { return anyOf(simd_m64_v128_store16_lane(m, 40, 8, 1, v)) })
_ = call(func() any { return anyOf(simd_m64_v128_store32_lane(m, 40, 8, 1, v)) })
_ = call(func() any { return anyOf(simd_m64_v128_store64_lane(m, 40, 8, 1, v)) })
_ = call(func() any { return anyOf(simd_p_m64_v128_store(m, 40, 8, 0 /*v0*/, 7)) })
_ = call(func() any { return anyOf(simd_p_m64_v128_store8_lane(m, 40, 8, 1, 0 /*v0*/, 7)) })
_ = call(func() any { return anyOf(simd_p_m64_v128_store16_lane(m, 40, 8, 1, 0 /*v0*/, 7)) })
_ = call(func() any { return anyOf(simd_p_m64_v128_store32_lane(m, 40, 8, 1, 0 /*v0*/, 7)) })
_ = call(func() any { return anyOf(simd_p_m64_v128_store64_lane(m, 40, 8, 1, 0 /*v0*/, 7)) })
}
func TestMem64CheckedEAOverflowAndWidth(t *testing.T) {
m := memTestModule(t, 4096)
if got := mem64CheckedEA(m, 32, 8, 8); got != 40 {
t.Fatalf("EA = %d, want 40", got)
}
for _, tc := range []struct {
addr, offset, width uint64
}{
{^uint64(0) - 31, 32, 8},
{^uint64(0), 0, 1},
{4095, 0, 2},
{4096, 1, 1},
} {
trapped := false
func() {
defer func() { trapped = recover() != nil }()
_ = mem64CheckedEA(m, tc.addr, tc.offset, tc.width)
}()
if !trapped {
t.Errorf("EA(%d,%d,%d) failed to trap", tc.addr, tc.offset, tc.width)
}
}
}