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
@@ -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
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user