Generate Python 3.11+ exception table from instruction handler info
(blocks: &[Block], block_to_index: &[u32])
| 2005 | |
| 2006 | /// Generate Python 3.11+ exception table from instruction handler info |
| 2007 | fn generate_exception_table(blocks: &[Block], block_to_index: &[u32]) -> Box<[u8]> { |
| 2008 | let mut entries: Vec<ExceptionTableEntry> = Vec::new(); |
| 2009 | let mut current_entry: Option<(ExceptHandlerInfo, u32)> = None; // (handler_info, start_index) |
| 2010 | let mut instr_index = 0u32; |
| 2011 | |
| 2012 | // Iterate through all instructions in block order |
| 2013 | // instr_index is the index into the final instructions array (including EXTENDED_ARG) |
| 2014 | // This matches how frame.rs uses lasti |
| 2015 | for (_, block) in iter_blocks(blocks) { |
| 2016 | for instr in &block.instructions { |
| 2017 | // instr_size includes EXTENDED_ARG and CACHE entries |
| 2018 | let instr_size = instr.arg.instr_size() as u32 + instr.cache_entries; |
| 2019 | |
| 2020 | match (¤t_entry, instr.except_handler) { |
| 2021 | // No current entry, no handler - nothing to do |
| 2022 | (None, None) => {} |
| 2023 | |
| 2024 | // No current entry, handler starts - begin new entry |
| 2025 | (None, Some(handler)) => { |
| 2026 | current_entry = Some((handler, instr_index)); |
| 2027 | } |
| 2028 | |
| 2029 | // Current entry exists, same handler - continue |
| 2030 | (Some((curr_handler, _)), Some(handler)) |
| 2031 | if curr_handler.handler_block == handler.handler_block |
| 2032 | && curr_handler.stack_depth == handler.stack_depth |
| 2033 | && curr_handler.preserve_lasti == handler.preserve_lasti => {} |
| 2034 | |
| 2035 | // Current entry exists, different handler - finish current, start new |
| 2036 | (Some((curr_handler, start)), Some(handler)) => { |
| 2037 | let target_index = block_to_index[curr_handler.handler_block.idx()]; |
| 2038 | entries.push(ExceptionTableEntry::new( |
| 2039 | *start, |
| 2040 | instr_index, |
| 2041 | target_index, |
| 2042 | curr_handler.stack_depth as u16, |
| 2043 | curr_handler.preserve_lasti, |
| 2044 | )); |
| 2045 | current_entry = Some((handler, instr_index)); |
| 2046 | } |
| 2047 | |
| 2048 | // Current entry exists, no handler - finish current entry |
| 2049 | (Some((curr_handler, start)), None) => { |
| 2050 | let target_index = block_to_index[curr_handler.handler_block.idx()]; |
| 2051 | entries.push(ExceptionTableEntry::new( |
| 2052 | *start, |
| 2053 | instr_index, |
| 2054 | target_index, |
| 2055 | curr_handler.stack_depth as u16, |
| 2056 | curr_handler.preserve_lasti, |
| 2057 | )); |
| 2058 | current_entry = None; |
| 2059 | } |
| 2060 | } |
| 2061 | |
| 2062 | instr_index += instr_size; // Account for EXTENDED_ARG instructions |
| 2063 | } |
| 2064 | } |
no test coverage detected