feat: add as type casting

This commit is contained in:
2026-04-22 22:40:19 +02:00
parent e66a4ee736
commit 041a49e574
13 changed files with 350 additions and 1 deletions
+59
View File
@@ -75,6 +75,7 @@ fn propagate_rvalue(rvalue: &mut Rvalue, known_constants: &HashMap<LocalId, Cons
propagate_operand(lhs, known_constants);
propagate_operand(rhs, known_constants);
}
Rvalue::Cast(_, op) => propagate_operand(op, known_constants),
}
}
@@ -85,6 +86,7 @@ fn evaluate_rvalue(rvalue: &Rvalue) -> Option<ConstantValue> {
Rvalue::BinaryOp(op, Operand::Constant(l), Operand::Constant(r)) => {
evaluate_binary(*op, l, r)
}
Rvalue::Cast(to_ty, Operand::Constant(c)) => evaluate_cast(to_ty, c),
_ => None,
}
}
@@ -184,6 +186,63 @@ fn evaluate_binary(
}
}
fn evaluate_cast(to_ty: &Ty, val: &ConstantValue) -> Option<ConstantValue> {
if to_ty.is_float() {
let f = match val {
ConstantValue::Integer(v, ty) => {
if ty.is_signed() {
let shift = 64 - ty.bit_width();
(((*v as i64) << shift) >> shift) as f64
} else {
*v as f64
}
}
ConstantValue::Float(v, _) => *v,
ConstantValue::Boolean(b) => {
if *b {
1.0
} else {
0.0
}
}
};
Some(ConstantValue::Float(f, to_ty.clone()))
} else if to_ty.is_integer() {
let i = match val {
ConstantValue::Integer(v, _) => *v,
ConstantValue::Float(v, _) => {
if to_ty.is_signed() {
(*v as i64) as u64
} else {
*v as u64
}
}
ConstantValue::Boolean(b) => {
if *b {
1
} else {
0
}
}
};
let mask = if to_ty.bit_width() == 64 {
u64::MAX
} else {
(1u64 << to_ty.bit_width()) - 1
};
Some(ConstantValue::Integer(i & mask, to_ty.clone()))
} else if to_ty == &Ty::Bool {
let b = match val {
ConstantValue::Integer(v, _) => *v != 0,
ConstantValue::Float(v, _) => *v != 0.0,
ConstantValue::Boolean(b) => *b,
};
Some(ConstantValue::Boolean(b))
} else {
None
}
}
#[cfg(test)]
mod test {
use super::*;