mir: include continue snapshots in phi sealing (#130)
This commit is contained in:
@ -34,6 +34,12 @@ pub struct LoopBuilder<'a> {
|
|||||||
/// ブロックごとの変数マップ(スコープ管理)
|
/// ブロックごとの変数マップ(スコープ管理)
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
block_var_maps: HashMap<BasicBlockId, HashMap<String, ValueId>>,
|
block_var_maps: HashMap<BasicBlockId, HashMap<String, ValueId>>,
|
||||||
|
|
||||||
|
/// ループヘッダーID(continueで使用)
|
||||||
|
loop_header: Option<BasicBlockId>,
|
||||||
|
|
||||||
|
/// continue文からの変数スナップショット
|
||||||
|
continue_snapshots: Vec<(BasicBlockId, HashMap<String, ValueId>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LoopBuilder<'a> {
|
impl<'a> LoopBuilder<'a> {
|
||||||
@ -43,6 +49,8 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
parent_builder: parent,
|
parent_builder: parent,
|
||||||
incomplete_phis: HashMap::new(),
|
incomplete_phis: HashMap::new(),
|
||||||
block_var_maps: HashMap::new(),
|
block_var_maps: HashMap::new(),
|
||||||
|
loop_header: None,
|
||||||
|
continue_snapshots: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +65,8 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
let header_id = self.new_block();
|
let header_id = self.new_block();
|
||||||
let body_id = self.new_block();
|
let body_id = self.new_block();
|
||||||
let after_loop_id = self.new_block();
|
let after_loop_id = self.new_block();
|
||||||
|
self.loop_header = Some(header_id);
|
||||||
|
self.continue_snapshots.clear();
|
||||||
|
|
||||||
// 2. Preheader -> Header へのジャンプ
|
// 2. Preheader -> Header へのジャンプ
|
||||||
self.emit_jump(header_id)?;
|
self.emit_jump(header_id)?;
|
||||||
@ -156,16 +166,21 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
// 不完全なPhi nodeを取得
|
// 不完全なPhi nodeを取得
|
||||||
if let Some(incomplete_phis) = self.incomplete_phis.remove(&block_id) {
|
if let Some(incomplete_phis) = self.incomplete_phis.remove(&block_id) {
|
||||||
for mut phi in incomplete_phis {
|
for mut phi in incomplete_phis {
|
||||||
// Latchブロックでの変数の値を取得
|
for (cid, snapshot) in &self.continue_snapshots {
|
||||||
let value_after = self.get_variable_at_block(&phi.var_name, latch_id)
|
if let Some(v) = snapshot.get(&phi.var_name) {
|
||||||
.ok_or_else(|| format!("Variable {} not found at latch block", phi.var_name))?;
|
phi.known_inputs.push((*cid, *v));
|
||||||
|
}
|
||||||
// Phi nodeの入力を完成させる
|
}
|
||||||
|
|
||||||
|
let value_after = self
|
||||||
|
.get_variable_at_block(&phi.var_name, latch_id)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
format!("Variable {} not found at latch block", phi.var_name)
|
||||||
|
})?;
|
||||||
|
|
||||||
phi.known_inputs.push((latch_id, value_after));
|
phi.known_inputs.push((latch_id, value_after));
|
||||||
|
|
||||||
// 完成したPhi nodeを発行
|
|
||||||
self.emit_phi_at_block_start(block_id, phi.phi_id, phi.known_inputs)?;
|
self.emit_phi_at_block_start(block_id, phi.phi_id, phi.known_inputs)?;
|
||||||
// 重要: ループ外から参照される変数はPhi結果に束縛し直す
|
|
||||||
self.update_variable(phi.var_name.clone(), phi.phi_id);
|
self.update_variable(phi.var_name.clone(), phi.phi_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -296,6 +311,26 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_statement(&mut self, stmt: ASTNode) -> Result<ValueId, String> {
|
fn build_statement(&mut self, stmt: ASTNode) -> Result<ValueId, String> {
|
||||||
self.parent_builder.build_expression(stmt)
|
match stmt {
|
||||||
|
ASTNode::Continue { .. } => {
|
||||||
|
let snapshot = self.get_current_variable_map();
|
||||||
|
let cur_block = self.current_block()?;
|
||||||
|
self.block_var_maps.insert(cur_block, snapshot.clone());
|
||||||
|
self.continue_snapshots.push((cur_block, snapshot));
|
||||||
|
|
||||||
|
if let Some(header) = self.loop_header {
|
||||||
|
self.emit_jump(header)?;
|
||||||
|
let _ = self.add_predecessor(header, cur_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
let next_block = self.new_block();
|
||||||
|
self.set_current_block(next_block)?;
|
||||||
|
|
||||||
|
let void_id = self.new_value();
|
||||||
|
self.emit_const(void_id, ConstValue::Void)?;
|
||||||
|
Ok(void_id)
|
||||||
|
}
|
||||||
|
other => self.parent_builder.build_expression(other),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user