feat(mir): Phase 32 Step 0-3B - LoopRegion/LoopControlShape view methods
Phase 32 introduces a "view pattern" for loop structures, enabling gradual migration without breaking existing code. Changes: - control_form.rs: Add new ID types (LoopId, ExitEdgeId, ContinueEdgeId) and structures (LoopRegion, LoopControlShape, ExitEdge, ContinueEdge) - control_form.rs: Add view methods on LoopShape: - to_region_view() - returns LoopRegion - to_control_view() - returns LoopControlShape - to_exit_edges() - returns Vec<ExitEdge> - to_continue_edges() - returns Vec<ContinueEdge> - loop_scope_shape.rs: Use views in from_existing_boxes_legacy() - loop_to_join.rs: Add debug logging with Phase 32 views All 4 minimal lowerers (skip_ws/trim/append_defs/stage1) now use view-based block ID extraction via shared from_existing_boxes_legacy(). Tests: joinir_runner_standalone_*, joinir_vm_bridge_trim_* PASS 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -11,6 +11,121 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::mir::{BasicBlock, BasicBlockId, MirFunction};
|
use crate::mir::{BasicBlock, BasicBlockId, MirFunction};
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Phase 32: 新しい ID 型(LoopRegion / LoopControlShape 用)
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// ループを一意に識別する ID
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub struct LoopId(pub u32);
|
||||||
|
|
||||||
|
/// 出口辺を一意に識別する ID
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub struct ExitEdgeId(pub u32);
|
||||||
|
|
||||||
|
/// continue 辺を一意に識別する ID
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub struct ContinueEdgeId(pub u32);
|
||||||
|
|
||||||
|
/// ループラベル(将来の labeled break/continue 用)
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub struct LoopLabel(pub String);
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Phase 32: LoopRegion - ブロック集合 + ネスト構造
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// ループ領域を表す箱
|
||||||
|
///
|
||||||
|
/// LoopShape の「形だけ」から拡張して、ブロック集合とネスト関係を持つ。
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct LoopRegion {
|
||||||
|
/// このループの ID
|
||||||
|
pub id: LoopId,
|
||||||
|
/// ループ直前のブロック
|
||||||
|
pub preheader: BasicBlockId,
|
||||||
|
/// ループヘッダ(条件判定)
|
||||||
|
pub header: BasicBlockId,
|
||||||
|
/// ラッチブロック群(通常は1つだが、複数の場合もある)
|
||||||
|
pub latches: Vec<BasicBlockId>,
|
||||||
|
/// ループ内の全ブロック集合
|
||||||
|
pub blocks: BTreeSet<BasicBlockId>,
|
||||||
|
/// 親ループの ID(ネストの外側)
|
||||||
|
pub parent: Option<LoopId>,
|
||||||
|
/// 子ループの ID 群(ネストの内側)
|
||||||
|
pub children: Vec<LoopId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Phase 32: LoopControlShape - 制御フロー辺
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// ループの制御フロー辺を表す箱
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct LoopControlShape {
|
||||||
|
/// このループの ID
|
||||||
|
pub loop_id: LoopId,
|
||||||
|
/// continue 辺の ID 群
|
||||||
|
pub continues: Vec<ContinueEdgeId>,
|
||||||
|
/// 出口辺の ID 群
|
||||||
|
pub exits: Vec<ExitEdgeId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 出口辺を表す構造体
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ExitEdge {
|
||||||
|
/// この辺の ID
|
||||||
|
pub id: ExitEdgeId,
|
||||||
|
/// どのループからの出口か(冗長だけど便利)
|
||||||
|
pub loop_id: LoopId,
|
||||||
|
/// 出発ブロック
|
||||||
|
pub from: BasicBlockId,
|
||||||
|
/// 到着ブロック
|
||||||
|
pub to: BasicBlockId,
|
||||||
|
/// 出口の種類
|
||||||
|
pub kind: ExitKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 出口辺の種類
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub enum ExitKind {
|
||||||
|
/// while(cond) の cond が false
|
||||||
|
ConditionFalse,
|
||||||
|
/// break 文
|
||||||
|
Break {
|
||||||
|
/// labeled break 用(将来拡張)
|
||||||
|
label: Option<LoopLabel>,
|
||||||
|
},
|
||||||
|
/// ループ内 return
|
||||||
|
Return,
|
||||||
|
/// throw / panic 相当
|
||||||
|
Throw,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// continue 辺を表す構造体
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ContinueEdge {
|
||||||
|
/// この辺の ID
|
||||||
|
pub id: ContinueEdgeId,
|
||||||
|
/// どのループの continue か
|
||||||
|
pub loop_id: LoopId,
|
||||||
|
/// 出発ブロック
|
||||||
|
pub from: BasicBlockId,
|
||||||
|
/// 到着ブロック(通常は latch または header)
|
||||||
|
pub to: BasicBlockId,
|
||||||
|
/// continue の種類
|
||||||
|
pub kind: ContinueKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// continue 辺の種類
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub enum ContinueKind {
|
||||||
|
/// 通常の continue
|
||||||
|
Normal,
|
||||||
|
// 将来: Labeled { label: LoopLabel },
|
||||||
|
}
|
||||||
|
|
||||||
/// ループ構造の形だけを表す箱だよ。
|
/// ループ構造の形だけを表す箱だよ。
|
||||||
///
|
///
|
||||||
@ -168,6 +283,87 @@ pub fn is_control_form_trace_on() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LoopShape {
|
impl LoopShape {
|
||||||
|
// ========================================================================
|
||||||
|
// Phase 32: View メソッド(段階移行用)
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
/// LoopRegion ビューを生成するよ。
|
||||||
|
///
|
||||||
|
/// 既存の LoopShape から LoopRegion 形式に変換する。
|
||||||
|
/// blocks 集合は呼び出し側が後から設定するか、空のままでもOK。
|
||||||
|
pub fn to_region_view(&self, loop_id: LoopId) -> LoopRegion {
|
||||||
|
LoopRegion {
|
||||||
|
id: loop_id,
|
||||||
|
preheader: self.preheader,
|
||||||
|
header: self.header,
|
||||||
|
latches: vec![self.latch], // 既存 LoopShape は latch 1つ
|
||||||
|
blocks: BTreeSet::new(), // 呼び出し側で設定可能
|
||||||
|
parent: None, // ネスト情報は後から設定
|
||||||
|
children: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// LoopControlShape ビューを生成するよ。
|
||||||
|
///
|
||||||
|
/// 既存の LoopShape から LoopControlShape 形式に変換する。
|
||||||
|
/// 辺の ID は呼び出し側で管理するため、ここでは ID リストのみ返す。
|
||||||
|
pub fn to_control_view(&self, loop_id: LoopId) -> LoopControlShape {
|
||||||
|
// 辺の数だけ ID を振る(0始まり、呼び出し側でオフセット可能)
|
||||||
|
let continues: Vec<ContinueEdgeId> = self
|
||||||
|
.continue_targets
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, _)| ContinueEdgeId(i as u32))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let exits: Vec<ExitEdgeId> = self
|
||||||
|
.break_targets
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, _)| ExitEdgeId(i as u32))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
LoopControlShape {
|
||||||
|
loop_id,
|
||||||
|
continues,
|
||||||
|
exits,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 出口辺を生成するよ。
|
||||||
|
///
|
||||||
|
/// break_targets の情報から ExitEdge 群を生成する。
|
||||||
|
pub fn to_exit_edges(&self, loop_id: LoopId) -> Vec<ExitEdge> {
|
||||||
|
self.break_targets
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, &from)| ExitEdge {
|
||||||
|
id: ExitEdgeId(i as u32),
|
||||||
|
loop_id,
|
||||||
|
from,
|
||||||
|
to: self.exit,
|
||||||
|
kind: ExitKind::Break { label: None },
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// continue 辺を生成するよ。
|
||||||
|
///
|
||||||
|
/// continue_targets の情報から ContinueEdge 群を生成する。
|
||||||
|
pub fn to_continue_edges(&self, loop_id: LoopId) -> Vec<ContinueEdge> {
|
||||||
|
self.continue_targets
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, &from)| ContinueEdge {
|
||||||
|
id: ContinueEdgeId(i as u32),
|
||||||
|
loop_id,
|
||||||
|
from,
|
||||||
|
to: self.header, // continue は header に戻る
|
||||||
|
kind: ContinueKind::Normal,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// Debug ビルドでだけ呼ぶ用の簡易 invariant チェックだよ。
|
/// Debug ビルドでだけ呼ぶ用の簡易 invariant チェックだよ。
|
||||||
///
|
///
|
||||||
/// - preheader → header にエッジがあること
|
/// - preheader → header にエッジがあること
|
||||||
|
|||||||
@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
|
use crate::mir::control_form::LoopId;
|
||||||
use crate::mir::join_ir::lowering::exit_args_resolver::resolve_exit_args;
|
use crate::mir::join_ir::lowering::exit_args_resolver::resolve_exit_args;
|
||||||
use crate::mir::join_ir::lowering::loop_form_intake::LoopFormIntake;
|
use crate::mir::join_ir::lowering::loop_form_intake::LoopFormIntake;
|
||||||
use crate::mir::loop_form::LoopForm;
|
use crate::mir::loop_form::LoopForm;
|
||||||
@ -341,6 +342,11 @@ impl LoopScopeShape {
|
|||||||
/// Phase 30 F-3.1: 従来の既存箱ベース実装(legacy path)
|
/// Phase 30 F-3.1: 従来の既存箱ベース実装(legacy path)
|
||||||
///
|
///
|
||||||
/// analyze_case_a と分離することで、Case-A minimal だけ新パスを通せる。
|
/// analyze_case_a と分離することで、Case-A minimal だけ新パスを通せる。
|
||||||
|
///
|
||||||
|
/// # Phase 32 Step 3-B: View 経由でブロック情報を取得
|
||||||
|
///
|
||||||
|
/// 直接 `loop_form.header` などを読む代わりに、`to_region_view()` 経由で取得。
|
||||||
|
/// 現在は同じ結果だが、将来 LoopRegion が独自情報を持つようになった時に差し替え可能。
|
||||||
fn from_existing_boxes_legacy(
|
fn from_existing_boxes_legacy(
|
||||||
loop_form: &LoopForm,
|
loop_form: &LoopForm,
|
||||||
intake: &LoopFormIntake,
|
intake: &LoopFormIntake,
|
||||||
@ -348,11 +354,28 @@ impl LoopScopeShape {
|
|||||||
exit_live_box: &LoopExitLivenessBox,
|
exit_live_box: &LoopExitLivenessBox,
|
||||||
query: &impl MirQuery,
|
query: &impl MirQuery,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
// Extract block IDs from LoopForm
|
// Phase 32 Step 3-B: Extract block IDs via view (情報源を view に切り替え)
|
||||||
let header = loop_form.header;
|
let loop_id = LoopId(0); // 単一ループの場合は 0
|
||||||
let body = loop_form.body;
|
let region = loop_form.to_region_view(loop_id);
|
||||||
let latch = loop_form.latch;
|
let exit_edges = loop_form.to_exit_edges(loop_id);
|
||||||
let exit = loop_form.exit;
|
|
||||||
|
// View からブロック ID を取得
|
||||||
|
let header = region.header;
|
||||||
|
let body = loop_form.body; // body は region.blocks から推測が難しいので直接参照を維持
|
||||||
|
let latch = region.latches.first().copied().unwrap_or(loop_form.latch);
|
||||||
|
let exit = exit_edges.first().map(|e| e.to).unwrap_or(loop_form.exit);
|
||||||
|
|
||||||
|
// Debug: view 経由の情報をログ
|
||||||
|
if std::env::var("NYASH_LOOPSCOPE_DEBUG").is_ok() {
|
||||||
|
let control = loop_form.to_control_view(loop_id);
|
||||||
|
eprintln!(
|
||||||
|
"[loopscope/view] region.header={:?}, latches={}, exit_edges={}, control.exits={}",
|
||||||
|
region.header,
|
||||||
|
region.latches.len(),
|
||||||
|
exit_edges.len(),
|
||||||
|
control.exits.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Extract pinned and carriers from intake (already classified)
|
// Extract pinned and carriers from intake (already classified)
|
||||||
let pinned: BTreeSet<String> = intake.pinned_ordered.iter().cloned().collect();
|
let pinned: BTreeSet<String> = intake.pinned_ordered.iter().cloned().collect();
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
//! let join_module = lowerer.lower(func, &loop_form, &query)?;
|
//! let join_module = lowerer.lower(func, &loop_form, &query)?;
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use crate::mir::control_form::LoopId;
|
||||||
use crate::mir::join_ir::lowering::generic_case_a;
|
use crate::mir::join_ir::lowering::generic_case_a;
|
||||||
use crate::mir::join_ir::lowering::loop_form_intake::intake_loop_form;
|
use crate::mir::join_ir::lowering::loop_form_intake::intake_loop_form;
|
||||||
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
||||||
@ -108,6 +109,23 @@ impl LoopToJoinLowerer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phase 32 Step 3-A: View メソッドを使った構造確認(段階移行)
|
||||||
|
if self.debug {
|
||||||
|
let loop_id = LoopId(0); // 単一ループの場合は 0
|
||||||
|
let region = loop_form.to_region_view(loop_id);
|
||||||
|
let control = loop_form.to_control_view(loop_id);
|
||||||
|
let exit_edges = loop_form.to_exit_edges(loop_id);
|
||||||
|
let continue_edges = loop_form.to_continue_edges(loop_id);
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"[LoopToJoinLowerer] Phase 32 views: region.header={:?}, control.exits={}, exit_edges={}, continue_edges={}",
|
||||||
|
region.header,
|
||||||
|
control.exits.len(),
|
||||||
|
exit_edges.len(),
|
||||||
|
continue_edges.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Step 5: パターンに応じた lowering を実行
|
// Step 5: パターンに応じた lowering を実行
|
||||||
self.lower_with_scope(scope, func_name)
|
self.lower_with_scope(scope, func_name)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user