Skip to content

Commit 7f109a5

Browse files
committed
machinst x64: use a sign-extension when loading jump table offsets;
The jump table offset that's loaded out of the jump table could be signed (if it's an offset to before the jump table itself), so we should use a signed extension there, not an unsigned extension.
1 parent 8fd9209 commit 7f109a5

File tree

3 files changed

+12
-5
lines changed

3 files changed

+12
-5
lines changed

cranelift/codegen/src/isa/x64/inst/emit.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,7 +1462,7 @@ pub(crate) fn emit(
14621462
// jnb $default_target
14631463
// movl %idx, %tmp2
14641464
// lea start_of_jump_table_offset(%rip), %tmp1
1465-
// movzlq [%tmp1, %tmp2], %tmp2
1465+
// movslq [%tmp1, %tmp2, 4], %tmp2 ;; shift of 2, viz. multiply index by 4
14661466
// addq %tmp2, %tmp1
14671467
// j *%tmp1
14681468
// $start_of_jump_table:
@@ -1485,8 +1485,9 @@ pub(crate) fn emit(
14851485
);
14861486
inst.emit(sink, flags, state);
14871487

1488-
// Load value out of jump table.
1489-
let inst = Inst::movzx_rm_r(
1488+
// Load value out of the jump table. It's a relative offset to the target block, so it
1489+
// might be negative; use a sign-extension.
1490+
let inst = Inst::movsx_rm_r(
14901491
ExtMode::LQ,
14911492
RegMem::mem(Amode::imm_reg_reg_shift(0, tmp1.to_reg(), tmp2.to_reg(), 2)),
14921493
*tmp2,

cranelift/codegen/src/isa/x64/inst/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ pub enum Inst {
350350
/// Jump-table sequence, as one compound instruction (see note in lower.rs for rationale).
351351
/// The generated code sequence is described in the emit's function match arm for this
352352
/// instruction.
353+
/// See comment in lowering about the temporaries signedness.
353354
JmpTableSeq {
354355
idx: Reg,
355356
tmp1: Writable<Reg>,

cranelift/codegen/src/isa/x64/lower.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,8 +1989,13 @@ impl LowerBackend for X64Backend {
19891989
// is to introduce a relocation pass for inlined jumptables, which is much
19901990
// worse.)
19911991

1992-
let tmp1 = ctx.alloc_tmp(RegClass::I64, I32);
1993-
let tmp2 = ctx.alloc_tmp(RegClass::I64, I32);
1992+
// This temporary is used as a signed integer of 64-bits (to hold addresses).
1993+
let tmp1 = ctx.alloc_tmp(RegClass::I64, I64);
1994+
// This temporary is used as a signed integer of 32-bits (for the wasm-table
1995+
// index) and then 64-bits (address addend). The small lie about the I64 type
1996+
// is benign, since the temporary is dead after this instruction (and its
1997+
// Cranelift type is thus unused).
1998+
let tmp2 = ctx.alloc_tmp(RegClass::I64, I64);
19941999

19952000
let targets_for_term: Vec<MachLabel> = targets.to_vec();
19962001
let default_target = BranchTarget::Label(targets[0]);

0 commit comments

Comments
 (0)