Skip to main content

Module isel

Module isel 

Source
Expand description

Instruction selection: one ir-lang 2.0 function to a MIR function on virtual registers.

Blocks and block parameters map one to one (IR.md §15): an IR edge’s arguments become the MIR branch’s arguments, resolved as a parallel copy at emission. Every value of an integer, bool, ptr, or ref type lives in one general-purpose virtual register, and in this release so does a float’s bit pattern (see below).

§Value representation

A value of a type narrower than 64 bits occupies the low bits of its register; the bits above its width are unspecified, exactly as the x86-64 32-bit operations leave them. Arithmetic on 8-, 16-, and 32-bit types runs at 32 bits; wherever the upper bits matter (comparisons, division, right shifts, overflow checks, widening conversions, switch values, array indices) the value is extended first by its type’s signedness. bool is the exception: always exactly 0 or 1, so it can be tested, stored, and converted directly; booleans entering from outside (parameters, call results, loads) are normalized.

§Policies

Every OPS integer operation is selected under every policy ir-lang can carry (IR.md §4): wrap computes modulo the width; trap branches to a per-function trap block that calls the runtime trap handler (Options::trap_symbol) with the OPS code; error (only inside a check terminator) branches to the error edge, passing the OPS code as err. Division checks zero, then MIN / -1, before it divides, so the processor never faults. Shifts check, mask, or saturate their amount (saturate, OPS v2: an amount at or past the width shifts every bit out, leaving the sign for an arithmetic right shift; a negative amount is still ShiftOutOfRange).

Integer pow (OPS v2) is repeated squaring: unrolled when the exponent is a constant (at most 64 squarings and 64 multiplications), a loop over the exponent’s bits otherwise (at most 64 iterations), each product checked for overflow under trap and error. A negative exponent is the NegativeExponent error (code 6) under every policy, which is why ir-lang 2.0.0-alpha.3 makes every signed pow the operation of a check (BinaryOp::can_error).

§Floats as bit patterns

isa-lang 0.2 encodes no SSE, so this release keeps a float in a general-purpose register as its bit pattern (f32 in the low 32 bits, the upper bits unspecified, like i32). Everything that only moves a value works on floats: constants, bitcast to and from the integer of the same width, loads, stores, select, block parameters and edge arguments. Float pow calls the runtime’s ls_pow routine (Options::pow_f64_symbol, Options::pow_f32_symbol) with the bit patterns in integer registers: ir-lang’s own routine, never a platform libm, so the result is bit-identical to every other tier.

§What is not selected yet

Float arithmetic other than pow, float comparisons, conversions between floats and integers, and float arguments and results (both conventions pass them in vector registers) wait on isa-lang’s SSE forms (ISSUES P11), as do lock-prefixed atomic read-modify-writes other than xchg and cmpxchg; aapcs64 waits on the AArch64 target; 32-bit pointer modules on a 32-bit target. Each is reported as IselError::Unsupported, never miscompiled.

Enums§

IselError
Why a function could not be selected.

Functions§

select
Selects func of a validated module into a MIR function on virtual registers, named after the function and under the calling convention its signature selects. The module is validated first.