def insert_uninit_checks(ir: FuncIR) -> None: # Remove dead blocks from the CFG, which helps avoid spurious # checks due to unused error handling blocks. cleanup_cfg(ir.blocks) cfg = get_cfg(ir.blocks) must_defined = analyze_must_defined_regs( ir.blocks, cfg, set(ir.arg_regs), all_values(ir.arg_regs, ir.blocks)) ir.blocks = split_blocks_at_uninits(ir.blocks, must_defined.before)
def insert_uninit_checks(ir: FuncIR) -> None: # Remove dead blocks from the CFG, which helps avoid spurious # checks due to unused error handling blocks. cleanup_cfg(ir.blocks) cfg = get_cfg(ir.blocks) args = set(reg for reg in ir.env.regs() if ir.env.indexes[reg] < len(ir.args)) must_defined = analyze_must_defined_regs(ir.blocks, cfg, args, ir.env.regs()) ir.blocks = split_blocks_at_uninits(ir.env, ir.blocks, must_defined.before)
def insert_exception_handling(ir: FuncIR) -> None: # Generate error block if any ops may raise an exception. If an op # fails without its own error handler, we'll branch to this # block. The block just returns an error value. error_label = None for block in ir.blocks: can_raise = any(op.can_raise() for op in block.ops) if can_raise: error_label = add_handler_block(ir) break if error_label: ir.blocks = split_blocks_at_errors(ir.blocks, error_label, ir.traceback_name)