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

@@ -97,12 +97,20 @@ fn handle_module(
context.func = func;
// Compile and encode the result to machine code.
let total_size = context
.compile(isa)
.map_err(|err| pretty_error(&context.func, Some(isa), err))?;
let mut mem = Vec::new();
mem.resize(total_size as usize, 0);
let mut relocs = PrintRelocs { flag_print };
let mut traps = PrintTraps { flag_print };
context
.compile_and_emit(isa, &mut mem, &mut relocs, &mut traps)
.map_err(|err| pretty_error(&context.func, Some(isa), err))?;
let mut code_sink: binemit::MemoryCodeSink;
unsafe {
code_sink = binemit::MemoryCodeSink::new(mem.as_mut_ptr(), &mut relocs, &mut traps);
}
isa.emit_function_to_memory(&context.func, &mut code_sink);
if flag_print {
println!("{}", context.func.display(isa));
@@ -121,17 +129,41 @@ fn handle_module(
}
println!();
print_disassembly(isa, &mem)?;
print_disassembly(isa, &mem[0..code_sink.code_size as usize])?;
print_readonly_data(&mem[code_sink.code_size as usize..total_size as usize]);
}
}
Ok(())
}
fn print_readonly_data(mem: &[u8]) {
if mem.len() == 0 {
return;
}
println!("\nFollowed by {} bytes of read-only data:", mem.len());
for (i, byte) in mem.iter().enumerate() {
if i % 16 == 0 {
if i != 0 {
println!();
}
print!("{:4}: ", i);
}
if i % 4 == 0 {
print!(" ");
}
print!("{:02x} ", byte);
}
println!();
}
cfg_if! {
if #[cfg(feature = "disas")] {
use capstone::prelude::*;
use target_lexicon::Architecture;
use std::fmt::Write;
fn get_disassembler(isa: &TargetIsa) -> Result<Capstone, String> {
let cs = match isa.triple().architecture {
@@ -168,10 +200,28 @@ cfg_if! {
fn print_disassembly(isa: &TargetIsa, mem: &[u8]) -> Result<(), String> {
let mut cs = get_disassembler(isa)?;
println!("\nDisassembly:");
println!("\nDisassembly of {} bytes:", mem.len());
let insns = cs.disasm_all(&mem, 0x0).unwrap();
for i in insns.iter() {
println!("{}", i);
let mut line = String::new();
write!(&mut line, "{:4x}:\t", i.address()).unwrap();
let mut bytes_str = String::new();
for b in i.bytes() {
write!(&mut bytes_str, "{:02x} ", b).unwrap();
}
write!(&mut line, "{:21}\t", bytes_str).unwrap();
if let Some(s) = i.mnemonic() {
write!(&mut line, "{}\t", s).unwrap();
}
if let Some(s) = i.op_str() {
write!(&mut line, "{}", s).unwrap();
}
println!("{}", line);
}
Ok(())
}