Browse Source

Add a 'regalloc' filetest command.

Run functions through the register allocator, and then filecheck.
pull/3/head
Jakob Stoklund Olesen 8 years ago
parent
commit
4ba5cfeed3
  1. 14
      docs/testing.rst
  2. 12
      filetests/regalloc/basic.cton
  3. 11
      src/filetest/mod.rs
  4. 55
      src/filetest/regalloc.rs

14
docs/testing.rst

@ -300,3 +300,17 @@ Legalize each function for the specified target ISA and run the resulting
function through filecheck. This test command can be used to validate the
encodings selected for legal instructions as well as the instruction
transformations performed by the legalizer.
`test regalloc`
---------------
Test the register allocator.
First, each function is legalized for the specified target ISA. This is
required for register allocation since the instruction encodings provide
register class constraints to the register allocator.
Second, the register allocator is run on the function, inserting spill code and
assigning registers and stack slots to all values.
The resulting function is then run through filecheck.

12
filetests/regalloc/basic.cton

@ -0,0 +1,12 @@
test regalloc
; We can add more ISAs once they have defined encodings.
isa riscv
function add(i32, i32) {
ebb0(v1: i32, v2: i32):
v3 = iadd v1, v2
; check: [R#0c,%x0]
; sameln: iadd
return_reg v3
}

11
src/filetest/mod.rs

@ -12,12 +12,14 @@ use print_cfg;
use filetest::runner::TestRunner;
pub mod subtest;
mod runner;
mod runone;
mod concurrent;
mod domtree;
mod verifier;
mod legalizer;
mod regalloc;
mod runner;
mod runone;
mod verifier;
/// The result of running the test in a file.
pub type TestResult = Result<time::Duration, String>;
@ -49,7 +51,7 @@ pub fn run(verbose: bool, files: Vec<String>) -> CommandResult {
/// Create a new subcommand trait object to match `parsed.command`.
///
/// This function knows how to create all of the possible `test <foo>` commands that can appear in
/// a .cton test file.
/// a `.cton` test file.
fn new_subtest(parsed: &TestCommand) -> subtest::Result<Box<subtest::SubTest>> {
match parsed.command {
"cat" => cat::subtest(parsed),
@ -57,6 +59,7 @@ fn new_subtest(parsed: &TestCommand) -> subtest::Result<Box<subtest::SubTest>> {
"domtree" => domtree::subtest(parsed),
"verifier" => verifier::subtest(parsed),
"legalizer" => legalizer::subtest(parsed),
"regalloc" => regalloc::subtest(parsed),
_ => Err(format!("unknown test command '{}'", parsed.command)),
}
}

55
src/filetest/regalloc.rs

@ -0,0 +1,55 @@
//! Test command for testing the register allocator.
//!
//! The `regalloc` test command runs each function through the register allocator after ensuring
//! that all instructions are legal for the target.
//!
//! The resulting function is sent to `filecheck`.
use std::borrow::Cow;
use cretonne::{self, write_function};
use cretonne::ir::Function;
use cton_reader::TestCommand;
use filetest::subtest::{SubTest, Context, Result, run_filecheck};
struct TestRegalloc;
pub fn subtest(parsed: &TestCommand) -> Result<Box<SubTest>> {
assert_eq!(parsed.command, "regalloc");
if !parsed.options.is_empty() {
Err(format!("No options allowed on {}", parsed))
} else {
Ok(Box::new(TestRegalloc))
}
}
impl SubTest for TestRegalloc {
fn name(&self) -> Cow<str> {
Cow::from("regalloc")
}
fn is_mutating(&self) -> bool {
true
}
fn needs_isa(&self) -> bool {
true
}
fn run(&self, func: Cow<Function>, context: &Context) -> Result<()> {
let isa = context.isa.expect("register allocator needs an ISA");
// Create a compilation context, and drop in the function.
let mut comp_ctx = cretonne::Context::new();
comp_ctx.func = func.into_owned();
// TODO: Should we have an option to skip legalization?
comp_ctx.legalize(isa);
comp_ctx.flowgraph();
comp_ctx.regalloc(isa);
let mut text = String::new();
try!(write_function(&mut text, &comp_ctx.func, Some(isa)).map_err(|e| e.to_string()));
run_filecheck(&text, context)
}
}
Loading…
Cancel
Save