Skip to content

Commit

Permalink
Fix handling of large branch values in cranelift_frontend::Switch (#8422
Browse files Browse the repository at this point in the history
)

Previously trying to branch on a i128 with a branch value larger than
i64::MAX after truncating to u64 would result in the branch value incorrectly
getting interpreted as a value with the upper 64 bits being 1 rather than 0.
  • Loading branch information
bjorn3 committed Apr 21, 2024
1 parent 1fa8de1 commit 4d25a4f
Showing 1 changed file with 44 additions and 2 deletions.
46 changes: 44 additions & 2 deletions cranelift/frontend/src/switch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,11 @@ impl Switch {
}

fn icmp_imm_u128(bx: &mut FunctionBuilder, cond: IntCC, x: Value, y: u128) -> Value {
if let Ok(index) = u64::try_from(y) {
bx.ins().icmp_imm(cond, x, index as i64)
if bx.func.dfg.value_type(x) != types::I128 {
assert!(u64::try_from(y).is_ok());
bx.ins().icmp_imm(cond, x, y as i64)
} else if let Ok(index) = i64::try_from(y) {
bx.ins().icmp_imm(cond, x, index)
} else {
let (lsb, msb) = (y as u64, (y >> 64) as u64);
let lsb = bx.ins().iconst(types::I64, lsb as i64);
Expand Down Expand Up @@ -651,4 +654,43 @@ block4:
br_table v3, block3, [block2, block1]"
);
}

#[test]
fn switch_128bit_max_u64() {
let mut func = Function::new();
let mut func_ctx = FunctionBuilderContext::new();
{
let mut bx = FunctionBuilder::new(&mut func, &mut func_ctx);
let block0 = bx.create_block();
bx.switch_to_block(block0);
let val = bx.ins().iconst(types::I64, 0);
let val = bx.ins().uextend(types::I128, val);
let mut switch = Switch::new();
let block1 = bx.create_block();
switch.set_entry(u64::MAX.into(), block1);
let block2 = bx.create_block();
switch.set_entry(0, block2);
let block3 = bx.create_block();
switch.emit(&mut bx, val, block3);
}
let func = func
.to_string()
.trim_start_matches("function u0:0() fast {\n")
.trim_end_matches("\n}\n")
.to_string();
assert_eq_output!(
func,
"block0:
v0 = iconst.i64 0
v1 = uextend.i128 v0 ; v0 = 0
v2 = iconst.i64 -1
v3 = iconst.i64 0
v4 = iconcat v2, v3 ; v2 = -1, v3 = 0
v5 = icmp eq v1, v4
brif v5, block1, block4
block4:
brif.i128 v1, block3, block2"
);
}
}

0 comments on commit 4d25a4f

Please sign in to comment.