feat: 调用实参 spread(f(...args) / new F(...args) / super(...args))

This commit is contained in:
爱特每羊队
2026-08-08 10:33:16 +08:00
parent ea86a2c0ac
commit 2777b00c82
14 changed files with 811 additions and 140 deletions
+10
View File
@@ -70,6 +70,15 @@ pub(super) fn collect_real_vregs(f: &IRFunction) -> BTreeSet<u32> {
}
}
}
// spread 调用系:ext 首字之后每个有序实参字是寄存器号(spread 源带高位标记)
if matches!(inst.op, OpCode::CALL_SPREAD | OpCode::NEW_EXPRESSION_SPREAD | OpCode::SUPER_CALL_SPREAD) {
for &w in inst.ext.iter().skip(1) {
let r = w & 0x7FFF_FFFF;
if r != 0 {
real.insert(r);
}
}
}
}
real
}
@@ -116,6 +125,7 @@ pub(super) fn build(
}
// ── 可分配色集 ──
// 窗口只为参数连续性 MOV 桥预留;spread 调用实参经 ext 逐个读寄存器,无连续性要求。
let max_nargs = f
.insts
.iter()
+41 -19
View File
@@ -134,7 +134,8 @@ pub(super) fn run(f: &mut IRFunction, map: &AllocMap) {
fn rewrite_inst(
f: &IRFunction, inst: &Inst, map: &AllocMap, slot_color: &BTreeMap<u32, u32>, i: usize,
) -> (Inst, Vec<(u32, u32)>) {
let nargs = inst.ext.first().copied().unwrap_or(0);
let raw_nargs = inst.ext.first().copied().unwrap_or(0);
let nargs = raw_nargs;
let first_arg = match inst.op {
OpCode::CALL | OpCode::CALL_NATIVE | OpCode::NEW_EXPRESSION => Some(inst.b),
OpCode::SUPER_CALL => Some(inst.a),
@@ -197,26 +198,34 @@ fn rewrite_inst(
let mut a = rewrite(inst.a);
let mut b = rewrite(inst.b);
// TEMPLATE_STR 的 ext 编码表达式寄存器(seg>>31==1 时低 8 位为 expr_reg)——必须随
// RegAlloc 重映射,否则读旧 vreg 号对应的物理槽(错值)。
let ext = if inst.op == OpCode::TEMPLATE_STR {
let mut ext = inst.ext.clone();
for seg in ext.iter_mut().skip(1) {
if *seg >> 31 == 1 {
let r = *seg & 0xFF;
let nr = if let Some(&c) = slot_color.get(&r) {
c
} else {
match map.map.get(&r) {
Some(Alloc::Phys(p)) => *p,
_ => r, // 非真实 vreg / spilled 未覆盖(防御保留原号)
}
};
*seg = (*seg & !0xFFu32) | (nr & 0xFF);
// RegAlloc 重映射,否则读旧 vreg 号对应的物理槽(错值)。spread 调用系 ext[1..] 每个
// 字是完整 spread 源 vreg,同样需重映射到物理号。
let ext = match inst.op {
OpCode::TEMPLATE_STR => {
let mut ext = inst.ext.clone();
for seg in ext.iter_mut().skip(1) {
if *seg >> 31 == 1 {
let r = *seg & 0xFF;
let nr = remap_ext_reg(r, slot_color, map);
*seg = (*seg & !0xFFu32) | (nr & 0xFF);
}
}
ext
}
ext
} else {
inst.ext.clone()
OpCode::CALL_SPREAD | OpCode::NEW_EXPRESSION_SPREAD | OpCode::SUPER_CALL_SPREAD => {
// 有序实参字:静态字直接重映射,spread 字保留高位标记、低 31 位重映射。
let mut ext = inst.ext.clone();
for seg in ext.iter_mut().skip(1) {
if *seg >> 31 == 1 {
let nr = remap_ext_reg(*seg & 0x7FFF_FFFF, slot_color, map);
*seg = 0x8000_0000 | nr;
} else {
*seg = remap_ext_reg(*seg, slot_color, map);
}
}
ext
}
_ => inst.ext.clone(),
};
// 调用点首参槽改指 arg_window_base(桥接后)
if let Some(ab) = arg_base {
@@ -257,6 +266,19 @@ fn rewrite_inst(
(Inst { op: inst.op, rd, a, b, ext }, arg_movs)
}
/// ext 内嵌寄存器重映射:优先用本指令点的 fresh 色(spilled vreg 的 use 点 UNSPILL),
/// 其次 AllocMap 物理色;未映射(防御)保留原号。
fn remap_ext_reg(r: u32, slot_color: &BTreeMap<u32, u32>, map: &AllocMap) -> u32 {
if let Some(&c) = slot_color.get(&r) {
c
} else {
match map.map.get(&r) {
Some(Alloc::Phys(p)) => *p,
_ => r,
}
}
}
/// terminator 判定:跳转族 + RETURN/HALT/THROW(def 结果必死,SPILL 跳过)。
fn is_terminator(op: OpCode) -> bool {
matches!(