luaur_code_gen/functions/
const_prop_in_block_chain.rs1use 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}