builder: add loop helpers (create_loop_blocks/add_predecessor) and adopt in LoopBuilder; use BinaryExpr/CallExpr wrappers in expr lowering (no behavior change)
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
// Expression lowering split from builder.rs to keep files lean
|
// Expression lowering split from builder.rs to keep files lean
|
||||||
use super::{ConstValue, MirInstruction, ValueId};
|
use super::{ConstValue, MirInstruction, ValueId};
|
||||||
use crate::ast::{ASTNode, AssignStmt, ReturnStmt};
|
use crate::ast::{ASTNode, AssignStmt, ReturnStmt, BinaryExpr, CallExpr};
|
||||||
|
|
||||||
impl super::MirBuilder {
|
impl super::MirBuilder {
|
||||||
// Main expression dispatcher
|
// Main expression dispatcher
|
||||||
@ -19,12 +19,11 @@ impl super::MirBuilder {
|
|||||||
match ast {
|
match ast {
|
||||||
ASTNode::Literal { value, .. } => self.build_literal(value),
|
ASTNode::Literal { value, .. } => self.build_literal(value),
|
||||||
|
|
||||||
ASTNode::BinaryOp {
|
node @ ASTNode::BinaryOp { .. } => {
|
||||||
left,
|
// Use BinaryExpr for clear destructuring (no behavior change)
|
||||||
operator,
|
let e = BinaryExpr::try_from(node).expect("ASTNode::BinaryOp must convert");
|
||||||
right,
|
self.build_binary_op(*e.left, e.operator, *e.right)
|
||||||
..
|
}
|
||||||
} => self.build_binary_op(*left, operator, *right),
|
|
||||||
|
|
||||||
ASTNode::UnaryOp {
|
ASTNode::UnaryOp {
|
||||||
operator, operand, ..
|
operator, operand, ..
|
||||||
@ -87,9 +86,10 @@ impl super::MirBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNode::FunctionCall {
|
node @ ASTNode::FunctionCall { .. } => {
|
||||||
name, arguments, ..
|
let c = CallExpr::try_from(node).expect("ASTNode::FunctionCall must convert");
|
||||||
} => self.build_function_call(name.clone(), arguments.clone()),
|
self.build_function_call(c.name, c.arguments)
|
||||||
|
}
|
||||||
|
|
||||||
ASTNode::Call {
|
ASTNode::Call {
|
||||||
callee, arguments, ..
|
callee, arguments, ..
|
||||||
|
|||||||
@ -1,5 +1,14 @@
|
|||||||
//! Small loop utilities for MirBuilder
|
//! Small loop utilities for MirBuilder
|
||||||
use super::BasicBlockId;
|
use super::{BasicBlockId, MirBuilder};
|
||||||
|
|
||||||
|
/// Create header/body/after blocks for a loop and push loop context.
|
||||||
|
pub(crate) fn create_loop_blocks(builder: &mut MirBuilder) -> (BasicBlockId, BasicBlockId, BasicBlockId) {
|
||||||
|
let header = builder.block_gen.next();
|
||||||
|
let body = builder.block_gen.next();
|
||||||
|
let after = builder.block_gen.next();
|
||||||
|
push_loop_context(builder, header, after);
|
||||||
|
(header, body, after)
|
||||||
|
}
|
||||||
|
|
||||||
/// Push loop context (header/exit) onto the MirBuilder stacks.
|
/// Push loop context (header/exit) onto the MirBuilder stacks.
|
||||||
pub(crate) fn push_loop_context(
|
pub(crate) fn push_loop_context(
|
||||||
@ -36,3 +45,19 @@ pub(crate) fn in_loop(builder: &super::MirBuilder) -> bool {
|
|||||||
pub(crate) fn depth(builder: &super::MirBuilder) -> usize {
|
pub(crate) fn depth(builder: &super::MirBuilder) -> usize {
|
||||||
builder.loop_header_stack.len()
|
builder.loop_header_stack.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add predecessor edge metadata to a basic block.
|
||||||
|
pub(crate) fn add_predecessor(
|
||||||
|
builder: &mut MirBuilder,
|
||||||
|
block: BasicBlockId,
|
||||||
|
pred: BasicBlockId,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
if let Some(ref mut function) = builder.current_function {
|
||||||
|
if let Some(bb) = function.get_block_mut(block) {
|
||||||
|
bb.add_predecessor(pred);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
return Err(format!("Block {} not found", block));
|
||||||
|
}
|
||||||
|
Err("No current function".to_string())
|
||||||
|
}
|
||||||
|
|||||||
@ -103,21 +103,14 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
) -> Result<ValueId, String> {
|
) -> Result<ValueId, String> {
|
||||||
// 1. ブロックの準備
|
// 1. ブロックの準備
|
||||||
let preheader_id = self.current_block()?;
|
let preheader_id = self.current_block()?;
|
||||||
let header_id = self.new_block();
|
let (header_id, body_id, after_loop_id) =
|
||||||
let body_id = self.new_block();
|
crate::mir::builder::loops::create_loop_blocks(self.parent_builder);
|
||||||
let after_loop_id = self.new_block();
|
|
||||||
self.loop_header = Some(header_id);
|
self.loop_header = Some(header_id);
|
||||||
self.continue_snapshots.clear();
|
self.continue_snapshots.clear();
|
||||||
// Push loop context to parent builder (for nested break/continue lowering)
|
|
||||||
crate::mir::builder::loops::push_loop_context(
|
|
||||||
self.parent_builder,
|
|
||||||
header_id,
|
|
||||||
after_loop_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
// 2. Preheader -> Header へのジャンプ
|
// 2. Preheader -> Header へのジャンプ
|
||||||
self.emit_jump(header_id)?;
|
self.emit_jump(header_id)?;
|
||||||
let _ = self.add_predecessor(header_id, preheader_id);
|
let _ = crate::mir::builder::loops::add_predecessor(self.parent_builder, header_id, preheader_id);
|
||||||
|
|
||||||
// 3. Headerブロックの準備(unsealed状態)
|
// 3. Headerブロックの準備(unsealed状態)
|
||||||
self.set_current_block(header_id)?;
|
self.set_current_block(header_id)?;
|
||||||
@ -133,8 +126,8 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
|
|
||||||
// 6. 条件分岐
|
// 6. 条件分岐
|
||||||
self.emit_branch(condition_value, body_id, after_loop_id)?;
|
self.emit_branch(condition_value, body_id, after_loop_id)?;
|
||||||
let _ = self.add_predecessor(body_id, header_id);
|
let _ = crate::mir::builder::loops::add_predecessor(self.parent_builder, body_id, header_id);
|
||||||
let _ = self.add_predecessor(after_loop_id, header_id);
|
let _ = crate::mir::builder::loops::add_predecessor(self.parent_builder, after_loop_id, header_id);
|
||||||
|
|
||||||
// 7. ループボディの構築
|
// 7. ループボディの構築
|
||||||
self.set_current_block(body_id)?;
|
self.set_current_block(body_id)?;
|
||||||
@ -159,7 +152,7 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
// 実際の latch_id に対してスナップショットを紐づける
|
// 実際の latch_id に対してスナップショットを紐づける
|
||||||
self.block_var_maps.insert(latch_id, latch_snapshot);
|
self.block_var_maps.insert(latch_id, latch_snapshot);
|
||||||
self.emit_jump(header_id)?;
|
self.emit_jump(header_id)?;
|
||||||
let _ = self.add_predecessor(header_id, latch_id);
|
let _ = crate::mir::builder::loops::add_predecessor(self.parent_builder, header_id, latch_id);
|
||||||
|
|
||||||
// 9. Headerブロックをシール(全predecessors確定)
|
// 9. Headerブロックをシール(全predecessors確定)
|
||||||
self.seal_block(header_id, latch_id)?;
|
self.seal_block(header_id, latch_id)?;
|
||||||
@ -539,7 +532,7 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
let cur_block = self.current_block()?;
|
let cur_block = self.current_block()?;
|
||||||
if let Some(exit_bb) = crate::mir::builder::loops::current_exit(self.parent_builder) {
|
if let Some(exit_bb) = crate::mir::builder::loops::current_exit(self.parent_builder) {
|
||||||
self.emit_jump(exit_bb)?;
|
self.emit_jump(exit_bb)?;
|
||||||
let _ = self.add_predecessor(exit_bb, cur_block);
|
let _ = crate::mir::builder::loops::add_predecessor(self.parent_builder, exit_bb, cur_block);
|
||||||
}
|
}
|
||||||
// Continue building in a fresh (unreachable) block to satisfy callers
|
// Continue building in a fresh (unreachable) block to satisfy callers
|
||||||
let next_block = self.new_block();
|
let next_block = self.new_block();
|
||||||
@ -556,7 +549,7 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
|
|
||||||
if let Some(header) = self.loop_header {
|
if let Some(header) = self.loop_header {
|
||||||
self.emit_jump(header)?;
|
self.emit_jump(header)?;
|
||||||
let _ = self.add_predecessor(header, cur_block);
|
let _ = crate::mir::builder::loops::add_predecessor(self.parent_builder, header, cur_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
let next_block = self.new_block();
|
let next_block = self.new_block();
|
||||||
|
|||||||
Reference in New Issue
Block a user