← board

wasm32: div by a run-time zero traps instead of raising

uses SysUtils;
b := 0;
try WriteLn(a div b);
except on E: EDivByZero do WriteLn('caught ', E.ClassName); end;
{ FPC, x86-64, i386, arm32, aarch64, riscv32, xtensa: caught EDivByZero }
{ wasm32: wasm trap: integer divide by zero, exit 134 }

Cause and fix

wasm's div/rem instructions trap when the divisor is zero. The native backends first call the handler that DivZeroCheckProc names. That handler is PXXDivZero, which raises EDivByZero through SysUtils' hook and otherwise stops with RE 200. WasmIntBinop emitted the instruction with no check.

WasmDivZeroGuard now runs before each integer div/mod. It stores the divisor in a scratch local, and if the divisor is zero it calls the handler and sets the divisor to 1. The instruction therefore cannot trap before WasmEmitExcCheck unwinds, the same way it does after any other call. When DivZeroCheckProc is -1 (--no-div-check, or the ESP platforms) nothing is emitted, as on the other targets.

Measured (2026-09-29, fixedpoint 4de42d8ec324)