diff --git a/cranelift/codegen/meta/src/isa/x86/encodings.rs b/cranelift/codegen/meta/src/isa/x86/encodings.rs index 788c0c3ec0..5a049eeaab 100644 --- a/cranelift/codegen/meta/src/isa/x86/encodings.rs +++ b/cranelift/codegen/meta/src/isa/x86/encodings.rs @@ -1224,13 +1224,10 @@ pub fn define( // Jump tables. e.enc64( - jump_table_entry.bind(I64).bind_any().bind_any(), + jump_table_entry.bind(I64), rec_jt_entry.opcodes(vec![0x63]).rex().w(), ); - e.enc32( - jump_table_entry.bind(I32).bind_any().bind_any(), - rec_jt_entry.opcodes(vec![0x8b]), - ); + e.enc32(jump_table_entry.bind(I32), rec_jt_entry.opcodes(vec![0x8b])); e.enc64( jump_table_base.bind(I64), diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index 78d017f1a8..36a1a89fb5 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -269,15 +269,9 @@ pub fn define( .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 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 entry = &operand_doc("entry", iAddr, "entry of jump table"); let JT = &operand("JT", jump_table); ig.push( @@ -305,6 +299,9 @@ pub fn define( .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"); ig.push( @@ -2644,11 +2641,11 @@ pub fn define( Cast the bits in `x` as a different type of the same bit width. This instruction does not change the data's representation but allows - data in registers to be used as different types, e.g. an i32x4 as a - b8x16. The only constraint on the result `a` is that it can be + data in registers to be used as different types, e.g. an i32x4 as a + b8x16. The only constraint on the result `a` is that it can be `raw_bitcast` back to the original type. Also, in a raw_bitcast between - vector types with the same number of lanes, the value of each result - lane is a raw_bitcast of the corresponding operand lane. TODO there is + vector types with the same number of lanes, the value of each result + lane is a raw_bitcast of the corresponding operand lane. TODO there is currently no mechanism for enforcing the bit width constraint. "#, ) diff --git a/cranelift/codegen/src/legalizer/mod.rs b/cranelift/codegen/src/legalizer/mod.rs index 5a87492964..e6f7bcb00d 100644 --- a/cranelift/codegen/src/legalizer/mod.rs +++ b/cranelift/codegen/src/legalizer/mod.rs @@ -240,29 +240,34 @@ fn expand_br_table_jt( // $addr = iadd $base, $rel_addr // 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 jump_table_ebb = func.dfg.make_ebb(); let mut pos = FuncCursor::new(func).at_inst(inst); pos.use_srcloc(inst); - // Bounds check + // Bounds check. + let table_size = pos.func.jump_tables[table].len() as i64; let oob = pos .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().jump(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 entry = pos .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); pos.ins().indirect_jump_table_br(addr, table); diff --git a/cranelift/filetests/filetests/isa/x86/legalize-br-table.clif b/cranelift/filetests/filetests/isa/x86/legalize-br-table.clif index fb0aec0606..6d49a6e6d0 100644 --- a/cranelift/filetests/filetests/isa/x86/legalize-br-table.clif +++ b/cranelift/filetests/filetests/isa/x86/legalize-br-table.clif @@ -16,8 +16,9 @@ ebb0(v0: i64): ; nextln: brif uge $oob, ebb2 ; nextln: fallthrough $(inb=$EBB) ; check: $inb: +; nextln: $(final_idx=$V) = uextend.i64 $idx ; 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: indirect_jump_table_br $addr, jt0 diff --git a/cranelift/filetests/filetests/licm/jump-table-entry.clif b/cranelift/filetests/filetests/licm/jump-table-entry.clif index 1d41af25db..cbf51cd080 100644 --- a/cranelift/filetests/filetests/licm/jump-table-entry.clif +++ b/cranelift/filetests/filetests/licm/jump-table-entry.clif @@ -14,7 +14,7 @@ ebb1: ; the loop! fallthrough ebb2 ebb2: - v1 = iconst.i32 -14 + v1 = iconst.i64 -14 v8 = ifcmp_imm v1, 2 brif uge v8, ebb1 jump ebb3 @@ -25,7 +25,7 @@ ebb3: v7 = iadd v5, v6 indirect_jump_table_br v7, jt0 ; check: ebb2: -; nextln: v8 = ifcmp_imm.i32 v1, 2 +; nextln: v8 = ifcmp_imm.i64 v1, 2 ; nextln: brif uge v8, ebb1 ; nextln: jump ebb3 ; check: ebb3: