phase29ao(p7): verify edgeargs layout for valuejoin (unconnected)

This commit is contained in:
2025-12-30 05:36:06 +09:00
parent 3478b0f716
commit bda1309a51
7 changed files with 115 additions and 7 deletions

View File

@ -22,6 +22,7 @@ mod pattern9_accum_const_loop;
mod pattern_scan_with_init;
mod pattern_split_scan;
mod skeleton_loop;
mod value_join_args;
mod common;
use super::{

View File

@ -0,0 +1,17 @@
use crate::mir::basic_block::EdgeArgs;
use crate::mir::join_ir::lowering::inline_boundary::JumpArgsLayout;
use crate::mir::ValueId;
#[allow(dead_code)]
pub(super) fn expr_result_plus_carriers_args(
expr_result: ValueId,
carriers: Vec<ValueId>,
) -> EdgeArgs {
let mut values = Vec::with_capacity(1 + carriers.len());
values.push(expr_result);
values.extend(carriers);
EdgeArgs {
layout: JumpArgsLayout::ExprResultPlusCarriers,
values,
}
}

View File

@ -23,7 +23,9 @@
//! Phase 273 P3: V1 (Carrier completeness) removed with CoreCarrierInfo
use super::{CoreEffectPlan, CoreExitPlan, CoreIfPlan, CoreLoopPlan, CorePlan};
use crate::mir::basic_block::EdgeArgs;
use crate::mir::builder::control_flow::plan::normalize::CanonicalLoopFacts;
use crate::mir::join_ir::lowering::inline_boundary::JumpArgsLayout;
use crate::mir::ValueId;
/// Phase 273 P1: PlanVerifier - CorePlan 不変条件検証 (fail-fast)
@ -152,6 +154,32 @@ impl PlanVerifier {
Self::verify_value_id_basic(*val, depth, &format!("final_values[{}]", i))?;
}
// Verify EdgeArgs layout (V13)
for (i, wire) in loop_plan.frag.wires.iter().enumerate() {
Self::verify_edge_args_layout(&wire.args, depth, &format!("frag.wires[{}]", i))?;
}
for (kind, stubs) in loop_plan.frag.exits.iter() {
for (i, stub) in stubs.iter().enumerate() {
Self::verify_edge_args_layout(
&stub.args,
depth,
&format!("frag.exits[{}][{}]", kind, i),
)?;
}
}
for (i, branch) in loop_plan.frag.branches.iter().enumerate() {
Self::verify_edge_args_layout(
&branch.then_args,
depth,
&format!("frag.branches[{}].then", i),
)?;
Self::verify_edge_args_layout(
&branch.else_args,
depth,
&format!("frag.branches[{}].else", i),
)?;
}
Ok(())
}
@ -331,6 +359,22 @@ impl PlanVerifier {
let _ = (value_id, depth, context);
Ok(())
}
fn verify_edge_args_layout(
args: &EdgeArgs,
depth: usize,
context: &str,
) -> Result<(), String> {
if matches!(args.layout, JumpArgsLayout::ExprResultPlusCarriers)
&& args.values.is_empty()
{
return Err(format!(
"[V13] EdgeArgs at depth {} {} requires expr_result value",
depth, context
));
}
Ok(())
}
}
#[cfg(debug_assertions)]
@ -350,7 +394,8 @@ pub(in crate::mir::builder) fn debug_assert_value_join_invariants(_facts: &Canon
mod tests {
use super::*;
use crate::mir::{BasicBlockId, ConstValue, ValueId};
use crate::mir::builder::control_flow::edgecfg::api::Frag;
use crate::mir::basic_block::EdgeArgs;
use crate::mir::builder::control_flow::edgecfg::api::{EdgeStub, ExitKind, Frag};
use crate::mir::builder::control_flow::plan::CorePhiInfo;
use crate::mir::builder::control_flow::plan::facts::feature_facts::{
LoopFeatureFacts, ValueJoinFacts,
@ -363,6 +408,7 @@ mod tests {
SkeletonFacts, SkeletonKind,
};
use crate::mir::builder::control_flow::plan::normalize::canonicalize_loop_facts;
use crate::mir::join_ir::lowering::inline_boundary::JumpArgsLayout;
use std::collections::BTreeMap;
fn make_loop_plan(body: Vec<CorePlan>) -> CoreLoopPlan {
@ -520,6 +566,41 @@ mod tests {
assert!(result.unwrap_err().contains("[V11]"));
}
#[test]
fn test_verify_expr_result_plus_carriers_requires_value() {
let mut loop_plan = make_loop_plan(vec![]);
loop_plan.frag.wires = vec![EdgeStub {
from: loop_plan.body_bb,
kind: ExitKind::Normal,
target: Some(loop_plan.step_bb),
args: EdgeArgs {
layout: JumpArgsLayout::ExprResultPlusCarriers,
values: vec![],
},
}];
let plan = CorePlan::Loop(loop_plan);
let result = PlanVerifier::verify(&plan);
assert!(result.is_err());
assert!(result.unwrap_err().contains("[V13]"));
}
#[test]
fn test_verify_expr_result_plus_carriers_with_value_ok() {
let mut loop_plan = make_loop_plan(vec![]);
loop_plan.frag.wires = vec![EdgeStub {
from: loop_plan.body_bb,
kind: ExitKind::Normal,
target: Some(loop_plan.step_bb),
args: EdgeArgs {
layout: JumpArgsLayout::ExprResultPlusCarriers,
values: vec![ValueId(200)],
},
}];
let plan = CorePlan::Loop(loop_plan);
let result = PlanVerifier::verify(&plan);
assert!(result.is_ok());
}
#[cfg(debug_assertions)]
#[test]
fn debug_value_join_invariant_allows_empty_when_not_needed() {