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
|
||||
use super::{ConstValue, MirInstruction, ValueId};
|
||||
use crate::ast::{ASTNode, AssignStmt, ReturnStmt};
|
||||
use crate::ast::{ASTNode, AssignStmt, ReturnStmt, BinaryExpr, CallExpr};
|
||||
|
||||
impl super::MirBuilder {
|
||||
// Main expression dispatcher
|
||||
@ -19,12 +19,11 @@ impl super::MirBuilder {
|
||||
match ast {
|
||||
ASTNode::Literal { value, .. } => self.build_literal(value),
|
||||
|
||||
ASTNode::BinaryOp {
|
||||
left,
|
||||
operator,
|
||||
right,
|
||||
..
|
||||
} => self.build_binary_op(*left, operator, *right),
|
||||
node @ ASTNode::BinaryOp { .. } => {
|
||||
// Use BinaryExpr for clear destructuring (no behavior change)
|
||||
let e = BinaryExpr::try_from(node).expect("ASTNode::BinaryOp must convert");
|
||||
self.build_binary_op(*e.left, e.operator, *e.right)
|
||||
}
|
||||
|
||||
ASTNode::UnaryOp {
|
||||
operator, operand, ..
|
||||
@ -87,9 +86,10 @@ impl super::MirBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
ASTNode::FunctionCall {
|
||||
name, arguments, ..
|
||||
} => self.build_function_call(name.clone(), arguments.clone()),
|
||||
node @ ASTNode::FunctionCall { .. } => {
|
||||
let c = CallExpr::try_from(node).expect("ASTNode::FunctionCall must convert");
|
||||
self.build_function_call(c.name, c.arguments)
|
||||
}
|
||||
|
||||
ASTNode::Call {
|
||||
callee, arguments, ..
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
//! 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.
|
||||
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 {
|
||||
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> {
|
||||
// 1. ブロックの準備
|
||||
let preheader_id = self.current_block()?;
|
||||
let header_id = self.new_block();
|
||||
let body_id = self.new_block();
|
||||
let after_loop_id = self.new_block();
|
||||
let (header_id, body_id, after_loop_id) =
|
||||
crate::mir::builder::loops::create_loop_blocks(self.parent_builder);
|
||||
self.loop_header = Some(header_id);
|
||||
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 へのジャンプ
|
||||
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状態)
|
||||
self.set_current_block(header_id)?;
|
||||
@ -133,8 +126,8 @@ impl<'a> LoopBuilder<'a> {
|
||||
|
||||
// 6. 条件分岐
|
||||
self.emit_branch(condition_value, body_id, after_loop_id)?;
|
||||
let _ = self.add_predecessor(body_id, header_id);
|
||||
let _ = self.add_predecessor(after_loop_id, header_id);
|
||||
let _ = crate::mir::builder::loops::add_predecessor(self.parent_builder, body_id, header_id);
|
||||
let _ = crate::mir::builder::loops::add_predecessor(self.parent_builder, after_loop_id, header_id);
|
||||
|
||||
// 7. ループボディの構築
|
||||
self.set_current_block(body_id)?;
|
||||
@ -159,7 +152,7 @@ impl<'a> LoopBuilder<'a> {
|
||||
// 実際の latch_id に対してスナップショットを紐づける
|
||||
self.block_var_maps.insert(latch_id, latch_snapshot);
|
||||
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確定)
|
||||
self.seal_block(header_id, latch_id)?;
|
||||
@ -539,7 +532,7 @@ impl<'a> LoopBuilder<'a> {
|
||||
let cur_block = self.current_block()?;
|
||||
if let Some(exit_bb) = crate::mir::builder::loops::current_exit(self.parent_builder) {
|
||||
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
|
||||
let next_block = self.new_block();
|
||||
@ -556,7 +549,7 @@ impl<'a> LoopBuilder<'a> {
|
||||
|
||||
if let Some(header) = self.loop_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();
|
||||
|
||||
Reference in New Issue
Block a user