feat: add as type casting
This commit is contained in:
@@ -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::*;
|
||||
|
||||
Reference in New Issue
Block a user