Files
hakorune/src/mir/query.rs
2025-11-24 15:02:51 +09:00

166 lines
5.9 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.

//! MirQuery - Read/Write/CFGビューを提供する共通窓口
//!
//! Box理論: MIR 全体の構造は MirQueryBox が保持し、他の箱ExitLiveness など)は
//! 「見せる窓」である MirQuery トレイト越しにしか触らないようにする。
//! これにより MIR 構造への依存を最小化し、テスタビリティと疎結合を保つ。
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
/// MIR への読み取り専用ビュー
pub trait MirQuery {
/// ブロック内の命令列PHI を含む)を順序付きで返す
fn insts_in_block(&self, bb: BasicBlockId) -> &[MirInstruction];
/// ブロックの後続succsを決定的順序で返す
fn succs(&self, bb: BasicBlockId) -> Vec<BasicBlockId>;
/// 命令が読むuse するValueId のリスト
fn reads_of(&self, inst: &MirInstruction) -> Vec<ValueId>;
/// 命令が書くdef するValueId のリスト
fn writes_of(&self, inst: &MirInstruction) -> Vec<ValueId>;
}
/// MirQuery の標準実装MirFunction 全体を抱えつつビューを提供
pub struct MirQueryBox<'m> {
mir: &'m MirFunction,
}
impl<'m> MirQueryBox<'m> {
pub fn new(mir: &'m MirFunction) -> Self {
Self { mir }
}
}
impl<'m> MirQuery for MirQueryBox<'m> {
fn insts_in_block(&self, bb: BasicBlockId) -> &[MirInstruction] {
static EMPTY: &[MirInstruction] = &[];
self.mir
.blocks
.get(&bb)
.map(|bb| bb.instructions.as_slice())
.unwrap_or(EMPTY)
}
fn succs(&self, bb: BasicBlockId) -> Vec<BasicBlockId> {
let mut v: Vec<_> = self
.mir
.blocks
.get(&bb)
.map(|bb| bb.successors.iter().copied().collect())
.unwrap_or_else(Vec::new);
v.sort_by_key(|b| b.0);
v
}
fn reads_of(&self, inst: &MirInstruction) -> Vec<ValueId> {
use MirInstruction::*;
match inst {
Const { .. } | Nop => Vec::new(),
Copy { src, .. } => vec![*src],
UnaryOp { operand, .. } => vec![*operand],
BinOp { lhs, rhs, .. } | Compare { lhs, rhs, .. } => {
vec![*lhs, *rhs]
}
TypeOp { value, .. } | TypeCheck { value, .. } | Cast { value, .. } => {
vec![*value]
}
Load { ptr, .. } => vec![*ptr],
Store { ptr, value } => vec![*ptr, *value],
ArrayGet { array, index, .. } => vec![*array, *index],
ArraySet {
array,
index,
value,
..
} => vec![*array, *index, *value],
Call { args, .. }
| BoxCall { args, .. }
| PluginInvoke { args, .. }
| ExternCall { args, .. } => args.clone(),
Return { value } => value.iter().copied().collect(),
Branch { condition, .. } => vec![*condition],
Jump { .. } => Vec::new(),
Phi { inputs, .. } => inputs.iter().map(|(_, v)| *v).collect(),
NewBox { args, .. } => args.clone(),
Debug { value, .. } | Print { value, .. } => vec![*value],
DebugLog { values, .. } => values.clone(),
Throw { exception, .. } => vec![*exception],
Catch { .. } => Vec::new(),
NewClosure { captures, me, .. } => {
let mut v: Vec<ValueId> = captures.iter().map(|(_, v)| *v).collect();
if let Some(m) = me {
v.push(*m);
}
v
}
RefNew { box_val, .. } => vec![*box_val],
RefGet { reference, .. } => vec![*reference],
RefSet {
reference, value, ..
} => vec![*reference, *value],
WeakNew { box_val, .. } => vec![*box_val],
WeakLoad { weak_ref, .. } => vec![*weak_ref],
WeakRef { value, .. } => vec![*value],
BarrierRead { ptr } | BarrierWrite { ptr } | Barrier { ptr, .. } => {
vec![*ptr]
}
FutureNew { value, .. } => vec![*value],
FutureSet { future, value } => vec![*future, *value],
Await { future, .. } => vec![*future],
Safepoint => Vec::new(),
}
}
fn writes_of(&self, inst: &MirInstruction) -> Vec<ValueId> {
use MirInstruction::*;
match inst {
Const { dst, .. }
| UnaryOp { dst, .. }
| BinOp { dst, .. }
| Compare { dst, .. }
| TypeOp { dst, .. }
| Cast { dst, .. }
| Load { dst, .. }
| ArrayGet { dst, .. }
| Call { dst: Some(dst), .. }
| BoxCall { dst: Some(dst), .. }
| PluginInvoke { dst: Some(dst), .. }
| ExternCall { dst: Some(dst), .. }
| Phi { dst, .. }
| NewBox { dst, .. }
| RefNew { dst, .. }
| RefGet { dst, .. }
| WeakNew { dst, .. }
| WeakLoad { dst, .. }
| WeakRef { dst, .. }
| FutureNew { dst, .. }
| NewClosure { dst, .. }
| Await { dst, .. }
| Copy { dst, .. } => vec![*dst], // Copy writes to dst
// No writes
Nop
| Store { .. }
| ArraySet { .. }
| Call { dst: None, .. }
| BoxCall { dst: None, .. }
| PluginInvoke { dst: None, .. }
| ExternCall { dst: None, .. }
| Return { .. }
| Branch { .. }
| Jump { .. }
| Debug { .. }
| DebugLog { .. }
| Print { .. }
| Throw { .. }
| Catch { .. }
| BarrierRead { .. }
| BarrierWrite { .. }
| Barrier { .. }
| FutureSet { .. }
| Safepoint => Vec::new(),
_ => Vec::new(),
}
}
}