GHC WebAssembly Weekly Update, 2023-02-01

Seven bugfixes since last week’s report. There aren’t interesting test suite failures that only fail for the wasm native codegen anymore, so it’s fair to say the wasm NCG has reached the same level of robustness as the unregisterised codegen, while being much faster at compile-time. I’m also getting closer towards the goal of zero testsuite failure for the wasm backend.

  • Fixed a bug in the wasm native codegen (!9837). This bug involves incorrect handling of negative 8-bit/16-bit literals. Previously they were lowered to something like i32.const -1, so the higher bits are filled with 1 due to 2’s complement. If such a literal is compared against another negative subword loaded from memory, incorrect runtime result awaits. The loaded operand would unfortunately have 0s in the higher bits, given Cmm type system doesn’t track signedness so I always do an i32.load8_u/i32.load16_u. The fix: lower negative subword literals to positive literals with the correct bit pattern, e.g. lower -1 :: W8 to i32.const 0xFF.
  • Fixed a bug in the wasm native codegen (!9838). This bug involves a missing case in the Cmm IR that I didn’t handle on purpose, given it should not exist after a certain Cmm pass, but turns out it may still appear in rare occasions that involve hand-written Cmm. The fix is trivial, though the bug shouldn’t affect normal Haskell programs and is only spotted in a single test case in the testsuite.
  • Fixed a bug in the wasm native codegen (!9849). This bug involves incorrect handling of signed 8-bit/16-bit foreign call arguments and return values. When signed subwords cross Cmm/C boundary, sign extensions and truncations must be performed. The patch adds the missing logic using the Cmm ForeignHints that annotate foreign call arguments and return values.
  • Fixed a bug in the wasm native codegen (!9854). This bug involves incorrect alignment values of data sections. Previously I tried to set the alignment value as low as possible, based on the section kind inferred from the CLabel. For info tables, .p2align 1 was applied given the GC should only need the lowest bit to tag forwarding pointers. But this would lead to unaligned loads/stores, which has a performance penalty even if the wasm spec permits it. Furthermore, the test suite has shown memory corruption in a few cases when compacting gc is used. Now, a more conservative approach is taken: all data sections except C strings align to word size.
  • Fixed a bug in the RTS that may affect wasm (!9858). This bug involves a potential divide-by-zero error when tickInterval is zero. Which is not the default on other targets, but it indeed defaults to zero on wasm, due to the lack of RTS timer. Shouldn’t affect typical user programs that don’t manually set these RTS options: -C, -i, -eventlog-flush-interval.
  • Fixed a bug in the testsuite that affects the wasm unregisterised codegen (!9862). This bug involves usage of a libc function which is glibc-specific and deprecated.
  • Fixed a bug in the wasm native codegen (!9873). This bug involves a misunderstanding about the CmmSwitch scrutinee, it can be an integer of any width and not necessarily a word. When it’s a 64-bit integer it can trigger a compiler panic, as reported in #22864. Once identified, the fix is straightforward, and a regression test is also added.
  • Reported a bug that affects the wasm native codegen (#22854). It surfaces as an LLVM segfault in one of testsuite cases, and the root cause is CLabel symbol kind confusion. It’s very annoying, since GHC isn’t 100% precise if a CLabel is function or data, and it just happened to work on other platforms whose toolchains can tolerate some inconsistency here. Rest assured, this bug only affects hand-written Cmm which is rare for typical user programs.
  • Another 9.6 backporting MR including new wasm-related fixes since the last one (!9848).
  • Landed the wasm-libc patch to add a safety check for WASI reactor modules (#388).

Previous update: