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§
- Isel
Error - Why a function could not be selected.
Functions§
- select
- Selects
funcof a validatedmoduleinto a MIR function on virtual registers, named after the function and under the calling convention its signature selects. The module is validated first.