use super::Lower;
use rt::lir::{Expr, ExprId, IntExpr, Operand, PlaceId, PlaceNumcheck, SenderCheck};
use syntax::Pos;
impl Lower<'_> {
pub(super) fn move_check(&self, from: Operand, to: PlaceId) -> SenderCheck {
match from {
Operand::Load(p) => rt::store::move_check(&self.c.options, self.kind_of(p), self.kind_of(to)),
_ => SenderCheck::None,
}
}
pub(super) fn place_numcheck(&self, item: usize, pos: Pos) -> PlaceNumcheck {
let lax = self.c.options.numcheck.and_then(|c| c.zon).is_some_and(|z| z.lax);
PlaceNumcheck { lax: self.layout.numcheck.lax(item).filter(|_| lax), removed: self.layout.numcheck.removed(item, pos) }
}
pub(super) fn int_tested(&self, e: &IntExpr) -> bool {
match e {
IntExpr::Const(_) | IntExpr::Walk(_) => false,
IntExpr::Item(p) => self.read_tested(*p),
IntExpr::Fixed { expr, prepass, .. } => prepass.iter().any(|&q| self.locate_tested(q)) || self.expr_tested(*expr),
}
}
pub(super) fn read_tested(&self, p: PlaceId) -> bool {
rt::store::numcheck_tests(&self.c.options, self.kind_of(p), false) || self.locate_tested(p)
}
fn locate_tested(&self, p: PlaceId) -> bool {
let place = &self.places[p as usize];
place.moved.iter().chain(&place.odo).any(|o| self.int_tested(&o.object))
|| place.subscripts.iter().any(|s| self.int_tested(&s.value))
|| place.refmod.as_ref().is_some_and(|r| self.int_tested(&r.start) || r.length.as_ref().is_some_and(|l| self.int_tested(l)))
}
fn expr_tested(&self, e: ExprId) -> bool {
match &self.exprs[e as usize] {
Expr::Operand(Operand::Load(p)) => self.read_tested(*p),
Expr::Operand(Operand::LengthOf(p) | Operand::AddressOf(p)) => self.locate_tested(*p),
Expr::Operand(Operand::Const(_)) => false,
Expr::Operand(Operand::Function(_) | Operand::UserFunction(_)) => self.c.options.numcheck.is_some(),
Expr::Neg(a) => self.expr_tested(*a),
Expr::Bin(a, _, b) => self.expr_tested(*a) || self.expr_tested(*b),
Expr::Pow(a, n) => self.expr_tested(*a) || self.int_tested(n),
}
}
}