let val = self.read_scalar(&args[0])?.check_init()?;
let bits = val.to_bits(layout_of.size)?;
let kind = match layout_of.abi {
- Abi::Scalar(scalar) => scalar.value,
+ Abi::Scalar(scalar) => scalar.primitive(),
_ => span_bug!(
self.cur_span(),
"{} called on invalid type {:?}",
let offset_ptr = ptr.wrapping_signed_offset(offset_bytes, self);
self.write_pointer(offset_ptr, dest)?;
}
- sym::ptr_offset_from => {
+ sym::ptr_offset_from | sym::ptr_offset_from_unsigned => {
let a = self.read_pointer(&args[0])?;
let b = self.read_pointer(&args[1])?;
// exception from the exception.)
// This is the dual to the special exception for offset-by-0
// in the inbounds pointer offset operation (see `ptr_offset_inbounds` below).
- match (self.memory.ptr_try_get_alloc(a), self.memory.ptr_try_get_alloc(b)) {
+ match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) {
(Err(a), Err(b)) if a == b && a != 0 => {
// Both are the same non-null integer.
self.write_scalar(Scalar::from_machine_isize(0, self), dest)?;
// Both are pointers. They must be into the same allocation.
if a_alloc_id != b_alloc_id {
throw_ub_format!(
- "ptr_offset_from cannot compute offset of pointers into different \
- allocations.",
+ "{} cannot compute offset of pointers into different allocations.",
+ intrinsic_name,
);
}
// And they must both be valid for zero-sized accesses ("in-bounds or one past the end").
- self.memory.check_ptr_access_align(
+ self.check_ptr_access_align(
a,
Size::ZERO,
Align::ONE,
CheckInAllocMsg::OffsetFromTest,
)?;
- self.memory.check_ptr_access_align(
+ self.check_ptr_access_align(
b,
Size::ZERO,
Align::ONE,
CheckInAllocMsg::OffsetFromTest,
)?;
+ if intrinsic_name == sym::ptr_offset_from_unsigned && a_offset < b_offset {
+ throw_ub_format!(
+ "{} cannot compute a negative offset, but {} < {}",
+ intrinsic_name,
+ a_offset.bytes(),
+ b_offset.bytes(),
+ );
+ }
+
// Compute offset.
let usize_layout = self.layout_of(self.tcx.types.usize)?;
let isize_layout = self.layout_of(self.tcx.types.isize)?;
- let a_offset = ImmTy::from_uint(a_offset.bytes(), usize_layout);
- let b_offset = ImmTy::from_uint(b_offset.bytes(), usize_layout);
- let (val, _overflowed, _ty) =
+ let ret_layout = if intrinsic_name == sym::ptr_offset_from {
+ isize_layout
+ } else {
+ usize_layout
+ };
+
+ // The subtraction is always done in `isize` to enforce
+ // the "no more than `isize::MAX` apart" requirement.
+ let a_offset = ImmTy::from_uint(a_offset.bytes(), isize_layout);
+ let b_offset = ImmTy::from_uint(b_offset.bytes(), isize_layout);
+ let (val, overflowed, _ty) =
self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
+ if overflowed {
+ throw_ub_format!("Pointers were too far apart for {}", intrinsic_name);
+ }
+
let pointee_layout = self.layout_of(substs.type_at(0))?;
- let val = ImmTy::from_scalar(val, isize_layout);
- let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
+ // This re-interprets an isize at ret_layout, but we already checked
+ // that if ret_layout is usize, then the result must be non-negative.
+ let val = ImmTy::from_scalar(val, ret_layout);
+ let size = ImmTy::from_int(pointee_layout.size.bytes(), ret_layout);
self.exact_div(&val, &size, dest)?;
}
}
let min_ptr = if offset_bytes >= 0 { ptr } else { offset_ptr };
let size = offset_bytes.unsigned_abs();
// This call handles checking for integer/null pointers.
- self.memory.check_ptr_access_align(
+ self.check_ptr_access_align(
min_ptr,
Size::from_bytes(size),
Align::ONE,
let src = self.read_pointer(&src)?;
let dst = self.read_pointer(&dst)?;
- self.memory.copy(src, align, dst, align, size, nonoverlapping)
+ self.mem_copy(src, align, dst, align, size, nonoverlapping)
}
pub(crate) fn write_bytes_intrinsic(
.ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?;
let bytes = std::iter::repeat(byte).take(len.bytes_usize());
- self.memory.write_bytes(dst, bytes)
+ self.write_bytes_ptr(dst, bytes)
}
pub(crate) fn raw_eq_intrinsic(
let lhs = self.read_pointer(lhs)?;
let rhs = self.read_pointer(rhs)?;
- let lhs_bytes = self.memory.read_bytes(lhs, layout.size)?;
- let rhs_bytes = self.memory.read_bytes(rhs, layout.size)?;
+ let lhs_bytes = self.read_bytes_ptr(lhs, layout.size)?;
+ let rhs_bytes = self.read_bytes_ptr(rhs, layout.size)?;
Ok(Scalar::from_bool(lhs_bytes == rhs_bytes))
}
}