Skip to main content

Crate backend_lang

Crate backend_lang 

Source
Expand description

§backend_lang

The core of the LexerSketch native backend: a machine IR over virtual and physical registers, target descriptions that say everything the backend needs to know about an ISA as data, calling conventions and frame layout, a parallel-move resolver, and emission to machine code through isa_lang. No Cranelift, no LLVM, no system assembler.

This release (0.2) is the foundation. Instruction selection from ir-lang and SSA register allocation build on it in 0.5; until then MIR is built directly, and emission takes functions whose registers are already physical.

§Quick start

emit is the one-call path: a MIR function on physical registers in, x86-64 machine code out.

use backend_lang::mir::{Effects, Function, Operand};
use backend_lang::x86_64::{op, SYSV, RAX, RDI};

// fn double(x) -> x + x, SysV: x arrives in rdi, the result leaves in rax.
let mut f = Function::new("double", &SYSV);
let entry = f.block()?;
f.add_param(entry, RDI.into())?;
f.push(entry, op::MOV64, &[RAX.into(), RDI.into()])?;
f.push(entry, op::ADD64, &[RAX.into(), RAX.into(), RDI.into()])?;
f.push_with(entry, op::RET, &[], Effects::new().uses(&[RAX]))?;
f.omit_frame_pointer();

let code = backend_lang::emit(&f)?;
// mov rax, rdi; add rax, rdi; ret
assert_eq!(code, [0x48, 0x89, 0xF8, 0x48, 0x01, 0xF8, 0xC3]);

§The pieces

  • mir: Functions of Blocks of target instructions, with typed virtual registers, stack slots, symbols, explicit implicit operands, and a deterministic text form.
  • target: the Target description (registers, classes, instructions with their operand rules and implicit operands), abi (argument and return registers, callee-saved sets, stack alignment, shadow space, red zone, probing), and frame (frame layout and prologue/epilogue plans).
  • moves: the parallel-move resolver every parallel copy goes through.
  • x86_64: the x86-64 description, SysV and Win64, and the Emitter.

§Block parameters, not phi nodes

Values cross control-flow edges as block parameters: a branch passes arguments, and the target block’s parameters receive them all at once. This is the same information as phi nodes, kept at the edge where it is used: the parallel copy a phi implies on each incoming edge is written down on that edge. An SSA register allocator (0.5) assigns parameters and arguments independently and resolves each edge with the parallel-move resolver; ir-lang already uses block parameters, so instruction selection maps them one to one; and there is no per-block phi list to keep in sync with predecessor order.

§Guarantees

  • Parallel copies are exact. Every edge, copy, and pcopy goes through moves::MoveResolver, which handles any permutation, cycles of any length, fan-out, registers and stack slots mixed, and immediates, with the fewest moves under its rules. Property tests run it against a parallel-assignment reference, and emitted edges against an interpreter of the emitted machine code.
  • Emission is checked. A function is verified before emission; virtual registers, mismatched tied operands, and writes to the stack or frame pointer are errors, not bad code.
  • No reachable panics, no recursion. Every table is a dense vector, every walk a loop, every fallible path a Result.

§Features

  • std (default): no effect beyond isa-lang’s; the crate is no_std and needs only alloc.

Re-exports§

pub use isa_lang;

Modules§

mir
Machine IR: target instructions on virtual and physical registers.
moves
The parallel-move resolver: turns a parallel copy into a sequence of moves (and swaps) that a machine can execute one at a time.
target
Target descriptions: the backend’s half of TARGET-DESC.md.
x86_64
The x86-64 target: registers, classes, calling conventions (SysV and Win64), the machine-instruction table, and emission through isa-lang.

Structs§

PReg
A physical register: an index into the target’s register file.
Reg
A register operand: physical or virtual.
RegClass
A register class: the set of physical registers a value may live in, and the type of a virtual register. An index into the target’s class table.
RegSet
A set of physical registers: 128 bits, one per PReg index.
RegSetIter
The registers of a RegSet, in index order. Made by RegSet::iter.
VReg
A virtual register: an index into a function’s virtual-register table.

Constants§

MAX_PREGS
The most physical registers a target may describe.

Functions§

emit
Emits one function to machine code: the one-call path.