fix int ptr ops on 32bit
This commit is contained in:
parent
98a5b24ef7
commit
1179d4f8a4
@ -20,7 +20,7 @@ pub trait EvalContextExt<'tcx> {
|
||||
&self,
|
||||
bin_op: mir::BinOp,
|
||||
left: Pointer,
|
||||
right: i128,
|
||||
right: u128,
|
||||
signed: bool,
|
||||
) -> EvalResult<'tcx, (Scalar, bool)>;
|
||||
}
|
||||
@ -138,7 +138,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
|
||||
self.ptr_int_arithmetic(
|
||||
bin_op,
|
||||
left.to_ptr()?,
|
||||
right.to_bits(self.memory.pointer_size())? as i128,
|
||||
right.to_bits(self.memory.pointer_size())?,
|
||||
left_kind == isize,
|
||||
).map(Some)
|
||||
}
|
||||
@ -150,7 +150,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
|
||||
self.ptr_int_arithmetic(
|
||||
bin_op,
|
||||
right.to_ptr()?,
|
||||
left.to_bits(self.memory.pointer_size())? as i128,
|
||||
left.to_bits(self.memory.pointer_size())?,
|
||||
left_kind == isize,
|
||||
).map(Some)
|
||||
}
|
||||
@ -162,7 +162,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
|
||||
&self,
|
||||
bin_op: mir::BinOp,
|
||||
left: Pointer,
|
||||
right: i128,
|
||||
right: u128,
|
||||
signed: bool,
|
||||
) -> EvalResult<'tcx, (Scalar, bool)> {
|
||||
use rustc::mir::BinOp::*;
|
||||
@ -174,23 +174,31 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
|
||||
Ok(match bin_op {
|
||||
Sub =>
|
||||
// The only way this can overflow is by underflowing, so signdeness of the right operands does not matter
|
||||
map_to_primval(left.overflowing_signed_offset(-right, self)),
|
||||
map_to_primval(left.overflowing_signed_offset(-(right as i128), self)),
|
||||
Add if signed =>
|
||||
map_to_primval(left.overflowing_signed_offset(right, self)),
|
||||
map_to_primval(left.overflowing_signed_offset(right as i128, self)),
|
||||
Add if !signed =>
|
||||
map_to_primval(left.overflowing_offset(Size::from_bytes(right as u64), self)),
|
||||
|
||||
BitAnd if !signed => {
|
||||
let ptr_base_align = self.memory.get(left.alloc_id)?.align.abi();
|
||||
let base_mask : u64 = !(ptr_base_align - 1);
|
||||
let right = right as u64;
|
||||
let base_mask = {
|
||||
// FIXME: Use interpret::truncate, once that takes a Size instead of a Layout
|
||||
let shift = 128 - self.memory.pointer_size().bits();
|
||||
let value = !(ptr_base_align as u128 - 1);
|
||||
// truncate (shift left to drop out leftover values, shift right to fill with zeroes)
|
||||
(value << shift) >> shift
|
||||
};
|
||||
let ptr_size = self.memory.pointer_size().bytes() as u8;
|
||||
trace!("Ptr BitAnd, align {}, operand {:#010x}, base_mask {:#010x}",
|
||||
ptr_base_align, right, base_mask);
|
||||
if right & base_mask == base_mask {
|
||||
// Case 1: The base address bits are all preserved, i.e., right is all-1 there
|
||||
(Scalar::Ptr(Pointer::new(left.alloc_id, Size::from_bytes(left.offset.bytes() & right))), false)
|
||||
let offset = (left.offset.bytes() as u128 & right) as u64;
|
||||
(Scalar::Ptr(Pointer::new(left.alloc_id, Size::from_bytes(offset))), false)
|
||||
} else if right & base_mask == 0 {
|
||||
// Case 2: The base address bits are all taken away, i.e., right is all-0 there
|
||||
(Scalar::Bits { bits: (left.offset.bytes() & right) as u128, size: ptr_size }, false)
|
||||
(Scalar::Bits { bits: (left.offset.bytes() as u128) & right, size: ptr_size }, false)
|
||||
} else {
|
||||
return err!(ReadPointerAsBytes);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user