cranelift: Better document and test stack maps
This commit is contained in:
103
cranelift/filetests/filetests/stackmaps/call.clif
Normal file
103
cranelift/filetests/filetests/stackmaps/call.clif
Normal file
@@ -0,0 +1,103 @@
|
||||
test stackmaps
|
||||
set enable_safepoints=true
|
||||
target x86_64
|
||||
|
||||
function %icall_fast(r64) -> r64 fast {
|
||||
; check: function %icall_fast
|
||||
; nextln: ss0 = spill_slot 8, offset -32
|
||||
fn0 = %none()
|
||||
block0(v0: r64):
|
||||
; check: ss0] v0 = spill v2
|
||||
; check: safepoint v0
|
||||
call fn0()
|
||||
return v0
|
||||
}
|
||||
; check: Stack maps:
|
||||
; nextln:
|
||||
; nextln: safepoint v0
|
||||
; nextln: - mapped words: 4
|
||||
; nextln: - live: [0]
|
||||
|
||||
function %icall_sys_v(r64) -> r64 system_v {
|
||||
; check: function %icall_sys_v
|
||||
; nextln: ss0 = spill_slot 8, offset -32
|
||||
fn0 = %none()
|
||||
block0(v0: r64):
|
||||
; check: ss0] v0 = spill v2
|
||||
; check: safepoint v0
|
||||
call fn0()
|
||||
return v0
|
||||
}
|
||||
; check: Stack maps:
|
||||
; nextln:
|
||||
; nextln: safepoint v0
|
||||
; nextln: - mapped words: 4
|
||||
; nextln: - live: [0]
|
||||
|
||||
function %icall_fastcall(r64) -> r64 windows_fastcall {
|
||||
; check: function %icall_fastcall
|
||||
; nextln: ss0 = spill_slot 8, offset -32
|
||||
; nextln: ss1 = incoming_arg 24, offset -24
|
||||
; nextln: ss2 = explicit_slot 32, offset -64
|
||||
fn0 = %none()
|
||||
block0(v0: r64):
|
||||
; check: ss0] v0 = spill v2
|
||||
; check: safepoint v0
|
||||
call fn0()
|
||||
return v0
|
||||
}
|
||||
; check: Stack maps:
|
||||
; nextln:
|
||||
; nextln: safepoint v0
|
||||
; nextln: - mapped words: 8
|
||||
; nextln: - live: [4]
|
||||
|
||||
function %call_fast(r64) -> r64 fast {
|
||||
; check: function %call_fast
|
||||
; nextln: ss0 = spill_slot 8, offset -32
|
||||
fn0 = colocated %none()
|
||||
block0(v0: r64):
|
||||
; check: ss0] v0 = spill v1
|
||||
; check: safepoint v0
|
||||
call fn0()
|
||||
return v0
|
||||
}
|
||||
; check: Stack maps:
|
||||
; nextln:
|
||||
; nextln: safepoint v0
|
||||
; nextln: - mapped words: 4
|
||||
; nextln: - live: [0]
|
||||
|
||||
function %call_sys_v(r64) -> r64 system_v {
|
||||
; check: function %call_sys_v
|
||||
; nextln: ss0 = spill_slot 8, offset -32
|
||||
fn0 = colocated %none()
|
||||
block0(v0: r64):
|
||||
; check: ss0] v0 = spill v1
|
||||
; check: safepoint v0
|
||||
call fn0()
|
||||
return v0
|
||||
}
|
||||
; check: Stack maps:
|
||||
; nextln:
|
||||
; nextln: safepoint v0
|
||||
; nextln: - mapped words: 4
|
||||
; nextln: - live: [0]
|
||||
|
||||
function %call_fastcall(r64) -> r64 windows_fastcall {
|
||||
; check: function %call_fastcall
|
||||
; nextln: ss0 = spill_slot 8, offset -32
|
||||
; nextln: ss1 = incoming_arg 24, offset -24
|
||||
; nextln: ss2 = explicit_slot 32, offset -64
|
||||
fn0 = colocated %none()
|
||||
block0(v0: r64):
|
||||
; check: ss0] v0 = spill v1
|
||||
; check: safepoint v0
|
||||
call fn0()
|
||||
return v0
|
||||
}
|
||||
; check: Stack maps:
|
||||
; nextln:
|
||||
; nextln: safepoint v0
|
||||
; nextln: - mapped words: 8
|
||||
; nextln: - live: [4]
|
||||
31
cranelift/filetests/filetests/stackmaps/incoming_args.clif
Normal file
31
cranelift/filetests/filetests/stackmaps/incoming_args.clif
Normal file
@@ -0,0 +1,31 @@
|
||||
test stackmaps
|
||||
set enable_safepoints=true
|
||||
target x86_64
|
||||
|
||||
;; Incoming args get included in stack maps.
|
||||
|
||||
function %incoming_args(r64, r64, r64, r64, r64) -> r64 windows_fastcall {
|
||||
; check: r64 [32]
|
||||
; nextln: ss0 = incoming_arg 8, offset 32
|
||||
; nextln: ss1 = incoming_arg 24, offset -24
|
||||
; nextln: ss2 = explicit_slot 32, offset -64
|
||||
|
||||
fn0 = %none()
|
||||
; nextln: sig0 = () fast
|
||||
; nextln: fn0 = %none sig0
|
||||
|
||||
block0(v0: r64, v1: r64, v2: r64, v3: r64, v4: r64):
|
||||
; check: v4: r64 [ss0]
|
||||
|
||||
call fn0()
|
||||
; check: safepoint v4
|
||||
; nextln: call_indirect
|
||||
return v4
|
||||
}
|
||||
|
||||
; check: Stack maps:
|
||||
; nextln:
|
||||
; nextln: safepoint v4
|
||||
; nextln: - mapped words: 13
|
||||
; nextln: - live: [12]
|
||||
|
||||
@@ -56,6 +56,7 @@ mod test_safepoint;
|
||||
mod test_shrink;
|
||||
mod test_simple_gvn;
|
||||
mod test_simple_preopt;
|
||||
mod test_stackmaps;
|
||||
mod test_unwind;
|
||||
mod test_verifier;
|
||||
|
||||
@@ -139,6 +140,7 @@ fn new_subtest(parsed: &TestCommand) -> subtest::SubtestResult<Box<dyn subtest::
|
||||
"shrink" => test_shrink::subtest(parsed),
|
||||
"simple-gvn" => test_simple_gvn::subtest(parsed),
|
||||
"simple_preopt" => test_simple_preopt::subtest(parsed),
|
||||
"stackmaps" => test_stackmaps::subtest(parsed),
|
||||
"unwind" => test_unwind::subtest(parsed),
|
||||
"verifier" => test_verifier::subtest(parsed),
|
||||
_ => Err(format!("unknown test command '{}'", parsed.command)),
|
||||
|
||||
112
cranelift/filetests/src/test_stackmaps.rs
Normal file
112
cranelift/filetests/src/test_stackmaps.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
use crate::subtest::{run_filecheck, Context, SubTest, SubtestResult};
|
||||
use cranelift_codegen::binemit::{self, Addend, CodeOffset, CodeSink, Reloc, Stackmap};
|
||||
use cranelift_codegen::ir::*;
|
||||
use cranelift_codegen::isa::TargetIsa;
|
||||
use cranelift_codegen::print_errors::pretty_error;
|
||||
use cranelift_reader::TestCommand;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Write;
|
||||
|
||||
struct TestStackmaps;
|
||||
|
||||
pub fn subtest(parsed: &TestCommand) -> SubtestResult<Box<dyn SubTest>> {
|
||||
assert_eq!(parsed.command, "stackmaps");
|
||||
if !parsed.options.is_empty() {
|
||||
Err(format!("No options allowed on {}", parsed))
|
||||
} else {
|
||||
Ok(Box::new(TestStackmaps))
|
||||
}
|
||||
}
|
||||
|
||||
impl SubTest for TestStackmaps {
|
||||
fn name(&self) -> &'static str {
|
||||
"stackmaps"
|
||||
}
|
||||
|
||||
fn run(&self, func: Cow<Function>, context: &Context) -> SubtestResult<()> {
|
||||
let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned());
|
||||
|
||||
comp_ctx
|
||||
.compile(context.isa.expect("`test stackmaps` requires an isa"))
|
||||
.map_err(|e| pretty_error(&comp_ctx.func, context.isa, e))?;
|
||||
|
||||
let mut sink = TestStackMapsSink::default();
|
||||
binemit::emit_function(
|
||||
&comp_ctx.func,
|
||||
|func, inst, div, sink, isa| {
|
||||
if func.dfg[inst].opcode() == Opcode::Safepoint {
|
||||
writeln!(&mut sink.text, "{}", func.dfg.display_inst(inst, isa)).unwrap();
|
||||
}
|
||||
isa.emit_inst(func, inst, div, sink)
|
||||
},
|
||||
&mut sink,
|
||||
context.isa.expect("`test stackmaps` requires an isa"),
|
||||
);
|
||||
|
||||
let mut text = comp_ctx.func.display(context.isa).to_string();
|
||||
text.push('\n');
|
||||
text.push_str("Stack maps:\n");
|
||||
text.push('\n');
|
||||
text.push_str(&sink.text);
|
||||
|
||||
run_filecheck(&text, context)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TestStackMapsSink {
|
||||
offset: u32,
|
||||
text: String,
|
||||
}
|
||||
|
||||
impl CodeSink for TestStackMapsSink {
|
||||
fn offset(&self) -> CodeOffset {
|
||||
self.offset
|
||||
}
|
||||
|
||||
fn put1(&mut self, _: u8) {
|
||||
self.offset += 1;
|
||||
}
|
||||
|
||||
fn put2(&mut self, _: u16) {
|
||||
self.offset += 2;
|
||||
}
|
||||
|
||||
fn put4(&mut self, _: u32) {
|
||||
self.offset += 4;
|
||||
}
|
||||
|
||||
fn put8(&mut self, _: u64) {
|
||||
self.offset += 8;
|
||||
}
|
||||
|
||||
fn reloc_block(&mut self, _: Reloc, _: CodeOffset) {}
|
||||
fn reloc_external(&mut self, _: SourceLoc, _: Reloc, _: &ExternalName, _: Addend) {}
|
||||
fn reloc_constant(&mut self, _: Reloc, _: ConstantOffset) {}
|
||||
fn reloc_jt(&mut self, _: Reloc, _: JumpTable) {}
|
||||
fn trap(&mut self, _: TrapCode, _: SourceLoc) {}
|
||||
fn begin_jumptables(&mut self) {}
|
||||
fn begin_rodata(&mut self) {}
|
||||
fn end_codegen(&mut self) {}
|
||||
|
||||
fn add_stackmap(&mut self, val_list: &[Value], func: &Function, isa: &dyn TargetIsa) {
|
||||
let map = Stackmap::from_values(&val_list, func, isa);
|
||||
|
||||
writeln!(&mut self.text, " - mapped words: {}", map.mapped_words()).unwrap();
|
||||
write!(&mut self.text, " - live: [").unwrap();
|
||||
|
||||
let mut needs_comma_space = false;
|
||||
for i in 0..(map.mapped_words() as usize) {
|
||||
if map.get_bit(i) {
|
||||
if needs_comma_space {
|
||||
write!(&mut self.text, ", ").unwrap();
|
||||
}
|
||||
needs_comma_space = true;
|
||||
|
||||
write!(&mut self.text, "{}", i).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(&mut self.text, "]").unwrap();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user