From 333a87a4dd1dc1387ae14f81862c2daba40e8bf7 Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Sat, 3 Oct 2026 20:04:02 +0000 Subject: [PATCH 1/2] fix(wasix): use strict LLVM memory semantics --- src/docs/internal/PERFORMANCE.md | 18 ++-- .../aot/aarch64-apple-darwin/build-support.rs | 8 +- .../build-support.rs | 8 +- .../x86_64-pc-windows-msvc/build-support.rs | 8 +- .../x86_64-unknown-linux-gnu/build-support.rs | 8 +- .../postmaster/executor/src/bin/compiler.rs | 14 ++-- src/wasix/postmaster/executor/src/sealed.rs | 6 +- .../postmaster/lib/build-sealed-carrier.mts | 2 +- src/wasix/postmaster/lib/common.sh | 2 +- src/wasix/postmaster/lib/common.test.sh | 2 +- src/wasix/postmaster/lib/sealed-carrier.sh | 2 +- .../postmaster/lib/verify-sealed-carrier.mts | 2 +- src/wasix/postmaster/wasmer/README.md | 5 +- ...009-strict-shared-memory-compilation.patch | 84 +++++++++++++++++++ .../postmaster/wasmer/patches/wasmer/series | 1 + src/wasix/postmaster/wasmer/tests.sh | 9 +- .../aot/aarch64-apple-darwin/build-support.rs | 8 +- .../build-support.rs | 8 +- .../x86_64-pc-windows-msvc/build-support.rs | 8 +- .../x86_64-unknown-linux-gnu/build-support.rs | 8 +- .../runtime/tools/wasix-aot-manifest.mts | 2 +- .../runtime/tools/wasix-aot-manifest.test.mts | 4 +- .../runtime/tools/xtask/src/aot_serializer.rs | 15 ++-- src/wasix/sdks/rust/src/oliphaunt/aot.rs | 4 +- 24 files changed, 162 insertions(+), 74 deletions(-) create mode 100644 src/wasix/postmaster/wasmer/patches/wasmer/0009-strict-shared-memory-compilation.patch diff --git a/src/docs/internal/PERFORMANCE.md b/src/docs/internal/PERFORMANCE.md index fdf4fffe2..3d8c5db5b 100644 --- a/src/docs/internal/PERFORMANCE.md +++ b/src/docs/internal/PERFORMANCE.md @@ -156,16 +156,14 @@ EH+PIC sysroot, including SIMD, relaxed SIMD, and extended const. Adding an extra `-msimd128` did not change the generated AOT artifact sizes in the local release experiment, so it is not carried as a project-specific flag. -Wasmer LLVM AOT is generated with the selected mainline codegen profile: -nonvolatile memory operations and a readonly funcref table. Local exact Oliphaunt -speed-suite measurements showed nonvolatile memory operations improving the -server SQLx suite by about 9% geomean. Adding the readonly funcref table on top -was about 1.4% faster geomean than nonvolatile-only and improved the indexed -update cases (`557.152ms -> 534.737ms` and `695.663ms -> 681.778ms`), while -regressing CREATE INDEX and DROP TABLE cases. Wasmer documents nonvolatile -memory operations as faster but not fully WebAssembly-spec compliant; this is a -conscious mainline runtime-profile decision for the packaged single-process -Postgres runtime and must stay covered by the correctness matrix. +Wasmer LLVM AOT uses the fixed `llvm-opta-ro_ftable` profile: spec-compliant +memory operations and the existing readonly funcref optimization. Disabling +the previous nonvolatile-memory optimization preserves Wasm memory semantics +but can increase query latency. Compiler policy is not a consumer runtime knob; +conflicting build-time overrides are rejected. + +The profile is part of the artifact identity. Rebuild AOT artifacts when it +changes; legacy nonvolatile artifacts cannot be relabelled as strict. WebAssembly exceptions are mandatory for production artifacts. The Postgres runtime depends on exception/longjmp recovery across the main module and side diff --git a/src/wasix/postgres-tools/crates/aot/aarch64-apple-darwin/build-support.rs b/src/wasix/postgres-tools/crates/aot/aarch64-apple-darwin/build-support.rs index 38f078a56..29ffc520b 100644 --- a/src/wasix/postgres-tools/crates/aot/aarch64-apple-darwin/build-support.rs +++ b/src/wasix/postgres-tools/crates/aot/aarch64-apple-darwin/build-support.rs @@ -162,7 +162,7 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { let text = format!( "pub const TARGET_TRIPLE: &str = {:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = true;\n\ pub const MANIFEST_JSON: &str = include_str!({});\n\ #[rustfmt::skip]\n\ @@ -188,11 +188,11 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { fn write_source_only_aot(out: &Path, target: &str) { let manifest = format!( - "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" + "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta-ro_ftable\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" ); let text = format!( "pub const TARGET_TRIPLE: &str = {target:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = false;\n\ pub const MANIFEST_JSON: &str = r#\"{manifest}\"#;\n\ pub fn artifact_bytes(_name: &str) -> Option<&'static [u8]> {{ None }}\n" @@ -233,7 +233,7 @@ fn write_core_aot_manifest(source: &Path, destination: &Path) -> Vec { serde_json::from_str(&text).expect("parse generated WASIX AOT manifest"); assert_eq!( manifest.get("engine").and_then(serde_json::Value::as_str), - Some("llvm-opta"), + Some("llvm-opta-ro_ftable"), "stale WASIX AOT profile; rebuild artifacts before compiling the carrier" ); let artifacts = manifest diff --git a/src/wasix/postgres-tools/crates/aot/aarch64-unknown-linux-gnu/build-support.rs b/src/wasix/postgres-tools/crates/aot/aarch64-unknown-linux-gnu/build-support.rs index 38f078a56..29ffc520b 100644 --- a/src/wasix/postgres-tools/crates/aot/aarch64-unknown-linux-gnu/build-support.rs +++ b/src/wasix/postgres-tools/crates/aot/aarch64-unknown-linux-gnu/build-support.rs @@ -162,7 +162,7 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { let text = format!( "pub const TARGET_TRIPLE: &str = {:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = true;\n\ pub const MANIFEST_JSON: &str = include_str!({});\n\ #[rustfmt::skip]\n\ @@ -188,11 +188,11 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { fn write_source_only_aot(out: &Path, target: &str) { let manifest = format!( - "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" + "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta-ro_ftable\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" ); let text = format!( "pub const TARGET_TRIPLE: &str = {target:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = false;\n\ pub const MANIFEST_JSON: &str = r#\"{manifest}\"#;\n\ pub fn artifact_bytes(_name: &str) -> Option<&'static [u8]> {{ None }}\n" @@ -233,7 +233,7 @@ fn write_core_aot_manifest(source: &Path, destination: &Path) -> Vec { serde_json::from_str(&text).expect("parse generated WASIX AOT manifest"); assert_eq!( manifest.get("engine").and_then(serde_json::Value::as_str), - Some("llvm-opta"), + Some("llvm-opta-ro_ftable"), "stale WASIX AOT profile; rebuild artifacts before compiling the carrier" ); let artifacts = manifest diff --git a/src/wasix/postgres-tools/crates/aot/x86_64-pc-windows-msvc/build-support.rs b/src/wasix/postgres-tools/crates/aot/x86_64-pc-windows-msvc/build-support.rs index 38f078a56..29ffc520b 100644 --- a/src/wasix/postgres-tools/crates/aot/x86_64-pc-windows-msvc/build-support.rs +++ b/src/wasix/postgres-tools/crates/aot/x86_64-pc-windows-msvc/build-support.rs @@ -162,7 +162,7 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { let text = format!( "pub const TARGET_TRIPLE: &str = {:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = true;\n\ pub const MANIFEST_JSON: &str = include_str!({});\n\ #[rustfmt::skip]\n\ @@ -188,11 +188,11 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { fn write_source_only_aot(out: &Path, target: &str) { let manifest = format!( - "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" + "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta-ro_ftable\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" ); let text = format!( "pub const TARGET_TRIPLE: &str = {target:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = false;\n\ pub const MANIFEST_JSON: &str = r#\"{manifest}\"#;\n\ pub fn artifact_bytes(_name: &str) -> Option<&'static [u8]> {{ None }}\n" @@ -233,7 +233,7 @@ fn write_core_aot_manifest(source: &Path, destination: &Path) -> Vec { serde_json::from_str(&text).expect("parse generated WASIX AOT manifest"); assert_eq!( manifest.get("engine").and_then(serde_json::Value::as_str), - Some("llvm-opta"), + Some("llvm-opta-ro_ftable"), "stale WASIX AOT profile; rebuild artifacts before compiling the carrier" ); let artifacts = manifest diff --git a/src/wasix/postgres-tools/crates/aot/x86_64-unknown-linux-gnu/build-support.rs b/src/wasix/postgres-tools/crates/aot/x86_64-unknown-linux-gnu/build-support.rs index 38f078a56..29ffc520b 100644 --- a/src/wasix/postgres-tools/crates/aot/x86_64-unknown-linux-gnu/build-support.rs +++ b/src/wasix/postgres-tools/crates/aot/x86_64-unknown-linux-gnu/build-support.rs @@ -162,7 +162,7 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { let text = format!( "pub const TARGET_TRIPLE: &str = {:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = true;\n\ pub const MANIFEST_JSON: &str = include_str!({});\n\ #[rustfmt::skip]\n\ @@ -188,11 +188,11 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { fn write_source_only_aot(out: &Path, target: &str) { let manifest = format!( - "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" + "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta-ro_ftable\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" ); let text = format!( "pub const TARGET_TRIPLE: &str = {target:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = false;\n\ pub const MANIFEST_JSON: &str = r#\"{manifest}\"#;\n\ pub fn artifact_bytes(_name: &str) -> Option<&'static [u8]> {{ None }}\n" @@ -233,7 +233,7 @@ fn write_core_aot_manifest(source: &Path, destination: &Path) -> Vec { serde_json::from_str(&text).expect("parse generated WASIX AOT manifest"); assert_eq!( manifest.get("engine").and_then(serde_json::Value::as_str), - Some("llvm-opta"), + Some("llvm-opta-ro_ftable"), "stale WASIX AOT profile; rebuild artifacts before compiling the carrier" ); let artifacts = manifest diff --git a/src/wasix/postmaster/executor/src/bin/compiler.rs b/src/wasix/postmaster/executor/src/bin/compiler.rs index 0ee2d713f..461e9240d 100644 --- a/src/wasix/postmaster/executor/src/bin/compiler.rs +++ b/src/wasix/postmaster/executor/src/bin/compiler.rs @@ -108,10 +108,10 @@ fn parse() -> Result> { fn product_compiler() -> LLVM { let mut compiler = LLVM::new(); - // Retain main's policy; strict shared-memory compilation is a separate change. + // Postmaster shares guest memory across concurrently running threads. compiler .opt_level(LLVMOptLevel::Aggressive) - .non_volatile_memops(true) + .non_volatile_memops(false) .readonly_funcref_table(true); compiler } @@ -213,11 +213,11 @@ fn verify_aot(module_path: PathBuf, artifact_path: PathBuf) -> Result<()> { } #[test] -fn product_compiler_uses_main_memory_identity() { - let relaxed_id = Box::new(product_compiler()).compiler().deterministic_id(); - let mut strict = product_compiler(); - strict.non_volatile_memops(false); - let strict_id = Box::new(strict).compiler().deterministic_id(); +fn product_compiler_uses_strict_memory_identity() { + let strict_id = Box::new(product_compiler()).compiler().deterministic_id(); + let mut relaxed = product_compiler(); + relaxed.non_volatile_memops(true); + let relaxed_id = Box::new(relaxed).compiler().deterministic_id(); assert!(strict_id.contains("-nv0-")); assert!(relaxed_id.contains("-nv1-")); assert_ne!(strict_id, relaxed_id); diff --git a/src/wasix/postmaster/executor/src/sealed.rs b/src/wasix/postmaster/executor/src/sealed.rs index d92c985c9..62f404f8e 100644 --- a/src/wasix/postmaster/executor/src/sealed.rs +++ b/src/wasix/postmaster/executor/src/sealed.rs @@ -1813,8 +1813,8 @@ fn validate_manifest_identity(manifest: &SealedManifest, engine: &Engine) -> Res Target::default().triple() ); ensure!( - manifest.engine == "llvm-opta", - "sealed manifest producer engine must be 'llvm-opta'" + manifest.engine == "llvm-opta-ro_ftable", + "sealed manifest producer engine must be 'llvm-opta-ro_ftable'" ); ensure_nonempty("compiler-config", &manifest.compiler_config)?; ensure!( @@ -2545,7 +2545,7 @@ mod tests { postgres_version: "18.4".to_string(), target_triple: "test-target".to_string(), host_abi: "test-abi".to_string(), - engine: "llvm-opta".to_string(), + engine: "llvm-opta-ro_ftable".to_string(), compiler_config: "test-compiler".to_string(), cpu_policy: "generic-baseline".to_string(), cpu_features: Vec::new(), diff --git a/src/wasix/postmaster/lib/build-sealed-carrier.mts b/src/wasix/postmaster/lib/build-sealed-carrier.mts index f8bc91e53..44cb375da 100644 --- a/src/wasix/postmaster/lib/build-sealed-carrier.mts +++ b/src/wasix/postmaster/lib/build-sealed-carrier.mts @@ -109,7 +109,7 @@ function manifest(args: string[]) { 'postgres-version': pg, 'target-triple': target, 'host-abi': abi, - engine: 'llvm-opta', + engine: 'llvm-opta-ro_ftable', 'compiler-config': config, 'cpu-policy': 'generic-baseline', 'cpu-features': [], diff --git a/src/wasix/postmaster/lib/common.sh b/src/wasix/postmaster/lib/common.sh index 095fbe490..59f8b6941 100644 --- a/src/wasix/postmaster/lib/common.sh +++ b/src/wasix/postmaster/lib/common.sh @@ -1603,7 +1603,7 @@ fresh_wasmer_compiler_cache_bucket() { case "$(fresh_normalize_wasmer_compiler "$compiler")" in llvm) - printf 'llvm-%s-v%s\n' "$(fresh_wasmer_llvm_opt_suffix "$llvm_opt_level")" "$artifact_version" + printf 'llvm-%s-ro_ftable-v%s\n' "$(fresh_wasmer_llvm_opt_suffix "$llvm_opt_level")" "$artifact_version" ;; esac } diff --git a/src/wasix/postmaster/lib/common.test.sh b/src/wasix/postmaster/lib/common.test.sh index 42029235e..d5d519509 100644 --- a/src/wasix/postmaster/lib/common.test.sh +++ b/src/wasix/postmaster/lib/common.test.sh @@ -817,7 +817,7 @@ write_postmaster_executor_receipt default_cache_dir="$(fresh_wasmer_cache_dir "$FRESH_UPSTREAM_WASMER_BIN")" default_cache_bucket="$(fresh_wasmer_compiler_cache_bucket llvm aggressive 21)" [ -n "$default_cache_dir" ] -[ "$default_cache_bucket" = llvm-opta-v21 ] +[ "$default_cache_bucket" = llvm-opta-ro_ftable-v21 ] mv "$WASMER_BUILD_RECEIPT" "$test_root/receipt.saved" expect_failure fresh_require_patched_wasmer "$FRESH_UPSTREAM_WASMER_BIN" diff --git a/src/wasix/postmaster/lib/sealed-carrier.sh b/src/wasix/postmaster/lib/sealed-carrier.sh index 41c227118..1d6e3633c 100644 --- a/src/wasix/postmaster/lib/sealed-carrier.sh +++ b/src/wasix/postmaster/lib/sealed-carrier.sh @@ -155,7 +155,7 @@ fresh_aot_producer_recipe_sha256() { for guest_input in "${verifier_inputs[@]}"; do printf '%s\0%s\0' verifier-input-sha256 "$(fresh_wasmer_bin_hash "$guest_input")" done - printf '%s\0%s\0' producer-engine llvm-opta + printf '%s\0%s\0' producer-engine llvm-opta-ro_ftable printf '%s\0%s\0' compiler-config "$compiler_config" printf '%s\0%s\0' target-triple "$target_triple" printf '%s\0%s\0' cpu-policy generic-baseline diff --git a/src/wasix/postmaster/lib/verify-sealed-carrier.mts b/src/wasix/postmaster/lib/verify-sealed-carrier.mts index 2b8dad39c..c0aaa7581 100644 --- a/src/wasix/postmaster/lib/verify-sealed-carrier.mts +++ b/src/wasix/postmaster/lib/verify-sealed-carrier.mts @@ -362,7 +362,7 @@ export function verify( 'postgres-version': pgVersion, 'target-triple': wasmer.rustc_host, 'host-abi': wasmer.host_abi, - engine: 'llvm-opta', + engine: 'llvm-opta-ro_ftable', 'cpu-policy': 'generic-baseline', 'cpu-features': [], 'wasmer-version': wasmerVersion, diff --git a/src/wasix/postmaster/wasmer/README.md b/src/wasix/postmaster/wasmer/README.md index e9c310625..93e0f62fb 100644 --- a/src/wasix/postmaster/wasmer/README.md +++ b/src/wasix/postmaster/wasmer/README.md @@ -28,8 +28,9 @@ hashes. Runtime selection never falls back to a stock or `PATH` Wasmer. The ordered `series` files, not directory globs, select patches. Their digest includes the manifest, member names and contents; editing or reordering a patch invalidates receipts. The product executor lives in `../executor`. -The compiler and verifier use the nonvolatile-memory profile. Compiler policy -changes require rebuilt carriers with matching identities. +Patch 0009 separately disables LLVM nonvolatile memory operations for shared +guest memory; the product compiler and artifact verifier use the same strict +policy. Carriers and AOT artifacts must be rebuilt, never relabelled. The libc series separates mapping, file, socket, process, exception and resource contracts. Its `sigsetjmp` fix evaluates the buffer expression once in the live diff --git a/src/wasix/postmaster/wasmer/patches/wasmer/0009-strict-shared-memory-compilation.patch b/src/wasix/postmaster/wasmer/patches/wasmer/0009-strict-shared-memory-compilation.patch new file mode 100644 index 000000000..208a4df88 --- /dev/null +++ b/src/wasix/postmaster/wasmer/patches/wasmer/0009-strict-shared-memory-compilation.patch @@ -0,0 +1,84 @@ +From: Oliphaunt Maintainers +Date: Mon, 7 Sep 2026 00:00:00 +0000 +Subject: [PATCH 9/9] Keep concurrent Postmaster LLVM memory operations strict + +Postmaster shares guest linear memory across threads and processes. Enabling +non-volatile memory operations promises an isolation guarantee that this +runtime does not have. Use the conservative LLVM setting in the product AOT +producer/verifier and both generic CLI compilation routes. This patch changes +the CLI routes; the first-party executor applies the same policy directly. Keep the existing +disable option accepted but hidden for caller compatibility; add no new knob. + +This is an explicit correctness change AFTER the source-equivalent bundle +split in patches 0001-0008, not part of that equivalence claim. Producer and +verifier share one fixed configuration. Tests require nv0 deterministic +compiler identities and distinguish the previously relaxed nv1 identity. +The ordered patch digest changes runtime ABI/receipts; the changed compiler +binary changes the AOT cache root. Old compiled carriers must be rebuilt. + +The strict LLVM policy is generally applicable to shared guest memory; +product compiler plumbing and receipt requirements are Oliphaunt-specific. +No performance win or fresh concurrent-runtime qualification is claimed here. + +diff --git a/lib/cli/src/backend.rs b/lib/cli/src/backend.rs +index 17fe4c9..63c2144 100644 +--- a/lib/cli/src/backend.rs ++++ b/lib/cli/src/backend.rs +@@ -170,11 +170,9 @@ pub struct RuntimeOptions { + #[clap(long = "enable-nan-canonicalization")] + enable_nan_canonicalization: bool, + +- /// Disable LLVM non-volatile memory operations. +- /// +- /// Available for LLVM. ++ /// Deprecated compatibility option: this runtime always uses strict LLVM memory operations. + #[cfg(feature = "llvm")] +- #[clap(long = "disable-non-volatile-memops")] ++ #[clap(long = "disable-non-volatile-memops", hide = true)] + disable_non_volatile_memops: bool, + + #[clap(flatten)] +@@ -480,9 +478,7 @@ impl RuntimeOptions { + use wasmer_compiler_llvm::LLVMCallbacks; + use wasmer_types::entity::EntityRef; + let mut config = LLVM::new(); +- if !self.disable_non_volatile_memops { +- config.enable_non_volatile_memops(); +- } ++ config.non_volatile_memops(false); + config.enable_readonly_funcref_table(); + + if let Some(num_threads) = self.compiler_threads { +@@ -631,9 +627,7 @@ impl BackendType { + use wasmer_types::entity::EntityRef; + + let mut config = wasmer_compiler_llvm::LLVM::new(); +- if !runtime_opts.disable_non_volatile_memops { +- config.enable_non_volatile_memops(); +- } ++ config.non_volatile_memops(false); + config.enable_readonly_funcref_table(); + + let supported_features = config.supported_features_for_target(target); +@@ -751,3 +745,21 @@ impl std::fmt::Display for BackendType { + ) + } + } ++ ++#[cfg(all(test, feature = "llvm"))] ++mod tests { ++ use super::*; ++ use clap::Parser; ++ ++ #[test] ++ fn llvm_cli_routes_use_strict_memory_identity() { ++ let target = Target::default(); ++ for arguments in [vec!["wasmer"], vec!["wasmer", "--disable-non-volatile-memops"]] { ++ let options = RuntimeOptions::try_parse_from(arguments).unwrap(); ++ let compiler = options.get_sys_compiler_config(&BackendType::LLVM).unwrap(); ++ assert!(compiler.compiler().deterministic_id().contains("-nv0-")); ++ let engine = BackendType::LLVM.get_engine(&target, &options).unwrap(); ++ assert!(engine.deterministic_id().contains("-nv0-")); ++ } ++ } ++} diff --git a/src/wasix/postmaster/wasmer/patches/wasmer/series b/src/wasix/postmaster/wasmer/patches/wasmer/series index af56dbf83..3676881df 100644 --- a/src/wasix/postmaster/wasmer/patches/wasmer/series +++ b/src/wasix/postmaster/wasmer/patches/wasmer/series @@ -6,3 +6,4 @@ 0006-wasix-epoll-and-socket-readiness.patch 0007-wasix-instance-linker-and-sealed-runtime.patch 0008-postmaster-executor-and-build-closure.patch +0009-strict-shared-memory-compilation.patch diff --git a/src/wasix/postmaster/wasmer/tests.sh b/src/wasix/postmaster/wasmer/tests.sh index 0a46c4489..55263c3ef 100644 --- a/src/wasix/postmaster/wasmer/tests.sh +++ b/src/wasix/postmaster/wasmer/tests.sh @@ -224,10 +224,15 @@ run_tests \ -- \ memory_profile::wasm_tool::tests -# The product compiler must preserve main's policy and distinguish strict AOT. +# run_tests rejects an empty selection; both producer and generic CLI routes +# must bind artifacts to the strict compiler identity. run_tests --locked --target-dir "$POSTMASTER_COMPILER_TARGET_DIR" \ --manifest-path "$FRESH_ROOT/executor/Cargo.toml" \ --package "$FRESH_POSTMASTER_EXECUTOR_PACKAGE" \ --bin "$FRESH_POSTMASTER_COMPILER_BINARY" \ --no-default-features --features "$FRESH_POSTMASTER_COMPILER_FEATURES" \ - -- --exact product_compiler_uses_main_memory_identity + -- --exact product_compiler_uses_strict_memory_identity +run_tests --locked --target-dir "$WASMER_TARGET_DIR" \ + --manifest-path "$WASMER_ROOT/lib/cli/Cargo.toml" --lib \ + --no-default-features --features "$FRESH_WASMER_COMPILER_FEATURES" \ + -- --exact backend::tests::llvm_cli_routes_use_strict_memory_identity diff --git a/src/wasix/runtime/crates/aot/aarch64-apple-darwin/build-support.rs b/src/wasix/runtime/crates/aot/aarch64-apple-darwin/build-support.rs index 7de9cfe54..09105cad3 100644 --- a/src/wasix/runtime/crates/aot/aarch64-apple-darwin/build-support.rs +++ b/src/wasix/runtime/crates/aot/aarch64-apple-darwin/build-support.rs @@ -156,7 +156,7 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { let text = format!( "pub const TARGET_TRIPLE: &str = {:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = true;\n\ pub const MANIFEST_JSON: &str = include_str!({});\n\ #[rustfmt::skip]\n\ @@ -182,11 +182,11 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { fn write_source_only_aot(out: &Path, target: &str) { let manifest = format!( - "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" + "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta-ro_ftable\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" ); let text = format!( "pub const TARGET_TRIPLE: &str = {target:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = false;\n\ pub const MANIFEST_JSON: &str = r#\"{manifest}\"#;\n\ pub fn artifact_bytes(_name: &str) -> Option<&'static [u8]> {{ None }}\n" @@ -227,7 +227,7 @@ fn write_core_aot_manifest(source: &Path, destination: &Path) -> Vec { serde_json::from_str(&text).expect("parse generated WASIX AOT manifest"); assert_eq!( manifest.get("engine").and_then(serde_json::Value::as_str), - Some("llvm-opta"), + Some("llvm-opta-ro_ftable"), "stale WASIX AOT profile; rebuild artifacts before compiling the carrier" ); let artifacts = manifest diff --git a/src/wasix/runtime/crates/aot/aarch64-unknown-linux-gnu/build-support.rs b/src/wasix/runtime/crates/aot/aarch64-unknown-linux-gnu/build-support.rs index 7de9cfe54..09105cad3 100644 --- a/src/wasix/runtime/crates/aot/aarch64-unknown-linux-gnu/build-support.rs +++ b/src/wasix/runtime/crates/aot/aarch64-unknown-linux-gnu/build-support.rs @@ -156,7 +156,7 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { let text = format!( "pub const TARGET_TRIPLE: &str = {:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = true;\n\ pub const MANIFEST_JSON: &str = include_str!({});\n\ #[rustfmt::skip]\n\ @@ -182,11 +182,11 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { fn write_source_only_aot(out: &Path, target: &str) { let manifest = format!( - "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" + "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta-ro_ftable\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" ); let text = format!( "pub const TARGET_TRIPLE: &str = {target:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = false;\n\ pub const MANIFEST_JSON: &str = r#\"{manifest}\"#;\n\ pub fn artifact_bytes(_name: &str) -> Option<&'static [u8]> {{ None }}\n" @@ -227,7 +227,7 @@ fn write_core_aot_manifest(source: &Path, destination: &Path) -> Vec { serde_json::from_str(&text).expect("parse generated WASIX AOT manifest"); assert_eq!( manifest.get("engine").and_then(serde_json::Value::as_str), - Some("llvm-opta"), + Some("llvm-opta-ro_ftable"), "stale WASIX AOT profile; rebuild artifacts before compiling the carrier" ); let artifacts = manifest diff --git a/src/wasix/runtime/crates/aot/x86_64-pc-windows-msvc/build-support.rs b/src/wasix/runtime/crates/aot/x86_64-pc-windows-msvc/build-support.rs index 7de9cfe54..09105cad3 100644 --- a/src/wasix/runtime/crates/aot/x86_64-pc-windows-msvc/build-support.rs +++ b/src/wasix/runtime/crates/aot/x86_64-pc-windows-msvc/build-support.rs @@ -156,7 +156,7 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { let text = format!( "pub const TARGET_TRIPLE: &str = {:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = true;\n\ pub const MANIFEST_JSON: &str = include_str!({});\n\ #[rustfmt::skip]\n\ @@ -182,11 +182,11 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { fn write_source_only_aot(out: &Path, target: &str) { let manifest = format!( - "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" + "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta-ro_ftable\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" ); let text = format!( "pub const TARGET_TRIPLE: &str = {target:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = false;\n\ pub const MANIFEST_JSON: &str = r#\"{manifest}\"#;\n\ pub fn artifact_bytes(_name: &str) -> Option<&'static [u8]> {{ None }}\n" @@ -227,7 +227,7 @@ fn write_core_aot_manifest(source: &Path, destination: &Path) -> Vec { serde_json::from_str(&text).expect("parse generated WASIX AOT manifest"); assert_eq!( manifest.get("engine").and_then(serde_json::Value::as_str), - Some("llvm-opta"), + Some("llvm-opta-ro_ftable"), "stale WASIX AOT profile; rebuild artifacts before compiling the carrier" ); let artifacts = manifest diff --git a/src/wasix/runtime/crates/aot/x86_64-unknown-linux-gnu/build-support.rs b/src/wasix/runtime/crates/aot/x86_64-unknown-linux-gnu/build-support.rs index 7de9cfe54..09105cad3 100644 --- a/src/wasix/runtime/crates/aot/x86_64-unknown-linux-gnu/build-support.rs +++ b/src/wasix/runtime/crates/aot/x86_64-unknown-linux-gnu/build-support.rs @@ -156,7 +156,7 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { let text = format!( "pub const TARGET_TRIPLE: &str = {:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = true;\n\ pub const MANIFEST_JSON: &str = include_str!({});\n\ #[rustfmt::skip]\n\ @@ -182,11 +182,11 @@ fn write_generated_aot(out: &Path, target: &str, artifact_dir: &Path) { fn write_source_only_aot(out: &Path, target: &str) { let manifest = format!( - "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" + "{{\"format-version\":1,\"target-triple\":{target:?},\"engine\":\"llvm-opta-ro_ftable\",\"wasmer-version\":\"7.2.1\",\"wasmer-wasix-version\":\"0.702.1\",\"artifacts\":[]}}" ); let text = format!( "pub const TARGET_TRIPLE: &str = {target:?};\n\ - pub const ENGINE: &str = \"llvm-opta\";\n\ + pub const ENGINE: &str = \"llvm-opta-ro_ftable\";\n\ pub const HAS_EMBEDDED_AOT: bool = false;\n\ pub const MANIFEST_JSON: &str = r#\"{manifest}\"#;\n\ pub fn artifact_bytes(_name: &str) -> Option<&'static [u8]> {{ None }}\n" @@ -227,7 +227,7 @@ fn write_core_aot_manifest(source: &Path, destination: &Path) -> Vec { serde_json::from_str(&text).expect("parse generated WASIX AOT manifest"); assert_eq!( manifest.get("engine").and_then(serde_json::Value::as_str), - Some("llvm-opta"), + Some("llvm-opta-ro_ftable"), "stale WASIX AOT profile; rebuild artifacts before compiling the carrier" ); let artifacts = manifest diff --git a/src/wasix/runtime/tools/wasix-aot-manifest.mts b/src/wasix/runtime/tools/wasix-aot-manifest.mts index e81559ba5..e2da8149c 100644 --- a/src/wasix/runtime/tools/wasix-aot-manifest.mts +++ b/src/wasix/runtime/tools/wasix-aot-manifest.mts @@ -6,7 +6,7 @@ import { export { WASIX_TOOLCHAIN_PATH }; export const STABLE_WASIX_SOURCE_LANE = 'stable'; -export const WASIX_AOT_ENGINE = 'llvm-opta'; +export const WASIX_AOT_ENGINE = 'llvm-opta-ro_ftable'; function requiredString(value, context) { if (typeof value !== 'string' || value.length === 0) { diff --git a/src/wasix/runtime/tools/wasix-aot-manifest.test.mts b/src/wasix/runtime/tools/wasix-aot-manifest.test.mts index 5705db1c8..2744644a6 100644 --- a/src/wasix/runtime/tools/wasix-aot-manifest.test.mts +++ b/src/wasix/runtime/tools/wasix-aot-manifest.test.mts @@ -29,9 +29,9 @@ test('accepts AOT metadata that exactly matches the canonical WASIX toolchain', ); }); -test('rejects artifacts compiled under a different memory-codegen profile', () => { +test('rejects legacy artifacts instead of relabeling their memory-codegen profile', () => { assert.throws( - () => assertCanonicalWasixAotManifest(manifest({ engine: 'llvm-opta-ro_ftable' })), + () => assertCanonicalWasixAotManifest(manifest({ engine: 'llvm-opta' })), /engine must match canonical WASIX metadata/u, ); }); diff --git a/src/wasix/runtime/tools/xtask/src/aot_serializer.rs b/src/wasix/runtime/tools/xtask/src/aot_serializer.rs index 647407b9d..434da3338 100644 --- a/src/wasix/runtime/tools/xtask/src/aot_serializer.rs +++ b/src/wasix/runtime/tools/xtask/src/aot_serializer.rs @@ -18,11 +18,11 @@ use crate::value_after; // Wasmer 7.2.1's deterministic_id omits these codegen choices. Keep our // artifact identity explicit; never label strict and nonvolatile code alike. -pub(crate) const AOT_ENGINE_PROFILE: &str = "llvm-opta"; +pub(crate) const AOT_ENGINE_PROFILE: &str = "llvm-opta-ro_ftable"; pub(crate) fn check_aot_codegen_environment() -> Result<()> { for (name, expected) in [ - ("OLIPHAUNT_WASM_AOT_NON_VOLATILE_MEMOPS", true), + ("OLIPHAUNT_WASM_AOT_NON_VOLATILE_MEMOPS", false), ("OLIPHAUNT_WASM_AOT_READONLY_FUNCREF_TABLE", true), ] { match std::env::var(name) { @@ -141,9 +141,8 @@ fn llvm_aot_engine() -> wasmer::Engine { if env_flag("OLIPHAUNT_WASM_WASMER_PERFMAP") { llvm.enable_perfmap(); } - // Retain main's codegen policy here; strict memory semantics are a separate - // correctness/performance change, not part of patch consolidation. - llvm.enable_non_volatile_memops(); + // Preserve Wasmer's spec-compliant memory operations. Nonvolatile memops + // are not safe merely because a PostgreSQL instance has one backend. llvm.enable_readonly_funcref_table(); EngineBuilder::new(llvm) .set_target(Some(portable_aot_target())) @@ -184,7 +183,7 @@ fn print_aot_engine_config(engine: &wasmer::Engine) { ); println!("wasmer-feature-exceptions: enabled"); println!("wasmer-llvm-target-cpu: generic"); - println!("wasmer-llvm-non-volatile-memops: enabled"); + println!("wasmer-llvm-non-volatile-memops: disabled"); println!("wasmer-llvm-readonly-funcref-table: enabled"); } @@ -222,8 +221,8 @@ mod tests { use super::*; #[test] - fn fixed_codegen_profile_rejects_conflicting_and_ambiguous_overrides() { - assert_eq!(AOT_ENGINE_PROFILE, "llvm-opta"); + fn fixed_codegen_profile_rejects_unsafe_and_ambiguous_overrides() { + assert_ne!(AOT_ENGINE_PROFILE, "llvm-opta"); for expected in [false, true] { validate_profile_override("test", None, expected).unwrap(); validate_profile_override("test", Some(if expected { "1" } else { "0" }), expected) diff --git a/src/wasix/sdks/rust/src/oliphaunt/aot.rs b/src/wasix/sdks/rust/src/oliphaunt/aot.rs index a73117026..0beccaba9 100644 --- a/src/wasix/sdks/rust/src/oliphaunt/aot.rs +++ b/src/wasix/sdks/rust/src/oliphaunt/aot.rs @@ -15,12 +15,12 @@ use zstd::stream::read::Decoder as ZstdDecoder; use super::assets; const RUNTIME_ARTIFACT: &str = "runtime:oliphaunt"; -const EXPECTED_AOT_ENGINE: &str = "llvm-opta"; +const EXPECTED_AOT_ENGINE: &str = "llvm-opta-ro_ftable"; const EXPECTED_WASMER_VERSION: &str = "7.2.1"; const EXPECTED_WASMER_WASIX_VERSION: &str = "0.702.1"; const AOT_ENGINE_ID: &str = concat!( "engine=", - "llvm-opta", + "llvm-opta-ro_ftable", ";wasmer=", "7.2.1", ";wasmer-wasix=", From 14326fe818cc5a702a8ab568aa106dadfe7b2fd6 Mon Sep 17 00:00:00 2001 From: Sid Jain Date: Sun, 4 Oct 2026 23:10:03 +0000 Subject: [PATCH 2/2] chore(patches): use consistent author for strict memory policy --- .../patches/wasmer/0009-strict-shared-memory-compilation.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasix/postmaster/wasmer/patches/wasmer/0009-strict-shared-memory-compilation.patch b/src/wasix/postmaster/wasmer/patches/wasmer/0009-strict-shared-memory-compilation.patch index 208a4df88..6dffbe8f4 100644 --- a/src/wasix/postmaster/wasmer/patches/wasmer/0009-strict-shared-memory-compilation.patch +++ b/src/wasix/postmaster/wasmer/patches/wasmer/0009-strict-shared-memory-compilation.patch @@ -1,4 +1,4 @@ -From: Oliphaunt Maintainers +From: Sid Jain Date: Mon, 7 Sep 2026 00:00:00 +0000 Subject: [PATCH 9/9] Keep concurrent Postmaster LLVM memory operations strict