2025-11-17 11:28:18 +09:00
|
|
|
use crate::ast::{ASTNode, BinaryOperator, LiteralValue, Span};
|
|
|
|
|
use crate::mir::{MirCompiler, MirVerifier};
|
|
|
|
|
|
|
|
|
|
fn lit_i(i: i64) -> ASTNode {
|
|
|
|
|
ASTNode::Literal {
|
|
|
|
|
value: LiteralValue::Integer(i),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn bin(op: BinaryOperator, l: ASTNode, r: ASTNode) -> ASTNode {
|
|
|
|
|
ASTNode::BinaryOp {
|
|
|
|
|
operator: op,
|
|
|
|
|
left: Box::new(l),
|
|
|
|
|
right: Box::new(r),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Basic PHI/SSA sanity: simple counted loop must verify without Undefined value.
|
|
|
|
|
#[test]
|
|
|
|
|
fn mir_phi_basic_counted_loop_verifies() {
|
|
|
|
|
// i = 0;
|
|
|
|
|
// loop (i < 3) {
|
|
|
|
|
// i = i + 1;
|
|
|
|
|
// }
|
|
|
|
|
// return i;
|
|
|
|
|
let ast = ASTNode::Program {
|
|
|
|
|
statements: vec![
|
|
|
|
|
ASTNode::Assignment {
|
|
|
|
|
target: Box::new(ASTNode::Variable {
|
|
|
|
|
name: "i".into(),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
}),
|
|
|
|
|
value: Box::new(lit_i(0)),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
},
|
|
|
|
|
ASTNode::Loop {
|
|
|
|
|
condition: Box::new(bin(
|
|
|
|
|
BinaryOperator::LessThan,
|
|
|
|
|
ASTNode::Variable {
|
|
|
|
|
name: "i".into(),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
},
|
|
|
|
|
lit_i(3),
|
|
|
|
|
)),
|
|
|
|
|
body: vec![ASTNode::Assignment {
|
|
|
|
|
target: Box::new(ASTNode::Variable {
|
|
|
|
|
name: "i".into(),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
}),
|
|
|
|
|
value: Box::new(bin(
|
|
|
|
|
BinaryOperator::Add,
|
|
|
|
|
ASTNode::Variable {
|
|
|
|
|
name: "i".into(),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
},
|
|
|
|
|
lit_i(1),
|
|
|
|
|
)),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
}],
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
},
|
|
|
|
|
ASTNode::Return {
|
|
|
|
|
value: Some(Box::new(ASTNode::Variable {
|
|
|
|
|
name: "i".into(),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
})),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let mut mc = MirCompiler::with_options(false);
|
|
|
|
|
let cr = mc.compile(ast).expect("compile");
|
|
|
|
|
|
|
|
|
|
let mut verifier = MirVerifier::new();
|
|
|
|
|
if let Err(errors) = verifier.verify_module(&cr.module) {
|
|
|
|
|
for e in &errors {
|
2025-11-18 06:39:45 +09:00
|
|
|
eprintln!("[rust-mir-verify] {}", e);
|
2025-11-17 11:28:18 +09:00
|
|
|
}
|
|
|
|
|
panic!("MIR verification failed for basic counted loop");
|
|
|
|
|
}
|
|
|
|
|
}
|