Implement jump tables (#453)
* Add 'jump_table_entry' and 'indirect_jump' instructions. * Update CodeSink to keep track of code size. Pretty up clif-util's disassembly output. * Only disassemble the machine portion of output. Pretty print the read-only data after it. * Update switch frontend code to use new br_table instruction w/ default.
This commit is contained in:
committed by
Dan Gohman
parent
de1d82b4ba
commit
79cea5e18b
@@ -4,7 +4,7 @@
|
||||
//! functions and compares the results to the expected output.
|
||||
|
||||
use cranelift_codegen::binemit;
|
||||
use cranelift_codegen::binemit::RegDiversions;
|
||||
use cranelift_codegen::binemit::{CodeSink, RegDiversions};
|
||||
use cranelift_codegen::dbg::DisplayList;
|
||||
use cranelift_codegen::ir;
|
||||
use cranelift_codegen::ir::entities::AnyEntity;
|
||||
@@ -30,6 +30,7 @@ pub fn subtest(parsed: &TestCommand) -> SubtestResult<Box<SubTest>> {
|
||||
|
||||
/// Code sink that generates text.
|
||||
struct TextSink {
|
||||
code_size: binemit::CodeOffset,
|
||||
offset: binemit::CodeOffset,
|
||||
text: String,
|
||||
}
|
||||
@@ -38,6 +39,7 @@ impl TextSink {
|
||||
/// Create a new empty TextSink.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
code_size: 0,
|
||||
offset: 0,
|
||||
text: String::new(),
|
||||
}
|
||||
@@ -93,6 +95,10 @@ impl binemit::CodeSink for TextSink {
|
||||
fn trap(&mut self, code: ir::TrapCode, _srcloc: ir::SourceLoc) {
|
||||
write!(self.text, "{} ", code).unwrap();
|
||||
}
|
||||
|
||||
fn begin_rodata(&mut self) {
|
||||
self.code_size = self.offset
|
||||
}
|
||||
}
|
||||
|
||||
impl SubTest for TestBinEmit {
|
||||
@@ -281,6 +287,21 @@ impl SubTest for TestBinEmit {
|
||||
}
|
||||
}
|
||||
|
||||
sink.begin_rodata();
|
||||
|
||||
for (jt, jt_data) in func.jump_tables.iter() {
|
||||
let jt_offset = func.jt_offsets[jt];
|
||||
for idx in 0..jt_data.len() {
|
||||
match jt_data.get_entry(idx) {
|
||||
Some(ebb) => {
|
||||
let rel_offset: i32 = func.offsets[ebb] as i32 - jt_offset as i32;
|
||||
sink.put4(rel_offset as u32)
|
||||
}
|
||||
None => sink.put4(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if sink.offset != code_size {
|
||||
return Err(format!(
|
||||
"Expected code size {}, got {}",
|
||||
|
||||
Reference in New Issue
Block a user