#![doc(html_root_url = "https://docs.rs/rucc-regalloc/0.3.4")]
pub mod assign;
pub mod check;
pub mod live;
pub mod moves;
pub mod order;
pub mod rewrite;
#[derive(Debug, Clone)]
pub struct Allocation {
pub assignment: assign::Assignment,
pub edits: Vec<rewrite::Edit>,
}
pub fn run(func: &mut rucc_mir::Func, env: &assign::Env) -> Allocation {
let order = order::Order::of(func);
let live = live::Live::of(func, &order);
let assignment = assign::assign(func, &order, &live, env);
if cfg!(debug_assertions) {
let problems = check::check(func, &order, &live, &assignment);
assert!(problems.is_empty(), "{}", check::report(&problems));
}
let edits = rewrite::rewrite(func, &assignment, env);
Allocation { assignment, edits }
}
pub const MILESTONE: &str = "M3";
#[cfg(test)]
mod tests {
use rucc_base::Interner;
use rucc_mir::{Func, Opcode};
use rucc_target::x86_64::{GPR, SYSV};
use super::*;
#[test]
fn milestone_is_recorded() {
assert!(MILESTONE.starts_with('M'));
}
#[test]
fn allocating_a_function_places_every_value_and_hands_back_the_moves_it_needs() {
let mut names = Interner::new();
let mut func = Func::new(names.intern("f"));
let opcode = Opcode::new(names.intern("x64.nop"));
let block = func.create_block();
let first = func.new_vreg(GPR);
let second = func.new_vreg(GPR);
let third = func.new_vreg(GPR);
func.build(block, opcode).def(first, GPR).finish();
func.build(block, opcode).def(second, GPR).finish();
func.build(block, opcode).def(third, GPR).finish();
func.build(block, opcode).uses(first, GPR).uses(second, GPR).uses(third, GPR).finish();
let env = assign::Env::new().with(GPR, &SYSV.int_order[..2], &SYSV.int_order[2..5]);
let allocation = run(&mut func, &env);
assert_eq!(allocation.assignment.spilled(), 1);
assert_eq!(allocation.edits.len(), 2);
}
}