diff --git a/cranelift/frontend/src/switch.rs b/cranelift/frontend/src/switch.rs index 5c8a9bb83f..7719de1752 100644 --- a/cranelift/frontend/src/switch.rs +++ b/cranelift/frontend/src/switch.rs @@ -240,8 +240,8 @@ impl Switch { // There are currently no 128bit systems supported by rustc, but once we do ensure that // we don't silently ignore a part of the jump table for 128bit integers on 128bit systems. assert!( - u64::try_from(blocks.len()).is_ok(), - "Jump tables bigger than 2^64-1 are not yet supported" + u32::try_from(blocks.len()).is_ok(), + "Jump tables bigger than 2^32-1 are not yet supported" ); let mut jt_data = JumpTableData::new(); @@ -265,18 +265,18 @@ impl Switch { } }; - let discr = if bx.func.dfg.value_type(discr).bits() > 64 { - // Check for overflow of cast to u64. + let discr = if bx.func.dfg.value_type(discr).bits() > 32 { + // Check for overflow of cast to u32. let new_block = bx.create_block(); - let bigger_than_u64 = + let bigger_than_u32 = bx.ins() - .icmp_imm(IntCC::UnsignedGreaterThan, discr, u64::max_value() as i64); - bx.ins().brnz(bigger_than_u64, otherwise, &[]); + .icmp_imm(IntCC::UnsignedGreaterThan, discr, u32::max_value() as i64); + bx.ins().brnz(bigger_than_u32, otherwise, &[]); bx.ins().jump(new_block, &[]); bx.switch_to_block(new_block); - // Cast to u64, as br_table is not implemented for integers bigger than 64bits. - bx.ins().ireduce(types::I64, discr) + // Cast to u32, as br_table is not implemented for integers bigger than 32bits. + bx.ins().ireduce(types::I32, discr) } else { discr }; @@ -571,6 +571,47 @@ block4: builder.finalize(); // Will panic if some blocks are not sealed } + #[test] + fn switch_64bit() { + 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 mut switch = Switch::new(); + let block1 = bx.create_block(); + switch.set_entry(1, 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!( + func, + " jt0 = jump_table [block2, block1] + +block0: + v0 = iconst.i64 0 + jump block4 + +block4: + v1 = icmp_imm.i64 ugt v0, 0xffff_ffff + brnz v1, block3 + jump block5 + +block5: + v2 = ireduce.i32 v0 + br_table v2, block3, jt0" + ); + } + #[test] fn switch_128bit() { let mut func = Function::new(); @@ -602,12 +643,12 @@ block0: jump block4 block4: - v1 = icmp_imm.i128 ugt v0, -1 + v1 = icmp_imm.i128 ugt v0, 0xffff_ffff brnz v1, block3 jump block5 block5: - v2 = ireduce.i64 v0 + v2 = ireduce.i32 v0 br_table v2, block3, jt0" ); }