Seal blocks created by cranelift_frontend::Switch
This commit is contained in:
@@ -160,6 +160,9 @@ impl Switch {
|
|||||||
bx.ins().brnz(should_take_right_side, right_block, &[]);
|
bx.ins().brnz(should_take_right_side, right_block, &[]);
|
||||||
bx.ins().jump(left_block, &[]);
|
bx.ins().jump(left_block, &[]);
|
||||||
|
|
||||||
|
bx.seal_block(left_block);
|
||||||
|
bx.seal_block(right_block);
|
||||||
|
|
||||||
stack.push((Some(left_block), left));
|
stack.push((Some(left_block), left));
|
||||||
stack.push((Some(right_block), right));
|
stack.push((Some(right_block), right));
|
||||||
}
|
}
|
||||||
@@ -181,6 +184,7 @@ impl Switch {
|
|||||||
if was_branch {
|
if was_branch {
|
||||||
let block = bx.create_block();
|
let block = bx.create_block();
|
||||||
bx.ins().jump(block, &[]);
|
bx.ins().jump(block, &[]);
|
||||||
|
bx.seal_block(block);
|
||||||
bx.switch_to_block(block);
|
bx.switch_to_block(block);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -203,6 +207,7 @@ impl Switch {
|
|||||||
// if `first_index` is 0, then `icmp_imm uge val, first_index` is trivially true
|
// if `first_index` is 0, then `icmp_imm uge val, first_index` is trivially true
|
||||||
let jt_block = bx.create_block();
|
let jt_block = bx.create_block();
|
||||||
bx.ins().jump(jt_block, &[]);
|
bx.ins().jump(jt_block, &[]);
|
||||||
|
bx.seal_block(jt_block);
|
||||||
cases_and_jt_blocks.push((first_index, jt_block, blocks));
|
cases_and_jt_blocks.push((first_index, jt_block, blocks));
|
||||||
// `jump otherwise` below must not be hit, because the current block has been
|
// `jump otherwise` below must not be hit, because the current block has been
|
||||||
// filled above. This is the last iteration anyway, as 0 is the smallest
|
// filled above. This is the last iteration anyway, as 0 is the smallest
|
||||||
@@ -218,6 +223,7 @@ impl Switch {
|
|||||||
first_index as i64,
|
first_index as i64,
|
||||||
);
|
);
|
||||||
bx.ins().brnz(is_good_val, jt_block, &[]);
|
bx.ins().brnz(is_good_val, jt_block, &[]);
|
||||||
|
bx.seal_block(jt_block);
|
||||||
cases_and_jt_blocks.push((first_index, jt_block, blocks));
|
cases_and_jt_blocks.push((first_index, jt_block, blocks));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -488,4 +494,40 @@ block4:
|
|||||||
br_table.i32 v1, block0, jt0"
|
br_table.i32 v1, block0, jt0"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn switch_seal_generated_blocks() {
|
||||||
|
let keys = [0, 1, 2, 10, 11, 12, 20, 30, 40, 50];
|
||||||
|
|
||||||
|
let mut func = Function::new();
|
||||||
|
let mut builder_ctx = FunctionBuilderContext::new();
|
||||||
|
let mut builder = FunctionBuilder::new(&mut func, &mut builder_ctx);
|
||||||
|
|
||||||
|
let root_block = builder.create_block();
|
||||||
|
let default_block = builder.create_block();
|
||||||
|
let mut switch = Switch::new();
|
||||||
|
|
||||||
|
let case_blocks = keys
|
||||||
|
.iter()
|
||||||
|
.map(|key| {
|
||||||
|
let block = builder.create_block();
|
||||||
|
switch.set_entry(*key, block);
|
||||||
|
block
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
builder.seal_block(root_block);
|
||||||
|
builder.switch_to_block(root_block);
|
||||||
|
|
||||||
|
let val = builder.ins().iconst(types::I32, 1);
|
||||||
|
switch.emit(&mut builder, val, default_block);
|
||||||
|
|
||||||
|
for &block in case_blocks.iter().chain(std::iter::once(&default_block)) {
|
||||||
|
builder.seal_block(block);
|
||||||
|
builder.switch_to_block(block);
|
||||||
|
builder.ins().return_(&[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.finalize(); // Will panic if some blocks are not sealed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user