thepowersgang opened Issue #1323:
Steps to reproduce:
- Structure code to seal blocks early (instead of sealing in bulk)
- Use
cranelift_frontend::Switch
to generate a sparse switch such that it generates chained comparisons instead of a jump table.- Observe debug assertion regarding unsealed blocks.
Version:
- As of current HEAD (832666c45ead73fd833ea86da94cacb2f30a530c), there is no reference to
seal_block
in theswitch
module. Issue originally seen withv0.58
fromcrates.io
thepowersgang labeled Issue #1323:
Steps to reproduce:
- Structure code to seal blocks early (instead of sealing in bulk)
- Use
cranelift_frontend::Switch
to generate a sparse switch such that it generates chained comparisons instead of a jump table.- Observe debug assertion regarding unsealed blocks.
Version:
- As of current HEAD (832666c45ead73fd833ea86da94cacb2f30a530c), there is no reference to
seal_block
in theswitch
module. Issue originally seen withv0.58
fromcrates.io
thepowersgang labeled Issue #1323:
Steps to reproduce:
- Structure code to seal blocks early (instead of sealing in bulk)
- Use
cranelift_frontend::Switch
to generate a sparse switch such that it generates chained comparisons instead of a jump table.- Observe debug assertion regarding unsealed blocks.
Version:
- As of current HEAD (832666c45ead73fd833ea86da94cacb2f30a530c), there is no reference to
seal_block
in theswitch
module. Issue originally seen withv0.58
fromcrates.io
teapotd commented on Issue #1323:
Example:
let mut func = Function::new(); let mut builder_ctx = FunctionBuilderContext::new(); let mut builder = FunctionBuilder::new(&mut func, &mut builder_ctx); let block0 = builder.create_block(); let block1 = builder.create_block(); let block2 = builder.create_block(); let block3 = builder.create_block(); builder.seal_block(block0); builder.switch_to_block(block0); let val = builder.ins().iconst(types::I32, 2); let mut switch = Switch::new(); switch.set_entry(2, block1); switch.set_entry(4, block2); switch.emit(&mut builder, val, block3); for &block in &[block1, block2, block3] { builder.seal_block(block); builder.switch_to_block(block); builder.ins().return_(&[]); } builder.finalize(); // panic: 'all blocks should be sealed before dropping a FunctionBuilder' dbg!(func);This panics in
finalize
, becauseSwitch
generates additional blocks and it doesn't seal them:function u0:0() fast { block0: v0 = iconst.i32 2 v1 = icmp_imm eq v0, 4 brnz v1, block2 jump block4 block4: ; this block is not sealed v2 = icmp_imm.i32 eq v0, 2 brnz v2, block1 jump block3 block1: return block2: return block3: return }An obvious way to fix this issue would be to seal generated blocks when switch is built, but it would break code that seal sections in bulk using
seal_all_blocks
:let mut func = Function::new(); let mut builder_ctx = FunctionBuilderContext::new(); let mut builder = FunctionBuilder::new(&mut func, &mut builder_ctx); let block0 = builder.create_block(); builder.seal_block(block0); builder.seal_all_blocks(); // panic: 'Attempting to seal block0 which is already sealed.'We could change
seal_all_blocks
to ignore already sealed blocks instead of panicking.
thepowersgang commented on Issue #1323:
I feel that having
Switch::emit
(configurably) seal created blocks is the more correct option from a "user" point of view. Needing to callseal_all_blocks
just because you used aSwitch
prevents you from catching cases where you forgot to seal one of your own blocks.
abrown closed Issue #1323:
Steps to reproduce:
- Structure code to seal blocks early (instead of sealing in bulk)
- Use
cranelift_frontend::Switch
to generate a sparse switch such that it generates chained comparisons instead of a jump table.- Observe debug assertion regarding unsealed blocks.
Version:
- As of current HEAD (832666c45ead73fd833ea86da94cacb2f30a530c), there is no reference to
seal_block
in theswitch
module. Issue originally seen withv0.58
fromcrates.io
Last updated: Dec 23 2024 at 12:05 UTC