Fix an assertion failure with an empty Switch (#5650)

Fix an error introduced in #5644, where an unsigned subtraction from zero was possible with an empty Switch structure. Additionally, missing the empty case caused us to not emit a branch to the default block. This PR fixes the issue by detecting the empty Switch case early, and emitting a jump.
This commit is contained in:
Trevor Elliott
2023-01-27 17:46:11 -08:00
committed by GitHub
parent ffbcc67eb3
commit 20a216923b

View File

@@ -114,6 +114,12 @@ impl Switch {
otherwise: Block,
contiguous_case_ranges: &'a [ContiguousCaseRange],
) {
// If no switch cases were added to begin with, we can just emit `jump otherwise`.
if contiguous_case_ranges.is_empty() {
bx.ins().jump(otherwise, &[]);
return;
}
// Avoid allocation in the common case
if contiguous_case_ranges.len() <= 3 {
Self::build_search_branches(bx, val, otherwise, contiguous_case_ranges);
@@ -159,9 +165,8 @@ impl Switch {
otherwise: Block,
contiguous_case_ranges: &'a [ContiguousCaseRange],
) {
let last_ix = contiguous_case_ranges.len() - 1;
for (ix, range) in contiguous_case_ranges.iter().rev().enumerate() {
let alternate = if ix == last_ix {
for (ix, range) in contiguous_case_ranges.iter().enumerate().rev() {
let alternate = if ix == 0 {
otherwise
} else {
bx.create_block()
@@ -343,6 +348,7 @@ mod tests {
let block = bx.create_block();
bx.switch_to_block(block);
let val = bx.ins().iconst(types::I8, 0);
#[allow(unused_mut)]
let mut switch = Switch::new();
$(
let block = bx.create_block();
@@ -360,18 +366,28 @@ mod tests {
macro_rules! assert_eq_output {
($actual:ident, $expected:literal) => {
if $actual != $expected {
assert!(
false,
"\n{}",
similar::TextDiff::from_lines($expected, &$actual)
.unified_diff()
.header("expected", "actual")
);
}
assert_eq!(
$actual,
$expected,
"\n{}",
similar::TextDiff::from_lines($expected, &$actual)
.unified_diff()
.header("expected", "actual")
)
};
}
#[test]
fn switch_empty() {
let func = setup!(42, []);
assert_eq_output!(
func,
"block0:
v0 = iconst.i8 0
jump block42"
);
}
#[test]
fn switch_zero() {
let func = setup!(0, [0,]);