hv1: early-exit at main (no plugin init); tokenizer: Stage-3 single-quote + full escapes (\/ \b \f \' \r fix); builder: route BinOp via SSOT emit_binop_to_dst; hv1 verify canary route (builder→Core); docs: phase-20.39 updates
This commit is contained in:
@ -94,12 +94,20 @@ impl super::MirBuilder {
|
||||
self.value_types.insert(dst, MirType::Integer);
|
||||
} else {
|
||||
// guard中は従来のBinOp
|
||||
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::binop_lower::emit_binop_to_dst(func, cur_bb, dst, op, lhs, rhs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
|
||||
}
|
||||
self.value_types.insert(dst, MirType::Integer);
|
||||
}
|
||||
} else {
|
||||
// 既存の算術経路
|
||||
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::binop_lower::emit_binop_to_dst(func, cur_bb, dst, op, lhs, rhs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
|
||||
}
|
||||
if matches!(op, crate::mir::BinaryOp::Add) {
|
||||
let lhs_is_str = match self.value_types.get(&lhs) {
|
||||
Some(MirType::String) => true,
|
||||
@ -122,7 +130,11 @@ impl super::MirBuilder {
|
||||
}
|
||||
} else {
|
||||
// 既存の算術経路
|
||||
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::binop_lower::emit_binop_to_dst(func, cur_bb, dst, op, lhs, rhs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?;
|
||||
}
|
||||
if matches!(op, crate::mir::BinaryOp::Add) {
|
||||
let lhs_is_str = match self.value_types.get(&lhs) {
|
||||
Some(MirType::String) => true,
|
||||
|
||||
@ -18,6 +18,7 @@ pub mod instruction_introspection; // Introspection helpers for tests (instructi
|
||||
pub mod types; // core MIR enums (ConstValue, Ops, MirType)
|
||||
pub mod loop_api; // Minimal LoopBuilder facade (adapter-ready)
|
||||
pub mod loop_builder; // SSA loop construction with phi nodes
|
||||
pub mod ssot; // Shared helpers (SSOT) for instruction lowering
|
||||
pub mod optimizer;
|
||||
pub mod utils; // Phase 15 control flow utilities for root treatment
|
||||
pub mod phi_core; // Phase 1 scaffold: unified PHI entry (re-exports only)
|
||||
|
||||
50
src/mir/ssot/binop_lower.rs
Normal file
50
src/mir/ssot/binop_lower.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::mir::{BasicBlockId, BinaryOp, MirFunction, MirInstruction, ValueId};
|
||||
|
||||
/// Parse a binary operator string to BinaryOp
|
||||
pub fn parse_binop_str(op: &str) -> Option<BinaryOp> {
|
||||
match op {
|
||||
"+" => Some(BinaryOp::Add),
|
||||
"-" => Some(BinaryOp::Sub),
|
||||
"*" => Some(BinaryOp::Mul),
|
||||
"/" => Some(BinaryOp::Div),
|
||||
"%" => Some(BinaryOp::Mod),
|
||||
"&" => Some(BinaryOp::BitAnd),
|
||||
"|" => Some(BinaryOp::BitOr),
|
||||
"^" => Some(BinaryOp::BitXor),
|
||||
"<<" => Some(BinaryOp::Shl),
|
||||
">>" => Some(BinaryOp::Shr),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit a MIR BinOp into the current block and return the destination ValueId
|
||||
pub fn emit_binop_func(
|
||||
f: &mut MirFunction,
|
||||
cur_bb: BasicBlockId,
|
||||
op: BinaryOp,
|
||||
lhs: ValueId,
|
||||
rhs: ValueId,
|
||||
) -> ValueId {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::BinOp { dst, op, lhs, rhs });
|
||||
}
|
||||
dst
|
||||
}
|
||||
|
||||
/// Emit a MIR BinOp into the current block using the provided destination id.
|
||||
/// This variant allows front-ends that pre-allocate `dst` (e.g., builders that
|
||||
/// maintain their own value id generator) to route through the SSOT without
|
||||
/// changing id allocation policy.
|
||||
pub fn emit_binop_to_dst(
|
||||
f: &mut MirFunction,
|
||||
cur_bb: BasicBlockId,
|
||||
dst: ValueId,
|
||||
op: BinaryOp,
|
||||
lhs: ValueId,
|
||||
rhs: ValueId,
|
||||
) {
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::BinOp { dst, op, lhs, rhs });
|
||||
}
|
||||
}
|
||||
26
src/mir/ssot/loop_common.rs
Normal file
26
src/mir/ssot/loop_common.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId, BinaryOp, ConstValue};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Apply `var += step` before continue so that header sees updated value.
|
||||
/// Returns the new ValueId of the variable if updated, otherwise None.
|
||||
pub fn apply_increment_before_continue(
|
||||
f: &mut MirFunction,
|
||||
cur_bb: BasicBlockId,
|
||||
vars: &mut HashMap<String, ValueId>,
|
||||
var_name: &str,
|
||||
step: i64,
|
||||
) -> Option<ValueId> {
|
||||
let cur_val = match vars.get(var_name) { Some(v) => *v, None => return None };
|
||||
// Emit const step
|
||||
let step_v = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::Const { dst: step_v, value: ConstValue::Integer(step) });
|
||||
}
|
||||
// Emit add
|
||||
let new_v = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::BinOp { dst: new_v, op: BinaryOp::Add, lhs: cur_val, rhs: step_v });
|
||||
}
|
||||
vars.insert(var_name.to_string(), new_v);
|
||||
Some(new_v)
|
||||
}
|
||||
2
src/mir/ssot/mod.rs
Normal file
2
src/mir/ssot/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod binop_lower;
|
||||
pub mod loop_common;
|
||||
Reference in New Issue
Block a user