WebAssembly Native Integer and Float Arithmetic

WebAssembly (Wasm) is designed as a low-level, high-performance compilation target that executes arithmetic operations near native machine speed. This article explores how Wasm natively handles integer and floating-point arithmetic, detailing its supported numeric types, instruction set design, overflow behaviors, and adherence to hardware standards.

Native Numeric Data Types

WebAssembly simplifies hardware abstraction by natively supporting only four basic numeric types. There are no specialized types for 8-bit or 16-bit values; instead, Wasm relies on:

When working with smaller data types (like 8-bit bytes or 16-bit integers), WebAssembly loads them from memory, extends them into i32 registers to perform arithmetic, and truncates them back when saving to memory.

How Wasm Handles Integer Arithmetic

Integer arithmetic in WebAssembly is designed to map directly to modern CPU instruction sets.

Sign-Neutral Types

Wasm integers are sign-neutral. There are no separate “unsigned integer” or “signed integer” types. Instead, the distinction is made entirely at the instruction level. For operations where sign matters—such as division, extension, or comparison—Wasm provides distinct signed (_s) and unsigned (_u) operators. For example: * i32.div_s performs signed 32-bit division. * i32.div_u performs unsigned 32-bit division. * Operators like i32.add and i32.sub do not have signed or unsigned variants because the binary arithmetic is identical for both in two’s complement representation.

Overflows and Traps

Wasm handle integer overflows in two distinct ways: * Wrapping Arithmetic: Basic operations like addition (add), subtraction (sub), and multiplication (mul) do not trap (crash) on overflow. Instead, they silently wrap around using two’s complement math. * Trapping Operations: Division (div_s, div_u) and remainder (rem_s, rem_u) operations will trigger a runtime trap (instantly halting execution) if a division by zero occurs, or if a signed division results in an overflow (such as dividing the minimum possible signed integer by -1).

How Wasm Handles Floating-Point Arithmetic

Floating-point arithmetic in WebAssembly strictly adheres to the IEEE 754-2008 standard for binary floating-point representation. This ensures that floating-point calculations are highly predictable across different hardware architectures.

IEEE 754 Compliance

Wasm supports standard floating-point operations, including addition (add), subtraction (sub), multiplication (mul), division (div), square root (sqrt), absolute value (abs), and copysign (copysign). It also includes instructions for ceiling (ceil), floor (floor), truncation (trunc), and rounding to the nearest integer (nearest).

No Runtime Traps

Unlike integers, floating-point operations in WebAssembly never cause runtime traps. * Dividing a positive number by zero results in positive infinity (inf). * Dividing a negative number by zero results in negative infinity (-inf). * Mathematically undefined operations, such as dividing zero by zero or taking the square root of a negative number, return Not-a-Number (NaN).

NaN Determinism

While WebAssembly aims for complete determinism, IEEE 754 allows for some hardware variation in the exact bit-pattern representation of NaN values. Wasm specifies that while the presence of a NaN is guaranteed, the specific sign bit and payload of the resulting NaN can be non-deterministic across different CPUs.

Conversions and Casts

WebAssembly provides explicit instructions for converting between integers and floating-point numbers.