in checker/src/z3_solver.rs [420:488]
fn general_relational(
&self,
left: &Rc<AbstractValue>,
right: &Rc<AbstractValue>,
float_op: unsafe extern "C" fn(
c: z3_sys::Z3_context,
t1: z3_sys::Z3_ast,
t2: z3_sys::Z3_ast,
) -> z3_sys::Z3_ast,
int_op: unsafe extern "C" fn(
c: z3_sys::Z3_context,
t1: z3_sys::Z3_ast,
t2: z3_sys::Z3_ast,
) -> z3_sys::Z3_ast,
signed_bit_op: unsafe extern "C" fn(
c: z3_sys::Z3_context,
t1: z3_sys::Z3_ast,
t2: z3_sys::Z3_ast,
) -> z3_sys::Z3_ast,
unsigned_bit_op: unsafe extern "C" fn(
c: z3_sys::Z3_context,
t1: z3_sys::Z3_ast,
t2: z3_sys::Z3_ast,
) -> z3_sys::Z3_ast,
) -> z3_sys::Z3_ast {
let (signed, num_bits) = if left.expression.is_bit_vector() {
let ty = left.expression.infer_type();
(ty.is_signed_integer(), u32::from(ty.bit_length()))
} else if right.expression.is_bit_vector() {
let ty = right.expression.infer_type();
let mut result = (ty.is_signed_integer(), u32::from(ty.bit_length()));
if let Expression::BitAnd { left, .. } = &right.expression {
if let Expression::CompileTimeConstant(ConstantDomain::U128(v)) = left.expression {
if v < u128::MAX && (v + 1).is_power_of_two() {
result = (false, 0);
}
}
}
result
} else {
(false, 0)
};
if num_bits > 0 {
let left_ast = self.get_as_bv_z3_ast(&(**left).expression, num_bits);
let right_ast = self.get_as_bv_z3_ast(&(**right).expression, num_bits);
unsafe {
if signed {
signed_bit_op(self.z3_context, left_ast, right_ast)
} else {
unsigned_bit_op(self.z3_context, left_ast, right_ast)
}
}
} else {
let (lf, left_ast) = self.get_as_numeric_z3_ast(&(**left).expression);
let (rf, right_ast) = self.get_as_numeric_z3_ast(&(**right).expression);
if lf != rf {
warn!("can't encode {:?} relational op {:?}", left, right);
return self
.general_variable(&Path::get_as_path(left.clone()), ExpressionType::Bool);
}
unsafe {
if lf {
float_op(self.z3_context, left_ast, right_ast)
} else {
int_op(self.z3_context, left_ast, right_ast)
}
}
}
}