Files
OxideJS-New/crates/oxide_fold/src/lib.rs
T

46 lines
2.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 常量折叠 pass:单向前扫常量传播加就地改写(IR 层)。
//!
//! `fold` 对每个函数(递归 nested,每个 nested 函数有独立常量池与指令流,独立前扫)
//! 运行单向前扫:维护 per-register known 表记录各虚拟寄存器的已知常量值,命中
//! 改写表即就地改写——A 组一元与算术常量折叠改写为 `LOAD_CONST`(新常量入池),
//! C 组位运算与比较常量折叠改写为 `LOAD_CONST`(新常量入池),B 组逻辑短路
//! 改写为 `MOV`(无新常量)。
//!
//! 不变量:
//! - 不删指令、不重映射 `label_pos`:改写只改变指令的 op 与操作数,不改变跳转
//! 结构,CFG 的块划分与边集不变,由下游 DCE 在折叠后的指令流上重建 CFG 吸收。
//! - 汇合点健全性:`label_pos` 指向的指令下标(控制流汇合点)整体清空 known 表,
//! 跨汇合的陈旧知识不用于折叠。
//! - 负零守卫:算术折叠做实际运算(f64 加),不取恒等捷径——`-0.0 + 0.0` 得
//! `+0.0`(`Object.is` 可区分)。
//! - 池溢出守卫:常量池满(`u16::MAX`)时 A 组与 C 组改写禁用(不新增常量),
//! B 组(MOV)不受影响;`const_overflow` 已被 emit 层置位时整个 pass 跳过。
//!
//! 折值计算复用 `oxide_runtime_api::coercion` 的纯函数族(`to_number` /
//! `to_int32` / `to_uint32` / `to_boolean` / `relational_compare` /
//! `abstract_eq_primitives` / `strict_equality`),与 emit 层字面量折叠同源,
//! 杜绝两层折叠各自镜像运行时语义的漂移风险。
mod fold_log;
mod fold_table;
mod propagate;
use oxide_ir::IRFunction;
/// 常量传播与折叠:对函数(递归 nested)单向前扫,就地改写。
///
/// 返回是否发生改写(仅调试日志用)。接在 emit 与 DCE 之间:改写后失去消费者
/// 的 `LOAD_CONST` 与死 `MOV` 由下游 DCE 清理,本 pass 不删指令。
pub fn fold(f: &mut IRFunction) -> bool {
let mut changed = propagate::fold_function(f);
for nested in f.nested.iter_mut() {
if fold(nested) {
changed = true;
}
}
if changed {
fold_info!("fold: rewrites applied");
}
changed
}