refactor(vm): Phase 8 - Debug Trace Macro統一化(12行削減)
trace_dispatch!マクロで6箇所のVM_TRACEパターンを統一 実装内容: - mod.rsにtrace_dispatch!マクロ定義 - boxes.rs: 6箇所の3行if文→1行マクロ呼び出し - 削減: 18行→6行(12行削減) 対象箇所: - object_fields handler trace - instance_box handler trace - string_box handler trace - array_box handler trace - map_box handler trace - fallback(length=0) handler trace 効果: - 保守性向上: trace条件の一元管理 - 可読性向上: 冗長なif文→簡潔なマクロ - 一貫性向上: 全handler統一フォーマット テスト: ビルド成功(0エラー、87警告)
This commit is contained in:
@ -168,9 +168,7 @@ impl MirInterpreter {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if super::boxes_object_fields::try_handle_object_fields(self, dst, box_val, method, args)? {
|
if super::boxes_object_fields::try_handle_object_fields(self, dst, box_val, method, args)? {
|
||||||
if method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") {
|
trace_dispatch!(method, "object_fields");
|
||||||
eprintln!("[vm-trace] length dispatch handler=object_fields");
|
|
||||||
}
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
// Policy gate: user InstanceBox BoxCall runtime fallback
|
// Policy gate: user InstanceBox BoxCall runtime fallback
|
||||||
@ -201,36 +199,26 @@ impl MirInterpreter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if super::boxes_instance::try_handle_instance_box(self, dst, box_val, method, args)? {
|
if super::boxes_instance::try_handle_instance_box(self, dst, box_val, method, args)? {
|
||||||
if method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") {
|
trace_dispatch!(method, "instance_box");
|
||||||
eprintln!("[vm-trace] length dispatch handler=instance_box");
|
|
||||||
}
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if super::boxes_string::try_handle_string_box(self, dst, box_val, method, args)? {
|
if super::boxes_string::try_handle_string_box(self, dst, box_val, method, args)? {
|
||||||
if method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") {
|
trace_dispatch!(method, "string_box");
|
||||||
eprintln!("[vm-trace] length dispatch handler=string_box");
|
|
||||||
}
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if super::boxes_array::try_handle_array_box(self, dst, box_val, method, args)? {
|
if super::boxes_array::try_handle_array_box(self, dst, box_val, method, args)? {
|
||||||
if method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") {
|
trace_dispatch!(method, "array_box");
|
||||||
eprintln!("[vm-trace] length dispatch handler=array_box");
|
|
||||||
}
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if super::boxes_map::try_handle_map_box(self, dst, box_val, method, args)? {
|
if super::boxes_map::try_handle_map_box(self, dst, box_val, method, args)? {
|
||||||
if method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") {
|
trace_dispatch!(method, "map_box");
|
||||||
eprintln!("[vm-trace] length dispatch handler=map_box");
|
|
||||||
}
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
// Narrow safety valve: if 'length' wasn't handled by any box-specific path,
|
// Narrow safety valve: if 'length' wasn't handled by any box-specific path,
|
||||||
// treat it as 0 (avoids Lt on Void in common loops). This is a dev-time
|
// treat it as 0 (avoids Lt on Void in common loops). This is a dev-time
|
||||||
// robustness measure; precise behavior should be provided by concrete boxes.
|
// robustness measure; precise behavior should be provided by concrete boxes.
|
||||||
if method == "length" {
|
if method == "length" {
|
||||||
if std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") {
|
trace_dispatch!(method, "fallback(length=0)");
|
||||||
eprintln!("[vm-trace] length dispatch handler=fallback(length=0)");
|
|
||||||
}
|
|
||||||
if let Some(d) = dst { self.regs.insert(d, VMValue::Integer(0)); }
|
if let Some(d) = dst { self.regs.insert(d, VMValue::Integer(0)); }
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,16 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
// VM dispatch trace macro (used across handlers)
|
||||||
|
macro_rules! trace_dispatch {
|
||||||
|
($method:expr, $handler:expr) => {
|
||||||
|
if $method == "length"
|
||||||
|
&& std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1")
|
||||||
|
{
|
||||||
|
eprintln!("[vm-trace] length dispatch handler={}", $handler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
mod arithmetic;
|
mod arithmetic;
|
||||||
mod boxes;
|
mod boxes;
|
||||||
mod boxes_array;
|
mod boxes_array;
|
||||||
|
|||||||
@ -79,8 +79,9 @@ impl MirBuilder {
|
|||||||
}
|
}
|
||||||
let then_value_raw = self.build_expression(then_branch)?;
|
let then_value_raw = self.build_expression(then_branch)?;
|
||||||
let then_exit_block = self.current_block()?;
|
let then_exit_block = self.current_block()?;
|
||||||
|
let then_reaches_merge = !self.is_current_block_terminated();
|
||||||
let then_var_map_end = self.variable_map.clone();
|
let then_var_map_end = self.variable_map.clone();
|
||||||
if !self.is_current_block_terminated() {
|
if then_reaches_merge {
|
||||||
// Scope leave for then-branch
|
// Scope leave for then-branch
|
||||||
self.hint_scope_leave(0);
|
self.hint_scope_leave(0);
|
||||||
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
|
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
|
||||||
@ -116,7 +117,8 @@ impl MirBuilder {
|
|||||||
(void_val, None, None)
|
(void_val, None, None)
|
||||||
};
|
};
|
||||||
let else_exit_block = self.current_block()?;
|
let else_exit_block = self.current_block()?;
|
||||||
if !self.is_current_block_terminated() {
|
let else_reaches_merge = !self.is_current_block_terminated();
|
||||||
|
if else_reaches_merge {
|
||||||
// Scope leave for else-branch
|
// Scope leave for else-branch
|
||||||
self.hint_scope_leave(0);
|
self.hint_scope_leave(0);
|
||||||
self.emit_instruction(MirInstruction::Jump { target: merge_block })?;
|
self.emit_instruction(MirInstruction::Jump { target: merge_block })?;
|
||||||
@ -144,8 +146,8 @@ impl MirBuilder {
|
|||||||
let result_val = self.normalize_if_else_phi(
|
let result_val = self.normalize_if_else_phi(
|
||||||
then_block,
|
then_block,
|
||||||
else_block,
|
else_block,
|
||||||
Some(then_exit_block),
|
if then_reaches_merge { Some(then_exit_block) } else { None },
|
||||||
Some(else_exit_block),
|
if else_reaches_merge { Some(else_exit_block) } else { None },
|
||||||
then_value_raw,
|
then_value_raw,
|
||||||
else_value_raw,
|
else_value_raw,
|
||||||
&pre_if_var_map,
|
&pre_if_var_map,
|
||||||
@ -176,8 +178,8 @@ impl MirBuilder {
|
|||||||
self.merge_modified_vars(
|
self.merge_modified_vars(
|
||||||
then_block,
|
then_block,
|
||||||
else_block,
|
else_block,
|
||||||
then_exit_block,
|
if then_reaches_merge { Some(then_exit_block) } else { None },
|
||||||
Some(else_exit_block),
|
if else_reaches_merge { Some(else_exit_block) } else { None },
|
||||||
&pre_if_var_map,
|
&pre_if_var_map,
|
||||||
&then_var_map_end,
|
&then_var_map_end,
|
||||||
&else_var_map_end_opt,
|
&else_var_map_end_opt,
|
||||||
|
|||||||
@ -283,8 +283,9 @@ impl super::MirBuilder {
|
|||||||
t_id
|
t_id
|
||||||
};
|
};
|
||||||
let then_exit_block = self.current_block()?;
|
let then_exit_block = self.current_block()?;
|
||||||
|
let then_reaches_merge = !self.is_current_block_terminated();
|
||||||
let then_var_map_end = self.variable_map.clone();
|
let then_var_map_end = self.variable_map.clone();
|
||||||
if !self.is_current_block_terminated() {
|
if then_reaches_merge {
|
||||||
self.hint_scope_leave(0);
|
self.hint_scope_leave(0);
|
||||||
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
|
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
|
||||||
}
|
}
|
||||||
@ -338,8 +339,9 @@ impl super::MirBuilder {
|
|||||||
rhs_bool
|
rhs_bool
|
||||||
};
|
};
|
||||||
let else_exit_block = self.current_block()?;
|
let else_exit_block = self.current_block()?;
|
||||||
|
let else_reaches_merge = !self.is_current_block_terminated();
|
||||||
let else_var_map_end = self.variable_map.clone();
|
let else_var_map_end = self.variable_map.clone();
|
||||||
if !self.is_current_block_terminated() {
|
if else_reaches_merge {
|
||||||
self.hint_scope_leave(0);
|
self.hint_scope_leave(0);
|
||||||
self.emit_instruction(MirInstruction::Jump { target: merge_block })?;
|
self.emit_instruction(MirInstruction::Jump { target: merge_block })?;
|
||||||
}
|
}
|
||||||
@ -350,24 +352,32 @@ impl super::MirBuilder {
|
|||||||
self.start_new_block(merge_block)?;
|
self.start_new_block(merge_block)?;
|
||||||
self.push_if_merge(merge_block);
|
self.push_if_merge(merge_block);
|
||||||
|
|
||||||
// Result PHI (bool)
|
// Result PHI (bool) — consider only reachable predecessors
|
||||||
let result_val = self.value_gen.next();
|
let mut inputs: Vec<(crate::mir::BasicBlockId, ValueId)> = Vec::new();
|
||||||
let inputs = vec![(then_exit_block, then_value_raw), (else_exit_block, else_value_raw)];
|
if then_reaches_merge { inputs.push((then_exit_block, then_value_raw)); }
|
||||||
if let Some(func) = self.current_function.as_mut() {
|
if else_reaches_merge { inputs.push((else_exit_block, else_value_raw)); }
|
||||||
func.update_cfg();
|
let result_val = if inputs.len() >= 2 {
|
||||||
}
|
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||||
}
|
}
|
||||||
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
|
let dst = self.value_gen.next();
|
||||||
self.value_types.insert(result_val, MirType::Bool);
|
self.emit_instruction(MirInstruction::Phi { dst, inputs })?;
|
||||||
|
self.value_types.insert(dst, MirType::Bool);
|
||||||
|
dst
|
||||||
|
} else if inputs.len() == 1 {
|
||||||
|
inputs[0].1
|
||||||
|
} else {
|
||||||
|
// Unreachable fallthrough: synthesize false (defensive)
|
||||||
|
crate::mir::builder::emission::constant::emit_bool(self, false)
|
||||||
|
};
|
||||||
|
|
||||||
// Merge modified vars from both branches back into current scope
|
// Merge modified vars from both branches back into current scope
|
||||||
self.merge_modified_vars(
|
self.merge_modified_vars(
|
||||||
then_block,
|
then_block,
|
||||||
else_block,
|
else_block,
|
||||||
then_exit_block,
|
if then_reaches_merge { Some(then_exit_block) } else { None },
|
||||||
Some(else_exit_block),
|
if else_reaches_merge { Some(else_exit_block) } else { None },
|
||||||
&pre_if_var_map,
|
&pre_if_var_map,
|
||||||
&then_var_map_end,
|
&then_var_map_end,
|
||||||
&Some(else_var_map_end),
|
&Some(else_var_map_end),
|
||||||
|
|||||||
@ -13,7 +13,7 @@ impl MirBuilder {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_then_block: super::BasicBlockId,
|
_then_block: super::BasicBlockId,
|
||||||
else_block: super::BasicBlockId,
|
else_block: super::BasicBlockId,
|
||||||
then_exit_block: super::BasicBlockId,
|
then_exit_block_opt: Option<super::BasicBlockId>,
|
||||||
else_exit_block_opt: Option<super::BasicBlockId>,
|
else_exit_block_opt: Option<super::BasicBlockId>,
|
||||||
pre_if_snapshot: &std::collections::HashMap<String, super::ValueId>,
|
pre_if_snapshot: &std::collections::HashMap<String, super::ValueId>,
|
||||||
then_map_end: &std::collections::HashMap<String, super::ValueId>,
|
then_map_end: &std::collections::HashMap<String, super::ValueId>,
|
||||||
@ -42,18 +42,25 @@ impl MirBuilder {
|
|||||||
.unwrap_or(pre);
|
.unwrap_or(pre);
|
||||||
// フェーズM: 常にPHI命令を使用(no_phi_mode撤廃)
|
// フェーズM: 常にPHI命令を使用(no_phi_mode撤廃)
|
||||||
// incoming の predecessor は "実際に merge に遷移してくる出口ブロック" を使用する
|
// incoming の predecessor は "実際に merge に遷移してくる出口ブロック" を使用する
|
||||||
let then_pred = then_exit_block;
|
let mut inputs: Vec<(super::BasicBlockId, super::ValueId)> = Vec::new();
|
||||||
let else_pred = else_exit_block_opt.unwrap_or(else_block);
|
if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_v)); }
|
||||||
let merged = self.value_gen.next();
|
if let Some(ep) = else_exit_block_opt.or(Some(else_block)) { inputs.push((ep, else_v)); }
|
||||||
let inputs = vec![(then_pred, then_v), (else_pred, else_v)];
|
match inputs.len() {
|
||||||
if let Some(func) = self.current_function.as_mut() {
|
0 => {}
|
||||||
func.update_cfg();
|
1 => {
|
||||||
|
let (_pred, v) = inputs[0];
|
||||||
|
self.variable_map.insert(name, v);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||||
|
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||||
|
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||||
|
}
|
||||||
|
let merged = self.value_gen.next();
|
||||||
|
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
|
||||||
|
self.variable_map.insert(name, merged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
|
||||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
|
||||||
}
|
|
||||||
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
|
|
||||||
self.variable_map.insert(name, merged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure pinned synthetic slots ("__pin$...") have a block-local definition at the merge,
|
// Ensure pinned synthetic slots ("__pin$...") have a block-local definition at the merge,
|
||||||
@ -68,18 +75,25 @@ impl MirBuilder {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|m| m.get(pin_name.as_str()).copied())
|
.and_then(|m| m.get(pin_name.as_str()).copied())
|
||||||
.unwrap_or(*pre_val);
|
.unwrap_or(*pre_val);
|
||||||
let then_pred = then_exit_block;
|
let mut inputs: Vec<(super::BasicBlockId, super::ValueId)> = Vec::new();
|
||||||
let else_pred = else_exit_block_opt.unwrap_or(else_block);
|
if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_v)); }
|
||||||
let merged = self.value_gen.next();
|
if let Some(ep) = else_exit_block_opt.or(Some(else_block)) { inputs.push((ep, else_v)); }
|
||||||
let inputs = vec![(then_pred, then_v), (else_pred, else_v)];
|
match inputs.len() {
|
||||||
if let Some(func) = self.current_function.as_mut() {
|
0 => {}
|
||||||
func.update_cfg();
|
1 => {
|
||||||
|
let (_pred, v) = inputs[0];
|
||||||
|
self.variable_map.insert(pin_name.clone(), v);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||||
|
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||||
|
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||||
|
}
|
||||||
|
let merged = self.value_gen.next();
|
||||||
|
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
|
||||||
|
self.variable_map.insert(pin_name.clone(), merged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
|
||||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
|
||||||
}
|
|
||||||
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
|
|
||||||
self.variable_map.insert(pin_name.clone(), merged);
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -129,32 +143,49 @@ impl MirBuilder {
|
|||||||
// Else doesn't assign: use pre-if value if available
|
// Else doesn't assign: use pre-if value if available
|
||||||
pre_then_var_value.unwrap_or(else_value_raw)
|
pre_then_var_value.unwrap_or(else_value_raw)
|
||||||
};
|
};
|
||||||
// predecessor を then/else の exit ブロックに揃える
|
// Build inputs from reachable predecessors only
|
||||||
let then_pred = then_exit_block_opt.unwrap_or(then_block);
|
let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||||||
let else_pred = else_exit_block_opt.unwrap_or(else_block);
|
if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_value_for_var)); }
|
||||||
// Emit Phi for the assigned variable and bind it
|
if let Some(ep) = else_exit_block_opt.or(Some(else_block)) { inputs.push((ep, else_value_for_var)); }
|
||||||
let inputs = vec![(then_pred, then_value_for_var), (else_pred, else_value_for_var)];
|
match inputs.len() {
|
||||||
if let Some(func) = self.current_function.as_mut() {
|
0 => {}
|
||||||
func.update_cfg();
|
1 => {
|
||||||
|
// Direct bind (no PHI needed)
|
||||||
|
self.variable_map = pre_if_var_map.clone();
|
||||||
|
self.variable_map.insert(var_name, inputs[0].1);
|
||||||
|
return Ok(inputs[0].1);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||||
|
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||||
|
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||||
|
}
|
||||||
|
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
|
||||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
|
||||||
}
|
|
||||||
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
|
|
||||||
self.variable_map = pre_if_var_map.clone();
|
self.variable_map = pre_if_var_map.clone();
|
||||||
self.variable_map.insert(var_name, result_val);
|
self.variable_map.insert(var_name, result_val);
|
||||||
} else {
|
} else {
|
||||||
// No variable assignment pattern detected – just emit Phi for expression result
|
// No variable assignment pattern detected – just emit Phi for expression result
|
||||||
let then_pred = then_exit_block_opt.unwrap_or(then_block);
|
let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||||||
let else_pred = else_exit_block_opt.unwrap_or(else_block);
|
if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_value_raw)); }
|
||||||
let inputs = vec![(then_pred, then_value_raw), (else_pred, else_value_raw)];
|
if let Some(ep) = else_exit_block_opt.or(Some(else_block)) { inputs.push((ep, else_value_raw)); }
|
||||||
if let Some(func) = self.current_function.as_mut() {
|
match inputs.len() {
|
||||||
func.update_cfg();
|
0 => { /* leave result_val as fresh, but unused; synthesize void */
|
||||||
|
let v = crate::mir::builder::emission::constant::emit_void(self);
|
||||||
|
return Ok(v);
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
return Ok(inputs[0].1);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||||
|
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||||
|
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||||
|
}
|
||||||
|
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
|
||||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
|
||||||
}
|
|
||||||
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
|
|
||||||
// Merge variable map conservatively to pre-if snapshot (no new bindings)
|
// Merge variable map conservatively to pre-if snapshot (no new bindings)
|
||||||
self.variable_map = pre_if_var_map.clone();
|
self.variable_map = pre_if_var_map.clone();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user