#![allow(clippy::unnecessary_wraps)]
use wasmparser::{Ieee32, Ieee64, ValType};
use super::Translator;
use crate::module::op::{Op, Slot};
use crate::{Error, Result};
impl Translator<'_> {
pub(in crate::module::compile) fn visit_i32_const(&mut self, value: i32) -> Result<()> {
if self.reachable {
self.fresh(|s| Op::I32Const(s, value));
self.pending_const = self.stack.last().map(|&dst| (dst, value));
}
Ok(())
}
pub(in crate::module::compile) fn visit_i64_const(&mut self, value: i64) -> Result<()> {
if self.reachable {
self.fresh(|s| Op::I64Const(s, value));
}
Ok(())
}
pub(in crate::module::compile) fn visit_f32_const(&mut self, value: Ieee32) -> Result<()> {
if self.reachable {
self.fresh(|s| Op::F32Const(s, value.bits()));
}
Ok(())
}
pub(in crate::module::compile) fn visit_f64_const(&mut self, value: Ieee64) -> Result<()> {
if self.reachable {
self.fresh(|s| Op::F64Const(s, value.bits()));
}
Ok(())
}
pub(in crate::module::compile) fn visit_drop(&mut self) -> Result<()> {
if self.reachable {
self.pop(1);
self.clear_fusion();
}
Ok(())
}
fn lower_select(&mut self) {
let s = self.slot_below(3);
self.pop(3);
self.push(1);
self.emit(Op::Select(s));
}
pub(in crate::module::compile) fn visit_select(&mut self) -> Result<()> {
if self.reachable {
self.lower_select();
}
Ok(())
}
pub(in crate::module::compile) fn visit_typed_select(&mut self, _ty: ValType) -> Result<()> {
if self.reachable {
self.lower_select();
}
Ok(())
}
pub(in crate::module::compile) fn visit_typed_select_multi(
&mut self,
tys: Vec<ValType>,
) -> Result<()> {
let _ = tys;
Err(Error::msg("unsupported operator: typed_select_multi"))
}
pub(in crate::module::compile) fn visit_local_get(&mut self, local_index: u32) -> Result<()> {
if self.reachable {
self.push_local(local_index);
}
Ok(())
}
pub(in crate::module::compile) fn visit_local_set(&mut self, local_index: u32) -> Result<()> {
if self.reachable {
let src = self.operand(0);
self.pop(1);
if !self.retarget(local_index, src) {
self.write_local(local_index, src);
}
}
Ok(())
}
pub(in crate::module::compile) fn visit_local_tee(&mut self, local_index: u32) -> Result<()> {
if self.reachable {
let src = self.operand(0);
if self.retarget(local_index, src) {
self.pop(1); self.push_local(local_index);
} else {
self.write_local(local_index, src);
}
}
Ok(())
}
fn retarget(&mut self, local: u32, src: Slot) -> bool {
let Some((ip, _)) = self.fusable_dst.filter(|&(_, dst)| dst == src) else {
return false;
};
if self.reads_local(local) {
return false;
}
let Some(dst) = self.op_get_mut(ip).and_then(Op::dst_mut) else {
return false;
};
*dst = local;
self.clear_fusion();
true
}
fn write_local(&mut self, local: u32, src: Slot) {
if src != local {
self.preserve(local);
self.emit(Op::Copy(local, src));
}
}
pub(in crate::module::compile) fn visit_global_get(&mut self, global_index: u32) -> Result<()> {
if self.reachable {
self.fresh(|s| Op::GlobalGet(s, global_index));
}
Ok(())
}
pub(in crate::module::compile) fn visit_global_set(&mut self, global_index: u32) -> Result<()> {
if self.reachable {
self.sink(|s| Op::GlobalSet(s, global_index));
}
Ok(())
}
}