fix(wasm): what the review found

-flto in a wasm configuration's compileFlags or linkFlags reached the
link, where LTO code generation runs without the backend options that
keep exception handling: every landing pad was dropped, and the build
succeeded with throws that escaped their catch blocks. -fno-exceptions
there made every `import std;` fail on the std module built with
exceptions, and a wasm shared library failed to link against the eh/
libc++, which is static archives built without -fPIC. Build() refuses
all three now, each with a line that says why, before it makes a
directory or starts a thread.

The sysroot check sat in BuildStdPcm, which the linter calls as well.
There the error only dropped the compile command, so lint ran no AST
rule on a wasm configuration and reported it clean. It also refused
static libraries, which never link, fired after the shader and
external threads had started, and called a missing sysroot, or one
without the target, "no C++ exception support". It is part of the same
early check now, which first says when the sysroot or the target's
directory is missing, and asks for libunwind only where something
links.

C sources got only the signal.h define. setjmp.h refused to compile in
C, and a C object given -wasm-enable-sjlj through compileFlags used the
legacy exception encoding next to C++ objects in the standard one, a
mix engines refuse to load. They get WasmCompileFlags now, like the C++
units, a variant pass's flags included.

The baseline probes include simd: V8 and SpiderMonkey switch SIMD off
on x86 CPUs without SSE4.1, which virtual machines often present, and
such an engine passed the exception-handling probe only to fail
compiling the module; the manifest tests expect it on every entry. The
Flatpak pins WASI_SDK_EXCEPTIONS=DUAL, which
wasi-sdk 34 defaults to only with clang 23 or newer, and checks that
the eh/ libunwind got installed: the wasm tests skip without it, so CI
would otherwise pass a Flatpak whose every wasm build fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-10-31 06:10:41 +01:00
commit 45b9f5cbb7
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
7 changed files with 103 additions and 42 deletions

View file

@ -12,12 +12,12 @@ import :Agents;
namespace fs = std::filesystem;
namespace Crafter {
// What every wasm32 C++ translation unit is compiled with, and the std
// module it imports. A BMI cannot be loaded by a unit whose options differ
// from the ones that wrote it, so GetCompileCommand and BuildStdPcm both
// take the set from here (through WasmCompileFlags), and VariantId and
// StdPcmDir hash it so that a crafter-build which changes it never reuses
// what the old set compiled.
// What every wasm32 translation unit is compiled with, C or C++, and the
// std module the C++ ones import. A BMI cannot be loaded by a unit whose
// options differ from the ones that wrote it, so GetCompileCommand and
// BuildStdPcm both take the set from here (through WasmCompileFlags), and
// VariantId and StdPcmDir hash it so that a crafter-build which changes
// it never reuses what the old set compiled.
//
// -fwasm-exceptions compiles C++ exceptions to WebAssembly exception
// handling. It also selects the sysroot's include/<triple>/eh and
@ -34,9 +34,10 @@ namespace Crafter {
// The wasi-runtime/runtime.js probes an engine has to pass to run anything
// built with WasmBaselineFlags; EnableWasiBrowserRuntime puts them on every
// entry of variants.json. Exception handling with exnref is the newest
// feature those flags need (Chrome 137, Firefox 131, Safari 18.4), so an
// engine that has it has SIMD128 and the rest as well.
inline constexpr auto WasmBaselineProbes = std::to_array<std::string_view>({"exception-handling"});
// feature those flags need (Chrome 137, Firefox 131, Safari 18.4). SIMD128
// is older, but V8 and SpiderMonkey switch it off on x86 CPUs without
// SSE4.1, which virtual machines often present.
inline constexpr auto WasmBaselineProbes = std::to_array<std::string_view>({"simd", "exception-handling"});
}
export namespace Crafter {
@ -750,7 +751,8 @@ export namespace Crafter {
// it only to engines that report relaxed-SIMD support (Chrome 114+, Firefox
// 120+) and falls back to the baseline outputName.wasm everywhere else
// (e.g. Safari, which still gates relaxed SIMD behind a flag as of mid
// 2026). Idempotent. Call before EnableWasiBrowserRuntime so the emitted
// 2026). Both need what WasmBaselineProbes names, so an engine without
// exception handling gets neither but an error saying so. Idempotent. Call before EnableWasiBrowserRuntime so the emitted
// variants.json manifest includes it. A no-op for non-wasm targets at build
// time (no wasm is produced), but harmless to declare unconditionally.
void EnableWasiRelaxedSimdVariant(Configuration& cfg);