Normalize passes keep spans and clean warnings
This commit is contained in:
@ -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);
|
||||
|
||||
Reference in New Issue
Block a user