Skip to main content

luaur_code_gen/functions/
const_prop_in_block_chain.rs

1use crate::enums::ir_block_kind::IrBlockKind;
2use crate::enums::ir_cmd::IrCmd;
3use crate::enums::ir_op_kind::IrOpKind;
4use crate::functions::const_prop_in_block::const_prop_in_block;
5use crate::functions::get_live_out_value_count::get_live_out_value_count;
6use crate::functions::save_block_exit_state::save_block_exit_state;
7use crate::functions::setup_block_entry_state_optimize_const_prop::setup_block_entry_state_ir_builder_ir_function_ir_block_const_prop_state;
8use crate::macros::codegen_assert::CODEGEN_ASSERT;
9use crate::macros::op_a::op_a;
10use crate::records::const_prop_state::ConstPropState;
11use crate::records::ir_block::IrBlock;
12use crate::records::ir_builder::IrBuilder;
13use luaur_common::FFlag;
14
15pub fn const_prop_in_block_chain(
16    build: &mut IrBuilder,
17    visited: &mut Vec<u8>,
18    mut block: *mut IrBlock,
19    state: &mut ConstPropState,
20) {
21    let function = &mut build.function as *mut _;
22
23    state.clear();
24
25    unsafe {
26        setup_block_entry_state_ir_builder_ir_function_ir_block_const_prop_state(
27            build,
28            &mut *function,
29            &*block,
30            state,
31        );
32    }
33
34    let start_sortkey = unsafe { (*block).sortkey };
35    let mut chain_pos = 0u32;
36    let mut last_block: *mut IrBlock = core::ptr::null_mut();
37
38    while !block.is_null() {
39        let block_idx = unsafe { (&*function).get_block_index(&*block) };
40        CODEGEN_ASSERT!(visited[block_idx as usize] == 0);
41        visited[block_idx as usize] = 1;
42
43        unsafe {
44            if state.in_safe_env && ((*block).flags & (1 << 0)) != 0 {
45                (*block).flags &= !(1 << 0);
46            }
47
48            const_prop_in_block(build, &mut *block, state);
49
50            if (*block).kind == IrBlockKind::Dead {
51                break;
52            }
53
54            (*block).sortkey = start_sortkey;
55            (*block).chainkey = chain_pos;
56            chain_pos += 1;
57
58            let term = (&mut (*function).instructions)[(*block).finish as usize].clone();
59            let mut next_block: *mut IrBlock = core::ptr::null_mut();
60
61            if term.cmd == IrCmd::JUMP {
62                let target_op = op_a(&mut term.clone());
63                if target_op.kind() == IrOpKind::Block {
64                    let target_idx = target_op.index();
65                    let target =
66                        &mut (&mut (*function).blocks)[target_idx as usize] as *mut IrBlock;
67
68                    if (*target).use_count == 1
69                        && visited[target_idx as usize] == 0
70                        && (*target).kind != IrBlockKind::Fallback
71                    {
72                        if get_live_out_value_count(&mut *function, &mut *target) != 0 {
73                            if FFlag::LuauCodegenRecordAllBlockExitInfo.get() {
74                                save_block_exit_state(&mut *function, &*block, state);
75                            } else {
76                                last_block = block;
77                            }
78                            break;
79                        }
80
81                        (*block).expected_next_block = target_idx;
82                        next_block = target;
83                    }
84                }
85            }
86
87            if FFlag::LuauCodegenRecordAllBlockExitInfo.get() {
88                save_block_exit_state(&mut *function, &*block, state);
89            } else {
90                last_block = block;
91            }
92
93            block = next_block;
94        }
95    }
96
97    if !FFlag::LuauCodegenRecordAllBlockExitInfo.get() && !last_block.is_null() {
98        unsafe {
99            save_block_exit_state(&mut *function, &*last_block, state);
100        }
101    }
102}