test(cfg): 各 Pass 模块补模块级单测,测试随实现拆分

This commit is contained in:
爱特每羊队
2026-08-06 14:09:03 +08:00
parent f7111b4658
commit ca46cf842e
4 changed files with 217 additions and 0 deletions
+61
View File
@@ -34,3 +34,64 @@ pub(super) fn partition_blocks(f: &IRFunction) -> Vec<bool> {
}
heads
}
#[cfg(test)]
mod tests {
use super::*;
use oxide_ir::inst::Inst;
/// 线性无跳转函数:仅 entry 为块头,其余位置非块头。
#[test]
fn linear_function_only_entry_is_head() {
let mut f = IRFunction::new();
f.insts.push(Inst::new(OpCode::NOP, Operand::None, Operand::None, Operand::None));
f.insts.push(Inst::new(OpCode::NOP, Operand::None, Operand::None, Operand::None));
f.insts.push(Inst::new(OpCode::RETURN, Operand::None, Operand::None, Operand::None));
let heads = partition_blocks(&f);
assert_eq!(heads, vec![true, false, false, false], "仅 inst 0 是块头");
}
/// label 目标是块头:`label_pos` 指向的指令位置置 heads。
#[test]
fn label_target_is_head() {
let mut f = IRFunction::new();
f.insts.push(Inst::new(OpCode::NOP, Operand::None, Operand::None, Operand::None)); // 0
f.insts.push(Inst::new(OpCode::NOP, Operand::None, Operand::None, Operand::None)); // 1: label 0 目标
f.insts.push(Inst::new(OpCode::RETURN, Operand::None, Operand::None, Operand::None)); // 2
f.label_pos = vec![Some(1)];
f.label_count = 1;
let heads = partition_blocks(&f);
assert!(heads[0] && heads[1], "entry 与 label 目标都是块头");
assert!(!heads[2], "非块头位置保持 false");
}
/// 条件跳转的 fallthrough 后继是块头(否则 cond+then 融块、条件边丢失)。
#[test]
fn conditional_jump_fallthrough_successor_is_head() {
let mut f = IRFunction::new();
f.insts.push(Inst::jmp_if_false(1, 0)); // 0: cond → L0(else)
f.insts.push(Inst::new(OpCode::NOP, Operand::None, Operand::None, Operand::None)); // 1: then
f.insts.push(Inst::new(OpCode::RETURN, Operand::None, Operand::None, Operand::None)); // 2
f.label_pos = vec![Some(2)];
f.label_count = 1;
let heads = partition_blocks(&f);
assert!(heads[1], "条件跳转 fallthrough 后继是块头");
}
/// 无条件 JMP 的后继位置成块头(JMP 不 fallthrough,后续代码需独立成块,修复 Jump 边丢失)。
#[test]
fn unconditional_jmp_successor_is_head() {
let mut f = IRFunction::new();
f.insts.push(Inst::jmp(0)); // 0: → L0
f.insts.push(Inst::new(OpCode::NOP, Operand::None, Operand::None, Operand::None)); // 1: 独立块头
f.insts.push(Inst::new(OpCode::RETURN, Operand::None, Operand::None, Operand::None)); // 2
f.label_pos = vec![Some(2)];
f.label_count = 1;
let heads = partition_blocks(&f);
assert!(heads[1], "无条件 JMP 后继位置是块头");
}
}