Files
hakorune/src/mir/join_ir_vm_bridge/bridge.rs

479 lines
20 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use super::{convert_join_module_to_mir_with_meta, join_func_name, JoinIrVmBridgeError};
use crate::mir::join_ir::frontend::JoinFuncMetaMap;
use crate::mir::join_ir::JoinModule;
use crate::mir::MirModule;
use std::collections::BTreeMap;
/// Phase 256 P1.5: JoinModule が JoinIR ValueIds (100+ or 1000+) を含むか確認
fn module_has_joinir_value_ids(module: &JoinModule) -> bool {
for func in module.functions.values() {
// Check params
for param in &func.params {
if param.0 >= 100 { // PARAM_MIN
return true;
}
}
// Check instructions (all variants that can use ValueIds)
for inst in &func.body {
match inst {
crate::mir::join_ir::JoinInst::Call { args, dst, .. } => {
if let Some(d) = dst {
if d.0 >= 100 { return true; }
}
for arg in args {
if arg.0 >= 100 { return true; }
}
}
crate::mir::join_ir::JoinInst::Jump { args, cond, .. } => {
if let Some(c) = cond {
if c.0 >= 100 { return true; }
}
for arg in args {
if arg.0 >= 100 { return true; }
}
}
crate::mir::join_ir::JoinInst::Ret { value } => {
if let Some(v) = value {
if v.0 >= 100 { return true; }
}
}
crate::mir::join_ir::JoinInst::Select { dst, cond, then_val, else_val, .. } => {
if dst.0 >= 100 || cond.0 >= 100 || then_val.0 >= 100 || else_val.0 >= 100 {
return true;
}
}
crate::mir::join_ir::JoinInst::IfMerge { cond, merges, .. } => {
if cond.0 >= 100 { return true; }
for merge in merges {
if merge.dst.0 >= 100 || merge.then_val.0 >= 100 || merge.else_val.0 >= 100 {
return true;
}
}
}
crate::mir::join_ir::JoinInst::MethodCall { dst, receiver, args, .. } => {
if dst.0 >= 100 || receiver.0 >= 100 {
return true;
}
for arg in args {
if arg.0 >= 100 { return true; }
}
}
crate::mir::join_ir::JoinInst::ConditionalMethodCall { cond, dst, receiver, args, .. } => {
if cond.0 >= 100 || dst.0 >= 100 || receiver.0 >= 100 {
return true;
}
for arg in args {
if arg.0 >= 100 { return true; }
}
}
crate::mir::join_ir::JoinInst::FieldAccess { dst, object, .. } => {
if dst.0 >= 100 || object.0 >= 100 {
return true;
}
}
crate::mir::join_ir::JoinInst::NewBox { dst, args, .. } => {
if dst.0 >= 100 { return true; }
for arg in args {
if arg.0 >= 100 { return true; }
}
}
crate::mir::join_ir::JoinInst::NestedIfMerge { conds, merges, .. } => {
for cond in conds {
if cond.0 >= 100 { return true; }
}
for merge in merges {
if merge.dst.0 >= 100 || merge.then_val.0 >= 100 || merge.else_val.0 >= 100 {
return true;
}
}
}
crate::mir::join_ir::JoinInst::Compute(mi) => {
// Check actual ValueIds in MirLikeInst
match mi {
crate::mir::join_ir::MirLikeInst::Const { dst, .. } => {
if dst.0 >= 100 { return true; }
}
crate::mir::join_ir::MirLikeInst::BinOp { dst, lhs, rhs, .. } => {
if dst.0 >= 100 || lhs.0 >= 100 || rhs.0 >= 100 { return true; }
}
crate::mir::join_ir::MirLikeInst::Compare { dst, lhs, rhs, .. } => {
if dst.0 >= 100 || lhs.0 >= 100 || rhs.0 >= 100 { return true; }
}
crate::mir::join_ir::MirLikeInst::BoxCall { dst, args, .. } => {
if let Some(d) = dst {
if d.0 >= 100 { return true; }
}
for arg in args {
if arg.0 >= 100 { return true; }
}
}
crate::mir::join_ir::MirLikeInst::UnaryOp { dst, operand, .. } => {
if dst.0 >= 100 || operand.0 >= 100 { return true; }
}
crate::mir::join_ir::MirLikeInst::Print { value } => {
if value.0 >= 100 { return true; }
}
crate::mir::join_ir::MirLikeInst::Select { dst, cond, then_val, else_val } => {
if dst.0 >= 100 || cond.0 >= 100 || then_val.0 >= 100 || else_val.0 >= 100 {
return true;
}
}
}
}
}
}
}
false
}
fn ensure_joinir_function_aliases(mir_module: &mut MirModule, join_module: &JoinModule) {
for (func_id, join_func) in &join_module.functions {
let generated_name = join_func_name(*func_id);
let function = mir_module
.functions
.get(&join_func.name)
.or_else(|| mir_module.functions.get(&generated_name))
.cloned();
if let Some(function) = function {
if !mir_module.functions.contains_key(&join_func.name) {
mir_module
.functions
.insert(join_func.name.clone(), function.clone());
}
if !mir_module.functions.contains_key(&generated_name) {
mir_module
.functions
.insert(generated_name.clone(), function.clone());
}
let actual_arity = format!("{}/{}", join_func.name, join_func.params.len());
if !mir_module.functions.contains_key(&actual_arity) {
mir_module
.functions
.insert(actual_arity, function.clone());
}
let generated_arity = format!("{}/{}", generated_name, join_func.params.len());
if !mir_module.functions.contains_key(&generated_arity) {
mir_module.functions.insert(generated_arity, function);
}
}
}
}
#[cfg(feature = "normalized_dev")]
use crate::config::env::joinir_dev::{current_joinir_mode, JoinIrMode};
#[cfg(feature = "normalized_dev")]
use crate::mir::join_ir::normalized::shape_guard::{self, NormalizedDevShape};
#[cfg(feature = "normalized_dev")]
use crate::mir::join_ir::normalized::{
normalize_pattern1_minimal, normalize_pattern2_minimal, NormalizedModule,
};
#[cfg(feature = "normalized_dev")]
use crate::mir::join_ir::JoinIrPhase;
#[cfg(feature = "normalized_dev")]
use crate::mir::join_ir_vm_bridge::lower_normalized_to_mir_minimal;
#[cfg(feature = "normalized_dev")]
use std::panic::{catch_unwind, AssertUnwindSafe};
/// Structured JoinIR → MIR既存経路の明示エントリ。
pub(crate) fn lower_joinir_structured_to_mir_with_meta(
module: &JoinModule,
meta: &JoinFuncMetaMap,
boundary: Option<&crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary>,
) -> Result<MirModule, JoinIrVmBridgeError> {
if !module.is_structured() {
return Err(JoinIrVmBridgeError::new(
"[joinir/bridge] expected Structured JoinIR module",
));
}
// Phase 256 P1.5: Fail-Fast - boundary 必須チェック
// JoinIR Param (100+) または Local (1000+) を含む module は boundary 必須
// NOTE: This check is DISABLED for now because merge_joinir_mir_blocks
// might already handle ValueId remapping. Will enable after verifying
// the merge function works correctly with Local ValueIds.
// if module_has_joinir_value_ids(module) && boundary.is_none() {
// return Err(JoinIrVmBridgeError::new(
// "[joinir/contract] Missing boundary remap: \
// JoinModule contains JoinIR ValueIds (100+ or 1000+) \
// but boundary is None. This is a contract violation.",
// ));
// }
convert_join_module_to_mir_with_meta(module, meta, boundary)
}
/// Normalized JoinIR → MIR現状は Structured に戻して既存ブリッジを再利用)。
#[cfg(feature = "normalized_dev")]
#[allow(dead_code)]
pub(crate) fn lower_joinir_normalized_to_mir_with_meta(
module: &NormalizedModule,
meta: &JoinFuncMetaMap,
) -> Result<MirModule, JoinIrVmBridgeError> {
if module.phase != JoinIrPhase::Normalized {
return Err(JoinIrVmBridgeError::new(
"[joinir/bridge] expected Normalized JoinIR module",
));
}
let structured = module.to_structured().ok_or_else(|| {
JoinIrVmBridgeError::new(
"[joinir/bridge] normalized module missing Structured snapshot (dev-only)",
)
})?;
lower_joinir_structured_to_mir_with_meta(&structured, meta)
}
#[cfg(feature = "normalized_dev")]
fn normalize_for_shape(
module: &JoinModule,
shape: NormalizedDevShape,
) -> Result<NormalizedModule, JoinIrVmBridgeError> {
let result = match shape {
NormalizedDevShape::Pattern1Mini => {
catch_unwind(AssertUnwindSafe(|| normalize_pattern1_minimal(module)))
}
NormalizedDevShape::Pattern2Mini
| NormalizedDevShape::JsonparserSkipWsMini
| NormalizedDevShape::JsonparserSkipWsReal
| NormalizedDevShape::JsonparserAtoiMini
| NormalizedDevShape::JsonparserAtoiReal
| NormalizedDevShape::JsonparserParseNumberReal => {
catch_unwind(AssertUnwindSafe(|| normalize_pattern2_minimal(module)))
}
NormalizedDevShape::SelfhostTokenScanP2 => catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_selfhost_token_scan_p2(module)
.expect("selfhost P2 normalization failed")
})),
NormalizedDevShape::SelfhostTokenScanP2Accum => catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_selfhost_token_scan_p2_accum(module)
.expect("selfhost P2 accum normalization failed")
})),
// Phase 47-A: P3 minimal normalization
NormalizedDevShape::Pattern3IfSumMinimal => catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_pattern3_if_sum_minimal(module)
.expect("P3 normalization failed")
})),
// Phase 47-B: P3 extended normalization
NormalizedDevShape::Pattern3IfSumMulti => catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_pattern3_if_sum_multi_minimal(module)
.expect("P3 multi normalization failed")
})),
NormalizedDevShape::Pattern3IfSumJson => catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_pattern3_if_sum_json_minimal(module)
.expect("P3 json normalization failed")
})),
NormalizedDevShape::SelfhostIfSumP3 => catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_selfhost_if_sum_p3(module)
.expect("selfhost P3 normalization failed")
})),
NormalizedDevShape::SelfhostIfSumP3Ext => catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_selfhost_if_sum_p3_ext(module)
.expect("selfhost P3 ext normalization failed")
})),
// Phase 53: selfhost P2/P3 practical variations (delegate to existing normalizers)
NormalizedDevShape::SelfhostArgsParseP2 => {
catch_unwind(AssertUnwindSafe(|| normalize_pattern2_minimal(module)))
}
NormalizedDevShape::SelfhostStmtCountP3 => catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_selfhost_if_sum_p3_ext(module)
.expect("selfhost stmt_count P3 normalization failed")
})),
// Phase 54: selfhost P2/P3 shape growth (delegate to existing normalizers)
NormalizedDevShape::SelfhostVerifySchemaP2 => {
catch_unwind(AssertUnwindSafe(|| normalize_pattern2_minimal(module)))
}
NormalizedDevShape::SelfhostDetectFormatP3 => catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_selfhost_if_sum_p3_ext(module)
.expect("selfhost detect_format P3 normalization failed")
})),
// Phase 48-A: P4 minimal normalization
NormalizedDevShape::Pattern4ContinueMinimal => catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_pattern4_continue_minimal(module)
.expect("P4 normalization failed")
})),
// Phase 48-B: JsonParser continue skip_ws (array/object)
NormalizedDevShape::JsonparserParseArrayContinueSkipWs => {
catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_jsonparser_parse_array_continue_skip_ws(
module,
)
.expect("P4 array normalization failed")
}))
}
NormalizedDevShape::JsonparserParseObjectContinueSkipWs => {
catch_unwind(AssertUnwindSafe(|| {
crate::mir::join_ir::normalized::normalize_jsonparser_parse_object_continue_skip_ws(
module,
)
.expect("P4 object normalization failed")
}))
}
// Phase 89: Continue + Early Return pattern (dev-only, delegates to P2 for now)
NormalizedDevShape::PatternContinueReturnMinimal => {
catch_unwind(AssertUnwindSafe(|| normalize_pattern2_minimal(module)))
}
// Phase 90: Parse String Composite pattern (dev-only, delegates to P2 for now)
NormalizedDevShape::ParseStringCompositeMinimal => {
catch_unwind(AssertUnwindSafe(|| normalize_pattern2_minimal(module)))
}
};
match result {
Ok(norm) => Ok(norm),
Err(_) => Err(JoinIrVmBridgeError::new(format!(
"[joinir/bridge/normalized] normalization failed for shape {:?}",
shape
))),
}
}
#[cfg(feature = "normalized_dev")]
fn try_normalized_direct_bridge(
module: &JoinModule,
meta: &JoinFuncMetaMap,
shapes: &[NormalizedDevShape],
allow_structured_fallback: bool,
use_env_guard: bool,
boundary: Option<&crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary>,
) -> Result<Option<MirModule>, JoinIrVmBridgeError> {
if shapes.is_empty() {
crate::mir::join_ir_vm_bridge::normalized_bridge::log_dev(
"fallback",
"normalized dev enabled but shape unsupported; using Structured path",
true,
);
return if allow_structured_fallback {
Ok(None)
} else {
Err(JoinIrVmBridgeError::new(
"[joinir/bridge] canonical normalized route requested but shape unsupported",
))
};
}
let exec = || {
let debug = crate::mir::join_ir::normalized::dev_env::normalized_dev_logs_enabled();
for &shape in shapes {
if debug {
crate::mir::join_ir_vm_bridge::normalized_bridge::log_dev(
"direct",
format!("attempting normalized→MIR for {:?}", shape),
false,
);
}
match normalize_for_shape(module, shape) {
Ok(norm) => {
let mir =
lower_normalized_to_mir_minimal(&norm, meta, allow_structured_fallback)?;
crate::mir::join_ir_vm_bridge::normalized_bridge::log_dev(
"direct",
format!(
"normalized→MIR succeeded (shape={:?}, functions={})",
shape,
norm.functions.len()
),
false,
);
return Ok(Some(mir));
}
Err(err) => {
if debug {
crate::mir::join_ir_vm_bridge::normalized_bridge::log_dev(
"direct",
format!(
"{:?} normalization failed: {} (continuing)",
shape, err.message
),
false,
);
}
}
}
}
if allow_structured_fallback {
Ok(None)
} else {
Err(JoinIrVmBridgeError::new(
"[joinir/bridge] canonical normalized route failed for all shapes",
))
}
};
if use_env_guard {
crate::mir::join_ir::normalized::dev_env::with_dev_env_if_unset(exec)
} else {
exec()
}
}
/// JoinIR → MIR の単一入口。Mode に応じて Normalized/Structured 経路を選択。
///
/// Phase 45: JoinIrMode 導入による統一ルーティング:
/// - Canonical P2-Core shapes → 常に Normalized→MIR(direct)mode 無視)
/// - NormalizedDev → サポート形状のみ Normalized path、それ以外 Structured path
/// - StructuredOnly | NormalizedCanonical → Structured path
///
/// Phase 256 P1.5: boundary parameter for ValueId remapping
pub(crate) fn bridge_joinir_to_mir_with_meta(
module: &JoinModule,
meta: &JoinFuncMetaMap,
boundary: Option<&crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary>,
) -> Result<MirModule, JoinIrVmBridgeError> {
#[cfg(feature = "normalized_dev")]
{
let mode = current_joinir_mode();
// Canonical set (P2/P3/P4): Always uses Normalized→MIR(direct) regardless of mode/env
let canonical_shapes = shape_guard::canonical_shapes(module);
if !canonical_shapes.is_empty() {
match try_normalized_direct_bridge(module, meta, &canonical_shapes, false, false, boundary)? {
Some(mut mir) => {
ensure_joinir_function_aliases(&mut mir, module);
return Ok(mir);
}
None => {
return Err(JoinIrVmBridgeError::new(
"[joinir/bridge] canonical normalized route returned None unexpectedly",
))
}
}
}
// Phase 45: Mode によるルーティング分岐
match mode {
JoinIrMode::NormalizedDev => {
// サポート形状のみ Normalized path を試行、失敗時は Structured fallback
let shapes = shape_guard::direct_shapes(module);
match try_normalized_direct_bridge(module, meta, &shapes, true, true, boundary)? {
Some(mut mir) => {
ensure_joinir_function_aliases(&mut mir, module);
return Ok(mir);
}
None => {} // Fallback to Structured
}
}
JoinIrMode::StructuredOnly | JoinIrMode::NormalizedCanonical => {
// Structured path のみ使用
// NormalizedCanonical は将来 Phase 46+ で canonical migration 完了後に専用経路を持つ)
}
}
}
let mut mir = lower_joinir_structured_to_mir_with_meta(module, meta, boundary)?;
ensure_joinir_function_aliases(&mut mir, module);
Ok(mir)
}
/// JoinIR → MIRメタなし呼び出しのユーティリティ。
pub(crate) fn bridge_joinir_to_mir(module: &JoinModule) -> Result<MirModule, JoinIrVmBridgeError> {
let empty_meta: JoinFuncMetaMap = BTreeMap::new();
bridge_joinir_to_mir_with_meta(module, &empty_meta, None)
}