Implement a poor man's jump table.
We will eventually support real jump tables, but for now just expand br_table into a sequence of conditional branches.
This commit is contained in:
@@ -48,3 +48,18 @@ function %undefined() {
|
||||
ebb0:
|
||||
trap user0
|
||||
}
|
||||
|
||||
function %br_table(i32) {
|
||||
jt0 = jump_table ebb3, ebb1, 0, ebb2
|
||||
|
||||
ebb0(v0: i32):
|
||||
br_table v0, jt0
|
||||
trap oob
|
||||
|
||||
ebb1:
|
||||
return
|
||||
ebb2:
|
||||
return
|
||||
ebb3:
|
||||
return
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ expand.custom_legalize(insts.heap_addr, 'expand_heap_addr')
|
||||
# TODO: Add sufficient XForm syntax that we don't need to hand-code these.
|
||||
expand.custom_legalize(insts.trapz, 'expand_cond_trap')
|
||||
expand.custom_legalize(insts.trapnz, 'expand_cond_trap')
|
||||
expand.custom_legalize(insts.br_table, 'expand_br_table')
|
||||
|
||||
# Custom expansions for floating point constants.
|
||||
# These expansions require bit-casting or creating constant pool entries.
|
||||
|
||||
@@ -39,6 +39,11 @@ impl JumpTableData {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the number of table entries.
|
||||
pub fn len(&self) -> usize {
|
||||
self.table.len()
|
||||
}
|
||||
|
||||
/// Set a table entry.
|
||||
///
|
||||
/// The table will grow as needed to fit `idx`.
|
||||
|
||||
@@ -147,6 +147,38 @@ fn expand_cond_trap(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFl
|
||||
cfg.recompute_ebb(pos.func, new_ebb);
|
||||
}
|
||||
|
||||
/// Jump tables.
|
||||
fn expand_br_table(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFlowGraph) {
|
||||
use ir::condcodes::IntCC;
|
||||
|
||||
let (arg, table) = match func.dfg[inst] {
|
||||
ir::InstructionData::BranchTable {
|
||||
opcode: ir::Opcode::BrTable,
|
||||
arg,
|
||||
table,
|
||||
} => (arg, table),
|
||||
_ => panic!("Expected br_table: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
// This is a poor man's jump table using just a sequence of conditional branches.
|
||||
// TODO: Lower into a jump table load and indirect branch.
|
||||
let table_size = func.jump_tables[table].len();
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
for i in 0..table_size {
|
||||
if let Some(dest) = pos.func.jump_tables[table].get_entry(i) {
|
||||
let t = pos.ins().icmp_imm(IntCC::Equal, arg, i as i64);
|
||||
pos.ins().brnz(t, dest, &[]);
|
||||
}
|
||||
}
|
||||
|
||||
// `br_table` falls through when nothing matches.
|
||||
let ebb = pos.current_ebb().unwrap();
|
||||
pos.remove_inst();
|
||||
cfg.recompute_ebb(pos.func, ebb);
|
||||
}
|
||||
|
||||
/// Expand illegal `f32const` and `f64const` instructions.
|
||||
fn expand_fconst(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut ControlFlowGraph) {
|
||||
let ty = func.dfg.value_type(func.dfg.first_result(inst));
|
||||
|
||||
Reference in New Issue
Block a user