Normalize passes keep spans and clean warnings

This commit is contained in:
nyash-codex
2025-11-24 15:02:51 +09:00
parent 466e636af6
commit da1a5558e5
40 changed files with 547 additions and 362 deletions

View File

@ -1,7 +1,9 @@
use crate::ast::Span;
use crate::mir::optimizer::MirOptimizer;
use crate::mir::optimizer_stats::OptimizationStats;
use crate::mir::{BarrierOp, MirModule, SpannedInstruction, TypeOpKind, ValueId, WeakRefOp};
use crate::mir::{
BarrierOp, EffectMask, MirModule, SpannedInstruction, TypeOpKind, ValueId, WeakRefOp,
};
use crate::ast::Span;
fn idemp_enabled() -> bool {
std::env::var("NYASH_MIR_DEV_IDEMP").ok().as_deref() == Some("1")
@ -36,26 +38,46 @@ pub fn force_plugin_invoke(_opt: &mut MirOptimizer, module: &mut MirModule) -> O
None => continue,
};
for (_bb, block) in &mut function.blocks {
for inst in &mut block.instructions {
if let I::BoxCall {
dst,
box_val,
method,
args,
effects,
..
} = inst.clone()
{
*inst = I::PluginInvoke {
let old_spanned = block.drain_spanned_instructions();
let mut new_spanned = Vec::with_capacity(old_spanned.len());
for SpannedInstruction { inst, span } in old_spanned {
let rewritten = match inst {
I::BoxCall {
dst,
box_val,
method,
args,
effects,
};
stats.intrinsic_optimizations += 1;
}
..
} => {
stats.intrinsic_optimizations += 1;
I::PluginInvoke {
dst,
box_val,
method,
args,
effects,
}
}
other => other,
};
new_spanned.push(SpannedInstruction {
inst: rewritten,
span,
});
}
let (insts, spans): (Vec<_>, Vec<_>) = new_spanned
.into_iter()
.map(|sp| (sp.inst, sp.span))
.unzip();
block.instructions = insts;
block.instruction_spans = spans;
block.effects = block
.instructions
.iter()
.chain(block.terminator.iter())
.fold(EffectMask::PURE, |mask, inst| mask | inst.effects());
}
if idemp_enabled() {
let key = idemp_key(pass_name, &fname);
@ -85,11 +107,13 @@ pub fn normalize_python_helper_calls(
None => continue,
};
for (_bb, block) in &mut function.blocks {
for inst in &mut block.instructions {
let old_spanned = block.drain_spanned_instructions();
let mut new_spanned = Vec::with_capacity(old_spanned.len());
for SpannedInstruction { mut inst, span } in old_spanned {
if let I::PluginInvoke {
box_val,
method,
args,
ref mut box_val,
ref method,
ref mut args,
..
} = inst
{
@ -105,7 +129,20 @@ pub fn normalize_python_helper_calls(
stats.intrinsic_optimizations += 1;
}
}
new_spanned.push(SpannedInstruction { inst, span });
}
let (insts, spans): (Vec<_>, Vec<_>) = new_spanned
.into_iter()
.map(|sp| (sp.inst, sp.span))
.unzip();
block.instructions = insts;
block.instruction_spans = spans;
block.effects = block
.instructions
.iter()
.chain(block.terminator.iter())
.fold(EffectMask::PURE, |mask, inst| mask | inst.effects());
}
if idemp_enabled() {
let key = idemp_key(pass_name, &fname);
@ -143,90 +180,79 @@ pub fn normalize_legacy_instructions(
None => continue,
};
for (_bb, block) in &mut function.blocks {
for inst in &mut block.instructions {
match inst {
let old_spanned = block.drain_spanned_instructions();
let mut new_spanned = Vec::with_capacity(old_spanned.len());
for SpannedInstruction { inst, span } in old_spanned {
let rewritten = match inst {
I::WeakNew { dst, box_val } => {
let d = *dst;
let v = *box_val;
*inst = I::WeakRef {
dst: d,
op: WeakRefOp::New,
value: v,
};
stats.intrinsic_optimizations += 1;
I::WeakRef {
dst,
op: WeakRefOp::New,
value: box_val,
}
}
I::WeakLoad { dst, weak_ref } => {
let d = *dst;
let v = *weak_ref;
*inst = I::WeakRef {
dst: d,
op: WeakRefOp::Load,
value: v,
};
stats.intrinsic_optimizations += 1;
I::WeakRef {
dst,
op: WeakRefOp::Load,
value: weak_ref,
}
}
I::BarrierRead { ptr } => {
let p = *ptr;
*inst = I::Barrier {
op: BarrierOp::Read,
ptr: p,
};
stats.intrinsic_optimizations += 1;
I::Barrier {
op: BarrierOp::Read,
ptr,
}
}
I::BarrierWrite { ptr } => {
let p = *ptr;
*inst = I::Barrier {
op: BarrierOp::Write,
ptr: p,
};
stats.intrinsic_optimizations += 1;
I::Barrier {
op: BarrierOp::Write,
ptr,
}
}
I::Print { value, .. } => {
let v = *value;
*inst = I::ExternCall {
stats.intrinsic_optimizations += 1;
I::ExternCall {
dst: None,
iface_name: "env.console".to_string(),
method_name: "log".to_string(),
args: vec![v],
args: vec![value],
effects: crate::mir::EffectMask::PURE.add(crate::mir::Effect::Io),
};
stats.intrinsic_optimizations += 1;
}
}
I::ArrayGet { dst, array, index } if array_to_boxcall => {
let d = *dst;
let a = *array;
let i = *index;
stats.intrinsic_optimizations += 1;
let mid =
crate::mir::slot_registry::resolve_slot_by_type_name("ArrayBox", "get");
*inst = I::BoxCall {
dst: Some(d),
box_val: a,
I::BoxCall {
dst: Some(dst),
box_val: array,
method: "get".to_string(),
method_id: mid,
args: vec![i],
args: vec![index],
effects: crate::mir::EffectMask::READ,
};
stats.intrinsic_optimizations += 1;
}
}
I::ArraySet {
array,
index,
value,
} if array_to_boxcall => {
let a = *array;
let i = *index;
let v = *value;
stats.intrinsic_optimizations += 1;
let mid =
crate::mir::slot_registry::resolve_slot_by_type_name("ArrayBox", "set");
*inst = I::BoxCall {
I::BoxCall {
dst: None,
box_val: a,
box_val: array,
method: "set".to_string(),
method_id: mid,
args: vec![i, v],
args: vec![index, value],
effects: crate::mir::EffectMask::WRITE,
};
stats.intrinsic_optimizations += 1;
}
}
I::PluginInvoke {
dst,
@ -235,176 +261,163 @@ pub fn normalize_legacy_instructions(
args,
effects,
} => {
let d = *dst;
let recv = *box_val;
let m = method.clone();
let as_ = args.clone();
let eff = *effects;
*inst = I::BoxCall {
dst: d,
box_val: recv,
method: m,
method_id: None,
args: as_,
effects: eff,
};
stats.intrinsic_optimizations += 1;
I::BoxCall {
dst,
box_val,
method,
method_id: None,
args,
effects,
}
}
I::Debug { .. } if !rw_dbg => {
*inst = I::Nop;
}
I::Safepoint if !rw_sp => {
*inst = I::Nop;
}
I::FutureNew { dst, value } if rw_future => {
let d = *dst;
let v = *value;
*inst = I::ExternCall {
dst: Some(d),
iface_name: "env.future".to_string(),
method_name: "new".to_string(),
args: vec![v],
effects: crate::mir::EffectMask::PURE.add(crate::mir::Effect::Io),
};
}
I::FutureSet { future, value } if rw_future => {
let f = *future;
let v = *value;
*inst = I::ExternCall {
dst: None,
iface_name: "env.future".to_string(),
method_name: "set".to_string(),
args: vec![f, v],
effects: crate::mir::EffectMask::PURE.add(crate::mir::Effect::Io),
};
}
I::Await { dst, future } if rw_future => {
let d = *dst;
let f = *future;
*inst = I::ExternCall {
dst: Some(d),
iface_name: "env.future".to_string(),
method_name: "await".to_string(),
args: vec![f],
effects: crate::mir::EffectMask::PURE.add(crate::mir::Effect::Io),
};
}
_ => {}
}
I::Debug { .. } if !rw_dbg => I::Nop,
I::Safepoint if !rw_sp => I::Nop,
I::FutureNew { dst, value } if rw_future => I::ExternCall {
dst: Some(dst),
iface_name: "env.future".to_string(),
method_name: "new".to_string(),
args: vec![value],
effects: crate::mir::EffectMask::PURE.add(crate::mir::Effect::Io),
},
I::FutureSet { future, value } if rw_future => I::ExternCall {
dst: None,
iface_name: "env.future".to_string(),
method_name: "set".to_string(),
args: vec![future, value],
effects: crate::mir::EffectMask::PURE.add(crate::mir::Effect::Io),
},
I::Await { dst, future } if rw_future => I::ExternCall {
dst: Some(dst),
iface_name: "env.future".to_string(),
method_name: "await".to_string(),
args: vec![future],
effects: crate::mir::EffectMask::PURE.add(crate::mir::Effect::Io),
},
other => other,
};
new_spanned.push(SpannedInstruction {
inst: rewritten,
span,
});
}
// terminator rewrite (subset migrated as needed)
if let Some(term) = &mut block.terminator {
match term {
let terminator = block.terminator.take();
let terminator_span = block.terminator_span.take();
if let Some(term) = terminator {
let span = terminator_span.unwrap_or_else(Span::unknown);
let rewritten = match term {
I::TypeCheck {
dst,
value,
expected_type,
} => {
let ty = crate::mir::MirType::Box(expected_type.clone());
*term = I::TypeOp {
dst: *dst,
op: TypeOpKind::Check,
value: *value,
ty,
};
let ty = crate::mir::MirType::Box(expected_type);
stats.intrinsic_optimizations += 1;
I::TypeOp {
dst,
op: TypeOpKind::Check,
value,
ty,
}
}
I::Cast {
dst,
value,
target_type,
} => {
let ty = target_type.clone();
*term = I::TypeOp {
dst: *dst,
op: TypeOpKind::Cast,
value: *value,
ty,
};
let ty = target_type;
stats.intrinsic_optimizations += 1;
I::TypeOp {
dst,
op: TypeOpKind::Cast,
value,
ty,
}
}
I::WeakNew { dst, box_val } => {
let d = *dst;
let v = *box_val;
*term = I::WeakRef {
dst: d,
op: WeakRefOp::New,
value: v,
};
stats.intrinsic_optimizations += 1;
I::WeakRef {
dst,
op: WeakRefOp::New,
value: box_val,
}
}
I::WeakLoad { dst, weak_ref } => {
let d = *dst;
let v = *weak_ref;
*term = I::WeakRef {
dst: d,
op: WeakRefOp::Load,
value: v,
};
stats.intrinsic_optimizations += 1;
I::WeakRef {
dst,
op: WeakRefOp::Load,
value: weak_ref,
}
}
I::BarrierRead { ptr } => {
let p = *ptr;
*term = I::Barrier {
op: BarrierOp::Read,
ptr: p,
};
stats.intrinsic_optimizations += 1;
I::Barrier {
op: BarrierOp::Read,
ptr,
}
}
I::BarrierWrite { ptr } => {
let p = *ptr;
*term = I::Barrier {
op: BarrierOp::Write,
ptr: p,
};
stats.intrinsic_optimizations += 1;
I::Barrier {
op: BarrierOp::Write,
ptr,
}
}
I::Print { value, .. } => {
let v = *value;
*term = I::ExternCall {
stats.intrinsic_optimizations += 1;
I::ExternCall {
dst: None,
iface_name: "env.console".to_string(),
method_name: "log".to_string(),
args: vec![v],
args: vec![value],
effects: crate::mir::EffectMask::PURE,
};
stats.intrinsic_optimizations += 1;
}
}
I::ArrayGet { dst, array, index } if array_to_boxcall => {
let d = *dst;
let a = *array;
let i = *index;
*term = I::BoxCall {
dst: Some(d),
box_val: a,
stats.intrinsic_optimizations += 1;
I::BoxCall {
dst: Some(dst),
box_val: array,
method: "get".to_string(),
method_id: None,
args: vec![i],
args: vec![index],
effects: crate::mir::EffectMask::READ,
};
stats.intrinsic_optimizations += 1;
}
}
I::ArraySet {
array,
index,
value,
} if array_to_boxcall => {
let a = *array;
let i = *index;
let v = *value;
*term = I::BoxCall {
stats.intrinsic_optimizations += 1;
I::BoxCall {
dst: None,
box_val: a,
box_val: array,
method: "set".to_string(),
method_id: None,
args: vec![i, v],
args: vec![index, value],
effects: crate::mir::EffectMask::WRITE,
};
stats.intrinsic_optimizations += 1;
}
}
_ => {}
}
other => other,
};
block.terminator = Some(rewritten);
block.terminator_span = Some(span);
}
let (insts, spans): (Vec<_>, Vec<_>) = new_spanned
.into_iter()
.map(|sp| (sp.inst, sp.span))
.unzip();
block.instructions = insts;
block.instruction_spans = spans;
block.effects = block
.instructions
.iter()
.chain(block.terminator.iter())
.fold(EffectMask::PURE, |mask, inst| mask | inst.effects());
}
if idemp_enabled() {
let key = idemp_key(pass_name, &fname);
@ -555,6 +568,12 @@ pub fn normalize_ref_field_access(
block.terminator_span = Some(term_span);
}
}
block.effects = block
.instructions
.iter()
.chain(block.terminator.iter())
.fold(EffectMask::PURE, |mask, inst| mask | inst.effects());
}
if idemp_enabled() {
let key = idemp_key(pass_name, &fname);