Simplify jump table instructions and add missing conversion;
This makes non-legalized jump table instructions operate on operands with pointer-sized types. This means we need to extend smaller types into the pointer-sized operand, when the two don't match.
This commit is contained in:
@@ -1224,13 +1224,10 @@ pub fn define(
|
|||||||
|
|
||||||
// Jump tables.
|
// Jump tables.
|
||||||
e.enc64(
|
e.enc64(
|
||||||
jump_table_entry.bind(I64).bind_any().bind_any(),
|
jump_table_entry.bind(I64),
|
||||||
rec_jt_entry.opcodes(vec![0x63]).rex().w(),
|
rec_jt_entry.opcodes(vec![0x63]).rex().w(),
|
||||||
);
|
);
|
||||||
e.enc32(
|
e.enc32(jump_table_entry.bind(I32), rec_jt_entry.opcodes(vec![0x8b]));
|
||||||
jump_table_entry.bind(I32).bind_any().bind_any(),
|
|
||||||
rec_jt_entry.opcodes(vec![0x8b]),
|
|
||||||
);
|
|
||||||
|
|
||||||
e.enc64(
|
e.enc64(
|
||||||
jump_table_base.bind(I64),
|
jump_table_base.bind(I64),
|
||||||
|
|||||||
@@ -269,15 +269,9 @@ pub fn define(
|
|||||||
.is_branch(true),
|
.is_branch(true),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// The index into the br_table can be any type; legalizer will convert it to the right type.
|
||||||
let x = &operand_doc("x", iB, "index into jump table");
|
let x = &operand_doc("x", iB, "index into jump table");
|
||||||
|
let entry = &operand_doc("entry", iAddr, "entry of jump table");
|
||||||
let Entry = &TypeVar::new(
|
|
||||||
"Entry",
|
|
||||||
"A scalar integer type",
|
|
||||||
TypeSetBuilder::new().ints(Interval::All).build(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let entry = &operand_doc("entry", Entry, "entry of jump table");
|
|
||||||
let JT = &operand("JT", jump_table);
|
let JT = &operand("JT", jump_table);
|
||||||
|
|
||||||
ig.push(
|
ig.push(
|
||||||
@@ -305,6 +299,9 @@ pub fn define(
|
|||||||
.is_branch(true),
|
.is_branch(true),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// These are the instructions which br_table legalizes to: they perform address computations,
|
||||||
|
// using pointer-sized integers, so their type variables are more constrained.
|
||||||
|
let x = &operand_doc("x", iAddr, "index into jump table");
|
||||||
let Size = &operand_doc("Size", uimm8, "Size in bytes");
|
let Size = &operand_doc("Size", uimm8, "Size in bytes");
|
||||||
|
|
||||||
ig.push(
|
ig.push(
|
||||||
|
|||||||
@@ -240,29 +240,34 @@ fn expand_br_table_jt(
|
|||||||
// $addr = iadd $base, $rel_addr
|
// $addr = iadd $base, $rel_addr
|
||||||
// indirect_jump_table_br $addr, $jt
|
// indirect_jump_table_br $addr, $jt
|
||||||
|
|
||||||
let table_size = func.jump_tables[table].len();
|
|
||||||
let addr_ty = isa.pointer_type();
|
|
||||||
let entry_ty = I32;
|
|
||||||
|
|
||||||
let ebb = func.layout.pp_ebb(inst);
|
let ebb = func.layout.pp_ebb(inst);
|
||||||
let jump_table_ebb = func.dfg.make_ebb();
|
let jump_table_ebb = func.dfg.make_ebb();
|
||||||
|
|
||||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||||
pos.use_srcloc(inst);
|
pos.use_srcloc(inst);
|
||||||
|
|
||||||
// Bounds check
|
// Bounds check.
|
||||||
|
let table_size = pos.func.jump_tables[table].len() as i64;
|
||||||
let oob = pos
|
let oob = pos
|
||||||
.ins()
|
.ins()
|
||||||
.icmp_imm(IntCC::UnsignedGreaterThanOrEqual, arg, table_size as i64);
|
.icmp_imm(IntCC::UnsignedGreaterThanOrEqual, arg, table_size);
|
||||||
|
|
||||||
pos.ins().brnz(oob, default_ebb, &[]);
|
pos.ins().brnz(oob, default_ebb, &[]);
|
||||||
pos.ins().jump(jump_table_ebb, &[]);
|
pos.ins().jump(jump_table_ebb, &[]);
|
||||||
pos.insert_ebb(jump_table_ebb);
|
pos.insert_ebb(jump_table_ebb);
|
||||||
|
|
||||||
|
let addr_ty = isa.pointer_type();
|
||||||
|
|
||||||
|
let arg = if pos.func.dfg.value_type(arg) == addr_ty {
|
||||||
|
arg
|
||||||
|
} else {
|
||||||
|
pos.ins().uextend(addr_ty, arg)
|
||||||
|
};
|
||||||
|
|
||||||
let base_addr = pos.ins().jump_table_base(addr_ty, table);
|
let base_addr = pos.ins().jump_table_base(addr_ty, table);
|
||||||
let entry = pos
|
let entry = pos
|
||||||
.ins()
|
.ins()
|
||||||
.jump_table_entry(addr_ty, arg, base_addr, entry_ty.bytes() as u8, table);
|
.jump_table_entry(arg, base_addr, I32.bytes() as u8, table);
|
||||||
|
|
||||||
let addr = pos.ins().iadd(base_addr, entry);
|
let addr = pos.ins().iadd(base_addr, entry);
|
||||||
pos.ins().indirect_jump_table_br(addr, table);
|
pos.ins().indirect_jump_table_br(addr, table);
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ ebb0(v0: i64):
|
|||||||
; nextln: brif uge $oob, ebb2
|
; nextln: brif uge $oob, ebb2
|
||||||
; nextln: fallthrough $(inb=$EBB)
|
; nextln: fallthrough $(inb=$EBB)
|
||||||
; check: $inb:
|
; check: $inb:
|
||||||
|
; nextln: $(final_idx=$V) = uextend.i64 $idx
|
||||||
; nextln: $(base=$V) = jump_table_base.i64 jt0
|
; nextln: $(base=$V) = jump_table_base.i64 jt0
|
||||||
; nextln: $(rel_addr=$V) = jump_table_entry.i64 $idx, $base, 4, jt0
|
; nextln: $(rel_addr=$V) = jump_table_entry $final_idx, $base, 4, jt0
|
||||||
; nextln: $(addr=$V) = iadd $base, $rel_addr
|
; nextln: $(addr=$V) = iadd $base, $rel_addr
|
||||||
; nextln: indirect_jump_table_br $addr, jt0
|
; nextln: indirect_jump_table_br $addr, jt0
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ ebb1: ; the loop!
|
|||||||
fallthrough ebb2
|
fallthrough ebb2
|
||||||
|
|
||||||
ebb2:
|
ebb2:
|
||||||
v1 = iconst.i32 -14
|
v1 = iconst.i64 -14
|
||||||
v8 = ifcmp_imm v1, 2
|
v8 = ifcmp_imm v1, 2
|
||||||
brif uge v8, ebb1
|
brif uge v8, ebb1
|
||||||
jump ebb3
|
jump ebb3
|
||||||
@@ -25,7 +25,7 @@ ebb3:
|
|||||||
v7 = iadd v5, v6
|
v7 = iadd v5, v6
|
||||||
indirect_jump_table_br v7, jt0
|
indirect_jump_table_br v7, jt0
|
||||||
; check: ebb2:
|
; check: ebb2:
|
||||||
; nextln: v8 = ifcmp_imm.i32 v1, 2
|
; nextln: v8 = ifcmp_imm.i64 v1, 2
|
||||||
; nextln: brif uge v8, ebb1
|
; nextln: brif uge v8, ebb1
|
||||||
; nextln: jump ebb3
|
; nextln: jump ebb3
|
||||||
; check: ebb3:
|
; check: ebb3:
|
||||||
|
|||||||
Reference in New Issue
Block a user