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:
Tyler McMullen
2018-10-03 11:04:21 -06:00
committed by Dan Gohman
parent de1d82b4ba
commit 79cea5e18b
39 changed files with 627 additions and 100 deletions

View File

@@ -32,6 +32,8 @@ use std::ptr::write_unaligned;
pub struct MemoryCodeSink<'a> {
data: *mut u8,
offset: isize,
/// Size of the machine code portion of output
pub code_size: isize,
relocs: &'a mut RelocSink,
traps: &'a mut TrapSink,
}
@@ -49,6 +51,7 @@ impl<'a> MemoryCodeSink<'a> {
MemoryCodeSink {
data,
offset: 0,
code_size: 0,
relocs,
traps,
}
@@ -131,6 +134,10 @@ impl<'a> CodeSink for MemoryCodeSink<'a> {
let ofs = self.offset();
self.traps.trap(ofs, srcloc, code);
}
fn begin_rodata(&mut self) {
self.code_size = self.offset;
}
}
/// A `TrapSink` implementation that does nothing, which is convenient when

View File

@@ -94,6 +94,9 @@ pub trait CodeSink {
/// Add trap information for the current offset.
fn trap(&mut self, TrapCode, SourceLoc);
/// Code output is complete, read-only data may follow.
fn begin_rodata(&mut self);
}
/// Report a bad encoding error.
@@ -123,4 +126,20 @@ where
emit_inst(func, inst, &mut divert, sink);
}
}
sink.begin_rodata();
// output jump tables
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),
}
}
}
}

View File

@@ -95,6 +95,13 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) -> CodegenResult<Cod
}
}
for (jt, jt_data) in func.jump_tables.iter() {
func.jt_offsets[jt] = offset;
// TODO: this should be computed based on the min size needed to hold
// the furthest branch.
offset += jt_data.len() as u32 * 4;
}
Ok(offset)
}