test(cfg): 各 Pass 模块补模块级单测,测试随实现拆分
This commit is contained in:
@@ -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 后继位置是块头");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user