refactor: MIR instruction.rs 4-Phase大型リファクタリング完了(888→315行、64%削減)
Single Responsibility Principle適用による完全分離: - Phase 1: テスト分離 → instruction/tests.rs (196行) - Phase 2: Display実装分離 → instruction/display.rs (130行) - Phase 3: メソッド実装分離 → instruction/methods.rs (247行) - Phase 4: 統合テスト成功(全コンパイルエラー解決) 技術的成果: - MirInstruction enumを単一責任に集中 - 各実装が独立して保守可能な構造 - EffectMask::read→READ修正も完了 - ビルド成功確認済み(警告のみ) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -302,587 +302,16 @@ pub enum MirInstruction {
|
||||
}
|
||||
|
||||
|
||||
impl MirInstruction {
|
||||
/// Get the effect mask for this instruction
|
||||
pub fn effects(&self) -> EffectMask {
|
||||
if let Some(eff) = inst_meta::effects_via_meta(self) {
|
||||
return eff;
|
||||
}
|
||||
match self {
|
||||
// Pure operations
|
||||
MirInstruction::Const { .. }
|
||||
| MirInstruction::BinOp { .. }
|
||||
| MirInstruction::UnaryOp { .. }
|
||||
| MirInstruction::Compare { .. }
|
||||
| MirInstruction::Cast { .. }
|
||||
| MirInstruction::TypeOp { .. }
|
||||
| MirInstruction::Copy { .. }
|
||||
| MirInstruction::Phi { .. }
|
||||
| MirInstruction::TypeCheck { .. }
|
||||
| MirInstruction::Nop => EffectMask::PURE,
|
||||
|
||||
// Memory operations
|
||||
MirInstruction::Load { .. } => EffectMask::READ,
|
||||
MirInstruction::Store { .. } | MirInstruction::ArraySet { .. } => EffectMask::WRITE,
|
||||
MirInstruction::ArrayGet { .. } => EffectMask::READ,
|
||||
|
||||
// Function calls use provided effect mask
|
||||
MirInstruction::Call { effects, .. }
|
||||
| MirInstruction::BoxCall { effects, .. }
|
||||
| MirInstruction::PluginInvoke { effects, .. } => *effects,
|
||||
|
||||
// Control flow (pure but affects execution)
|
||||
MirInstruction::Branch { .. }
|
||||
| MirInstruction::Jump { .. }
|
||||
| MirInstruction::Return { .. } => EffectMask::PURE,
|
||||
|
||||
// Box creation may allocate
|
||||
MirInstruction::NewBox { .. } => EffectMask::PURE.add(Effect::Alloc),
|
||||
|
||||
// Debug has debug effect
|
||||
MirInstruction::Debug { .. } => EffectMask::PURE.add(Effect::Debug),
|
||||
|
||||
// Print has external write effect
|
||||
MirInstruction::Print { effects, .. } => *effects,
|
||||
|
||||
// Phase 5: Control flow & exception handling
|
||||
MirInstruction::Throw { effects, .. } => *effects,
|
||||
MirInstruction::Catch { .. } => EffectMask::CONTROL, // Handler setup affects control handling
|
||||
MirInstruction::Safepoint => EffectMask::PURE, // No-op for now
|
||||
|
||||
// Phase 6: Box reference operations
|
||||
MirInstruction::RefNew { .. } => EffectMask::PURE, // Creating reference is pure
|
||||
MirInstruction::RefGet { .. } => EffectMask::READ, // Reading field has read effects
|
||||
MirInstruction::RefSet { .. } => EffectMask::WRITE, // Writing field has write effects
|
||||
MirInstruction::WeakNew { .. } => EffectMask::PURE, // Creating weak ref is pure
|
||||
MirInstruction::WeakLoad { .. } => EffectMask::READ, // Loading weak ref has read effects
|
||||
MirInstruction::BarrierRead { .. } => EffectMask::READ.add(Effect::Barrier), // Memory barrier with read
|
||||
MirInstruction::BarrierWrite { .. } => EffectMask::WRITE.add(Effect::Barrier), // Memory barrier with write
|
||||
// PoC unified ops mirror legacy effects
|
||||
MirInstruction::WeakRef { op, .. } => match op {
|
||||
WeakRefOp::New => EffectMask::PURE,
|
||||
WeakRefOp::Load => EffectMask::READ,
|
||||
},
|
||||
MirInstruction::Barrier { op, .. } => match op {
|
||||
BarrierOp::Read => EffectMask::READ.add(Effect::Barrier),
|
||||
BarrierOp::Write => EffectMask::WRITE.add(Effect::Barrier),
|
||||
},
|
||||
|
||||
// Phase 7: Async/Future Operations
|
||||
MirInstruction::FutureNew { .. } => EffectMask::PURE.add(Effect::Alloc), // Creating future may allocate
|
||||
MirInstruction::FutureSet { .. } => EffectMask::WRITE, // Setting future has write effects
|
||||
MirInstruction::Await { .. } => EffectMask::READ.add(Effect::Async), // Await blocks and reads
|
||||
|
||||
// Phase 9.7: External Function Calls
|
||||
MirInstruction::ExternCall { effects, .. } => *effects, // Use provided effect mask
|
||||
// Function value construction: treat as pure with allocation
|
||||
MirInstruction::NewClosure { .. } => EffectMask::PURE.add(Effect::Alloc),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the destination ValueId if this instruction produces a value
|
||||
pub fn dst_value(&self) -> Option<ValueId> {
|
||||
if let Some(dst) = inst_meta::dst_via_meta(self) {
|
||||
return Some(dst);
|
||||
}
|
||||
match self {
|
||||
MirInstruction::Const { dst, .. }
|
||||
| MirInstruction::BinOp { dst, .. }
|
||||
| MirInstruction::UnaryOp { dst, .. }
|
||||
| MirInstruction::Compare { dst, .. }
|
||||
| MirInstruction::Load { dst, .. }
|
||||
| MirInstruction::Phi { dst, .. }
|
||||
| MirInstruction::NewBox { dst, .. }
|
||||
| MirInstruction::TypeCheck { dst, .. }
|
||||
| MirInstruction::Cast { dst, .. }
|
||||
| MirInstruction::TypeOp { dst, .. }
|
||||
| MirInstruction::ArrayGet { dst, .. }
|
||||
| MirInstruction::Copy { dst, .. }
|
||||
| MirInstruction::RefNew { dst, .. }
|
||||
| MirInstruction::RefGet { dst, .. }
|
||||
| MirInstruction::WeakNew { dst, .. }
|
||||
| MirInstruction::WeakLoad { dst, .. }
|
||||
| MirInstruction::WeakRef { dst, .. }
|
||||
| MirInstruction::FutureNew { dst, .. }
|
||||
| MirInstruction::Await { dst, .. } => Some(*dst),
|
||||
MirInstruction::NewClosure { dst, .. } => Some(*dst),
|
||||
|
||||
MirInstruction::Call { dst, .. }
|
||||
| MirInstruction::BoxCall { dst, .. }
|
||||
| MirInstruction::PluginInvoke { dst, .. }
|
||||
| MirInstruction::ExternCall { dst, .. } => *dst,
|
||||
|
||||
MirInstruction::Store { .. }
|
||||
| MirInstruction::Branch { .. }
|
||||
| MirInstruction::Jump { .. }
|
||||
| MirInstruction::Return { .. }
|
||||
| MirInstruction::ArraySet { .. }
|
||||
| MirInstruction::Debug { .. }
|
||||
| MirInstruction::Print { .. }
|
||||
| MirInstruction::Throw { .. }
|
||||
| MirInstruction::RefSet { .. }
|
||||
| MirInstruction::BarrierRead { .. }
|
||||
| MirInstruction::BarrierWrite { .. }
|
||||
| MirInstruction::Barrier { .. }
|
||||
| MirInstruction::FutureSet { .. }
|
||||
| MirInstruction::Safepoint
|
||||
| MirInstruction::Nop => None,
|
||||
|
||||
MirInstruction::Catch {
|
||||
exception_value, ..
|
||||
} => Some(*exception_value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all ValueIds used by this instruction
|
||||
pub fn used_values(&self) -> Vec<ValueId> {
|
||||
if let Some(used) = inst_meta::used_via_meta(self) {
|
||||
return used;
|
||||
}
|
||||
match self {
|
||||
MirInstruction::Const { .. } | MirInstruction::Jump { .. } | MirInstruction::Nop => {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
MirInstruction::UnaryOp { operand, .. }
|
||||
| MirInstruction::Load { ptr: operand, .. }
|
||||
| MirInstruction::TypeCheck { value: operand, .. }
|
||||
| MirInstruction::Cast { value: operand, .. }
|
||||
| MirInstruction::TypeOp { value: operand, .. }
|
||||
| MirInstruction::Copy { src: operand, .. }
|
||||
| MirInstruction::Debug { value: operand, .. }
|
||||
| MirInstruction::Print { value: operand, .. } => vec![*operand],
|
||||
|
||||
MirInstruction::BinOp { lhs, rhs, .. }
|
||||
| MirInstruction::Compare { lhs, rhs, .. }
|
||||
| MirInstruction::Store {
|
||||
value: lhs,
|
||||
ptr: rhs,
|
||||
..
|
||||
} => vec![*lhs, *rhs],
|
||||
|
||||
MirInstruction::ArrayGet { array, index, .. } => vec![*array, *index],
|
||||
|
||||
MirInstruction::ArraySet {
|
||||
array,
|
||||
index,
|
||||
value,
|
||||
} => vec![*array, *index, *value],
|
||||
|
||||
MirInstruction::Branch { condition, .. } => vec![*condition],
|
||||
|
||||
MirInstruction::Return { value } => value.map(|v| vec![v]).unwrap_or_default(),
|
||||
|
||||
MirInstruction::Call { func, args, .. } => {
|
||||
let mut used = vec![*func];
|
||||
used.extend(args);
|
||||
used
|
||||
}
|
||||
MirInstruction::NewClosure { captures, me, .. } => {
|
||||
let mut used: Vec<ValueId> = Vec::new();
|
||||
used.extend(captures.iter().map(|(_, v)| *v));
|
||||
if let Some(m) = me {
|
||||
used.push(*m);
|
||||
}
|
||||
used
|
||||
}
|
||||
|
||||
MirInstruction::BoxCall { box_val, args, .. }
|
||||
| MirInstruction::PluginInvoke { box_val, args, .. } => {
|
||||
let mut used = vec![*box_val];
|
||||
used.extend(args);
|
||||
used
|
||||
}
|
||||
|
||||
MirInstruction::NewBox { args, .. } => args.clone(),
|
||||
|
||||
MirInstruction::Phi { inputs, .. } => inputs.iter().map(|(_, value)| *value).collect(),
|
||||
|
||||
// Phase 5: Control flow & exception handling
|
||||
MirInstruction::Throw { exception, .. } => vec![*exception],
|
||||
MirInstruction::Catch { .. } => Vec::new(), // Handler setup doesn't use values
|
||||
MirInstruction::Safepoint => Vec::new(),
|
||||
|
||||
// Phase 6: Box reference operations
|
||||
MirInstruction::RefNew { box_val, .. } => vec![*box_val],
|
||||
MirInstruction::RefGet { reference, .. } => vec![*reference],
|
||||
MirInstruction::RefSet {
|
||||
reference, value, ..
|
||||
} => vec![*reference, *value],
|
||||
MirInstruction::WeakNew { box_val, .. } => vec![*box_val],
|
||||
MirInstruction::WeakLoad { weak_ref, .. } => vec![*weak_ref],
|
||||
MirInstruction::BarrierRead { ptr } => vec![*ptr],
|
||||
MirInstruction::BarrierWrite { ptr } => vec![*ptr],
|
||||
MirInstruction::WeakRef { value, .. } => vec![*value],
|
||||
MirInstruction::Barrier { ptr, .. } => vec![*ptr],
|
||||
|
||||
// Phase 7: Async/Future Operations
|
||||
MirInstruction::FutureNew { value, .. } => vec![*value],
|
||||
MirInstruction::FutureSet { future, value } => vec![*future, *value],
|
||||
MirInstruction::Await { future, .. } => vec![*future],
|
||||
|
||||
// Phase 9.7: External Function Calls
|
||||
MirInstruction::ExternCall { args, .. } => args.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl ConstValue {
|
||||
/*
|
||||
/// Convert to NyashValue
|
||||
pub fn to_nyash_value(&self) -> NyashValue {
|
||||
match self {
|
||||
ConstValue::Integer(n) => NyashValue::new_integer(*n),
|
||||
ConstValue::Float(f) => NyashValue::new_float(*f),
|
||||
ConstValue::Bool(b) => NyashValue::new_bool(*b),
|
||||
ConstValue::String(s) => NyashValue::new_string(s.clone()),
|
||||
ConstValue::Null => NyashValue::new_null(),
|
||||
ConstValue::Void => NyashValue::new_void(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from NyashValue
|
||||
pub fn from_nyash_value(value: &NyashValue) -> Option<Self> {
|
||||
match value {
|
||||
NyashValue::Integer(n) => Some(ConstValue::Integer(*n)),
|
||||
NyashValue::Float(f) => Some(ConstValue::Float(*f)),
|
||||
NyashValue::Bool(b) => Some(ConstValue::Bool(*b)),
|
||||
NyashValue::String(s) => Some(ConstValue::String(s.clone())),
|
||||
NyashValue::Null => Some(ConstValue::Null),
|
||||
NyashValue::Void => Some(ConstValue::Void),
|
||||
_ => None, // Collections and Boxes can't be constants
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
impl fmt::Display for MirInstruction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
MirInstruction::Const { dst, value } => {
|
||||
write!(f, "{} = const {}", dst, value)
|
||||
}
|
||||
MirInstruction::BinOp { dst, op, lhs, rhs } => {
|
||||
write!(f, "{} = {} {:?} {}", dst, lhs, op, rhs)
|
||||
}
|
||||
MirInstruction::UnaryOp { dst, op, operand } => {
|
||||
write!(f, "{} = {:?} {}", dst, op, operand)
|
||||
}
|
||||
MirInstruction::Compare { dst, op, lhs, rhs } => {
|
||||
write!(f, "{} = {} {:?} {}", dst, lhs, op, rhs)
|
||||
}
|
||||
MirInstruction::Load { dst, ptr } => {
|
||||
write!(f, "{} = load {}", dst, ptr)
|
||||
}
|
||||
MirInstruction::Store { value, ptr } => {
|
||||
write!(f, "store {} -> {}", value, ptr)
|
||||
}
|
||||
MirInstruction::Call {
|
||||
dst,
|
||||
func,
|
||||
callee: _, // TODO: Use callee for type-safe resolution display
|
||||
args,
|
||||
effects,
|
||||
} => {
|
||||
if let Some(dst) = dst {
|
||||
write!(
|
||||
f,
|
||||
"{} = call {}({}); effects: {}",
|
||||
dst,
|
||||
func,
|
||||
args.iter()
|
||||
.map(|v| format!("{}", v))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
effects
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"call {}({}); effects: {}",
|
||||
func,
|
||||
args.iter()
|
||||
.map(|v| format!("{}", v))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
effects
|
||||
)
|
||||
}
|
||||
}
|
||||
MirInstruction::PluginInvoke {
|
||||
dst,
|
||||
box_val,
|
||||
method,
|
||||
args,
|
||||
effects: _,
|
||||
} => {
|
||||
if let Some(dst) = dst {
|
||||
write!(
|
||||
f,
|
||||
"{} = plugin_invoke {}.{}({})",
|
||||
dst,
|
||||
box_val,
|
||||
method,
|
||||
args.iter()
|
||||
.map(|v| format!("{}", v))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"plugin_invoke {}.{}({})",
|
||||
box_val,
|
||||
method,
|
||||
args.iter()
|
||||
.map(|v| format!("{}", v))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
MirInstruction::Return { value } => {
|
||||
if let Some(value) = value {
|
||||
write!(f, "ret {}", value)
|
||||
} else {
|
||||
write!(f, "ret void")
|
||||
}
|
||||
}
|
||||
MirInstruction::ExternCall {
|
||||
dst,
|
||||
iface_name,
|
||||
method_name,
|
||||
args,
|
||||
effects,
|
||||
} => {
|
||||
if let Some(dst) = dst {
|
||||
write!(
|
||||
f,
|
||||
"{} = extern_call {}.{}({}); effects: {}",
|
||||
dst,
|
||||
iface_name,
|
||||
method_name,
|
||||
args.iter()
|
||||
.map(|v| format!("{}", v))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
effects
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"extern_call {}.{}({}); effects: {}",
|
||||
iface_name,
|
||||
method_name,
|
||||
args.iter()
|
||||
.map(|v| format!("{}", v))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
effects
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => write!(f, "{:?}", self), // Fallback for other instructions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method implementations have been moved to src/mir/instruction/methods.rs
|
||||
#[path = "instruction/methods.rs"]
|
||||
mod methods;
|
||||
|
||||
// Display implementation has been moved to src/mir/instruction/display.rs
|
||||
#[path = "instruction/display.rs"]
|
||||
mod display;
|
||||
|
||||
// Tests have been moved to src/mir/instruction/tests.rs for better organization
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_const_instruction() {
|
||||
let dst = ValueId::new(0);
|
||||
let inst = MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::Integer(42),
|
||||
};
|
||||
|
||||
assert_eq!(inst.dst_value(), Some(dst));
|
||||
assert!(inst.used_values().is_empty());
|
||||
assert!(inst.effects().is_pure());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_binop_instruction() {
|
||||
let dst = ValueId::new(0);
|
||||
let lhs = ValueId::new(1);
|
||||
let rhs = ValueId::new(2);
|
||||
|
||||
let inst = MirInstruction::BinOp {
|
||||
dst,
|
||||
op: BinaryOp::Add,
|
||||
lhs,
|
||||
rhs,
|
||||
};
|
||||
|
||||
assert_eq!(inst.dst_value(), Some(dst));
|
||||
assert_eq!(inst.used_values(), vec![lhs, rhs]);
|
||||
assert!(inst.effects().is_pure());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_call_instruction() {
|
||||
let dst = ValueId::new(0);
|
||||
let func = ValueId::new(1);
|
||||
let arg1 = ValueId::new(2);
|
||||
let arg2 = ValueId::new(3);
|
||||
|
||||
let inst = MirInstruction::Call {
|
||||
dst: Some(dst),
|
||||
func,
|
||||
args: vec![arg1, arg2],
|
||||
effects: EffectMask::IO,
|
||||
};
|
||||
|
||||
assert_eq!(inst.dst_value(), Some(dst));
|
||||
assert_eq!(inst.used_values(), vec![func, arg1, arg2]);
|
||||
assert_eq!(inst.effects(), EffectMask::IO);
|
||||
}
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn test_const_value_conversion() {
|
||||
let const_val = ConstValue::Integer(42);
|
||||
let nyash_val = const_val.to_nyash_value();
|
||||
|
||||
assert_eq!(nyash_val, NyashValue::new_integer(42));
|
||||
|
||||
let back = ConstValue::from_nyash_value(&nyash_val).unwrap();
|
||||
assert_eq!(back, const_val);
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn test_ref_new_instruction() {
|
||||
let dst = ValueId::new(0);
|
||||
let box_val = ValueId::new(1);
|
||||
let inst = MirInstruction::RefNew { dst, box_val };
|
||||
|
||||
assert_eq!(inst.dst_value(), Some(dst));
|
||||
assert_eq!(inst.used_values(), vec![box_val]);
|
||||
assert!(inst.effects().is_pure());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ref_get_instruction() {
|
||||
let dst = ValueId::new(0);
|
||||
let reference = ValueId::new(1);
|
||||
let field = "name".to_string();
|
||||
let inst = MirInstruction::RefGet {
|
||||
dst,
|
||||
reference,
|
||||
field,
|
||||
};
|
||||
|
||||
assert_eq!(inst.dst_value(), Some(dst));
|
||||
assert_eq!(inst.used_values(), vec![reference]);
|
||||
assert!(!inst.effects().is_pure());
|
||||
assert!(inst
|
||||
.effects()
|
||||
.contains(super::super::effect::Effect::ReadHeap));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ref_set_instruction() {
|
||||
let reference = ValueId::new(0);
|
||||
let field = "value".to_string();
|
||||
let value = ValueId::new(1);
|
||||
let inst = MirInstruction::RefSet {
|
||||
reference,
|
||||
field,
|
||||
value,
|
||||
};
|
||||
|
||||
assert_eq!(inst.dst_value(), None);
|
||||
assert_eq!(inst.used_values(), vec![reference, value]);
|
||||
assert!(!inst.effects().is_pure());
|
||||
assert!(inst
|
||||
.effects()
|
||||
.contains(super::super::effect::Effect::WriteHeap));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_weak_new_instruction() {
|
||||
let dst = ValueId::new(0);
|
||||
let box_val = ValueId::new(1);
|
||||
let inst = MirInstruction::WeakNew { dst, box_val };
|
||||
|
||||
assert_eq!(inst.dst_value(), Some(dst));
|
||||
assert_eq!(inst.used_values(), vec![box_val]);
|
||||
assert!(inst.effects().is_pure());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_weak_load_instruction() {
|
||||
let dst = ValueId::new(0);
|
||||
let weak_ref = ValueId::new(1);
|
||||
let inst = MirInstruction::WeakLoad { dst, weak_ref };
|
||||
|
||||
assert_eq!(inst.dst_value(), Some(dst));
|
||||
assert_eq!(inst.used_values(), vec![weak_ref]);
|
||||
assert!(!inst.effects().is_pure());
|
||||
assert!(inst
|
||||
.effects()
|
||||
.contains(super::super::effect::Effect::ReadHeap));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_barrier_instructions() {
|
||||
let ptr = ValueId::new(0);
|
||||
|
||||
let read_barrier = MirInstruction::BarrierRead { ptr };
|
||||
assert_eq!(read_barrier.dst_value(), None);
|
||||
assert_eq!(read_barrier.used_values(), vec![ptr]);
|
||||
assert!(read_barrier
|
||||
.effects()
|
||||
.contains(super::super::effect::Effect::Barrier));
|
||||
assert!(read_barrier
|
||||
.effects()
|
||||
.contains(super::super::effect::Effect::ReadHeap));
|
||||
|
||||
let write_barrier = MirInstruction::BarrierWrite { ptr };
|
||||
assert_eq!(write_barrier.dst_value(), None);
|
||||
assert_eq!(write_barrier.used_values(), vec![ptr]);
|
||||
assert!(write_barrier
|
||||
.effects()
|
||||
.contains(super::super::effect::Effect::Barrier));
|
||||
assert!(write_barrier
|
||||
.effects()
|
||||
.contains(super::super::effect::Effect::WriteHeap));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extern_call_instruction() {
|
||||
let dst = ValueId::new(0);
|
||||
let arg1 = ValueId::new(1);
|
||||
let arg2 = ValueId::new(2);
|
||||
let inst = MirInstruction::ExternCall {
|
||||
dst: Some(dst),
|
||||
iface_name: "env.console".to_string(),
|
||||
method_name: "log".to_string(),
|
||||
args: vec![arg1, arg2],
|
||||
effects: super::super::effect::EffectMask::IO,
|
||||
};
|
||||
|
||||
assert_eq!(inst.dst_value(), Some(dst));
|
||||
assert_eq!(inst.used_values(), vec![arg1, arg2]);
|
||||
assert_eq!(inst.effects(), super::super::effect::EffectMask::IO);
|
||||
|
||||
// Test void extern call
|
||||
let void_inst = MirInstruction::ExternCall {
|
||||
dst: None,
|
||||
iface_name: "env.canvas".to_string(),
|
||||
method_name: "fillRect".to_string(),
|
||||
args: vec![arg1],
|
||||
effects: super::super::effect::EffectMask::IO,
|
||||
};
|
||||
|
||||
assert_eq!(void_inst.dst_value(), None);
|
||||
assert_eq!(void_inst.used_values(), vec![arg1]);
|
||||
}
|
||||
}
|
||||
#[path = "instruction/tests.rs"]
|
||||
mod tests;
|
||||
|
||||
Reference in New Issue
Block a user