fix(regalloc): nested 子模块引用父槽无预着色保护致读错物理槽(B014)
子模块 alloc 时引用父槽的 LOAD_VAR.a/STORE_VAR.rd 被当作自身 vreg 染色移走, 父侧 collect_escaped 只保护父不移动槽,子侧无对称保护。以 param_layout.base (inherited_reg_start 分界)识别父槽引用并预着色恒等,spill 自由色排除。 新增 nested_parent_slot_regress 回归测试(field/method + 高压力变量), workspace 全绿 + clippy 干净。
This commit is contained in:
@@ -269,6 +269,9 @@ pub(super) fn spilled_builtin_bindings(f: &IRFunction, map: &AllocMap) -> Vec<(S
|
||||
}
|
||||
// escaped 色(递归 nested 的 LOAD_VAR.a / STORE_VAR.rd)
|
||||
collect_escaped(&f.nested, &mut excluded);
|
||||
// own-escaped 色(B013 延伸):本函数 LOAD_VAR.a / STORE_VAR.rd 引用父槽(< base)。
|
||||
// 与 graph.rs collect_own_escaped 对称——spill 自由色不得占用父槽号。
|
||||
collect_own_escaped(f, &mut excluded);
|
||||
// 窗口
|
||||
for c in map.arg_window_base..=253 {
|
||||
excluded.push(c);
|
||||
@@ -321,6 +324,27 @@ fn collect_escaped(nested: &[IRFunction], out: &mut Vec<u32>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// 收集本函数 LOAD_VAR.a / STORE_VAR.rd 中引用父槽(槽号 < param_layout.base)的 vreg。
|
||||
/// 与 graph.rs::collect_own_escaped 对称:base = emit inherited_reg_start 分界线。
|
||||
fn collect_own_escaped(f: &IRFunction, out: &mut Vec<u32>) {
|
||||
let base = f.param_layout.base;
|
||||
if base == 0 {
|
||||
return;
|
||||
}
|
||||
for inst in &f.insts {
|
||||
let slot = match inst.op {
|
||||
OpCode::LOAD_VAR => inst.a,
|
||||
OpCode::STORE_VAR => inst.rd,
|
||||
_ => Operand::None,
|
||||
};
|
||||
if let Operand::Reg(r) = slot {
|
||||
if r < base {
|
||||
out.push(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user