Declare br_table otherwise ebb as predecessor (#551)
* Declare br_table otherwise ebb as predecessor (fixes #545)
This commit is contained in:
@@ -141,7 +141,10 @@ impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> {
|
|||||||
None => {
|
None => {
|
||||||
// branch_destination() doesn't detect jump_tables
|
// branch_destination() doesn't detect jump_tables
|
||||||
// If jump table we declare all entries successor
|
// If jump table we declare all entries successor
|
||||||
if let InstructionData::BranchTable { table, .. } = data {
|
if let InstructionData::BranchTable {
|
||||||
|
table, destination, ..
|
||||||
|
} = data
|
||||||
|
{
|
||||||
// Unlike all other jumps/branches, jump tables are
|
// Unlike all other jumps/branches, jump tables are
|
||||||
// capable of having the same successor appear
|
// capable of having the same successor appear
|
||||||
// multiple times, so we must deduplicate.
|
// multiple times, so we must deduplicate.
|
||||||
@@ -159,8 +162,13 @@ impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> {
|
|||||||
*dest_ebb,
|
*dest_ebb,
|
||||||
self.builder.position.basic_block.unwrap(),
|
self.builder.position.basic_block.unwrap(),
|
||||||
inst,
|
inst,
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
self.builder.func_ctx.ssa.declare_ebb_predecessor(
|
||||||
|
destination,
|
||||||
|
self.builder.position.basic_block.unwrap(),
|
||||||
|
inst,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,3 +77,76 @@ fn panic_on_define_after_finalize() {
|
|||||||
module.finalize_definitions();
|
module.finalize_definitions();
|
||||||
define_simple_function(&mut module);
|
define_simple_function(&mut module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn switch_error() {
|
||||||
|
use cranelift_codegen::settings;
|
||||||
|
|
||||||
|
let sig = Signature {
|
||||||
|
params: vec![AbiParam::new(types::I32)],
|
||||||
|
returns: vec![AbiParam::new(types::I32)],
|
||||||
|
call_conv: CallConv::SystemV,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
|
||||||
|
|
||||||
|
let mut func_ctx = FunctionBuilderContext::new();
|
||||||
|
{
|
||||||
|
let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut func, &mut func_ctx);
|
||||||
|
let start = bcx.create_ebb();
|
||||||
|
let bb0 = bcx.create_ebb();
|
||||||
|
let bb1 = bcx.create_ebb();
|
||||||
|
let bb2 = bcx.create_ebb();
|
||||||
|
let bb3 = bcx.create_ebb();
|
||||||
|
println!("{} {} {} {} {}", start, bb0, bb1, bb2, bb3);
|
||||||
|
|
||||||
|
bcx.declare_var(Variable::new(0), types::I32);
|
||||||
|
bcx.declare_var(Variable::new(1), types::I32);
|
||||||
|
let in_val = bcx.append_ebb_param(start, types::I32);
|
||||||
|
bcx.switch_to_block(start);
|
||||||
|
bcx.def_var(Variable::new(0), in_val);
|
||||||
|
bcx.ins().jump(bb0, &[]);
|
||||||
|
|
||||||
|
bcx.switch_to_block(bb0);
|
||||||
|
let discr = bcx.use_var(Variable::new(0));
|
||||||
|
let mut switch = cranelift_frontend::Switch::new();
|
||||||
|
for &(index, bb) in &[
|
||||||
|
(9, bb1),
|
||||||
|
(13, bb1),
|
||||||
|
(10, bb1),
|
||||||
|
(92, bb1),
|
||||||
|
(39, bb1),
|
||||||
|
(34, bb1),
|
||||||
|
] {
|
||||||
|
switch.set_entry(index, bb);
|
||||||
|
}
|
||||||
|
switch.emit(&mut bcx, discr, bb2);
|
||||||
|
|
||||||
|
bcx.switch_to_block(bb1);
|
||||||
|
let v = bcx.use_var(Variable::new(0));
|
||||||
|
bcx.def_var(Variable::new(1), v);
|
||||||
|
bcx.ins().jump(bb3, &[]);
|
||||||
|
|
||||||
|
bcx.switch_to_block(bb2);
|
||||||
|
let v = bcx.use_var(Variable::new(0));
|
||||||
|
bcx.def_var(Variable::new(1), v);
|
||||||
|
bcx.ins().jump(bb3, &[]);
|
||||||
|
|
||||||
|
bcx.switch_to_block(bb3);
|
||||||
|
let r = bcx.use_var(Variable::new(1));
|
||||||
|
bcx.ins().return_(&[r]);
|
||||||
|
|
||||||
|
bcx.seal_all_blocks();
|
||||||
|
bcx.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
let flags = settings::Flags::new(settings::builder());
|
||||||
|
match cranelift_codegen::verify_function(&func, &flags) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(err) => {
|
||||||
|
let pretty_error =
|
||||||
|
cranelift_codegen::print_errors::pretty_verifier_error(&func, None, None, err);
|
||||||
|
panic!("pretty_error:\n{}", pretty_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user