Skip to content

Commit

Permalink
pass clippy::integer_arithmetic in our shims
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Aug 22, 2022
1 parent ab88e64 commit 8497fd4
Show file tree
Hide file tree
Showing 10 changed files with 42 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
clippy::too_many_arguments,
clippy::type_complexity,
clippy::single_element_loop,
clippy::needless_return,
// We are not implementing queries here so it's fine
rustc::potential_query_instability
)]
Expand Down
2 changes: 1 addition & 1 deletion src/shims/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// file would have more than 2^32 lines or columns, but whatever, just default to 0.
let lineno: u32 = u32::try_from(lo.line).unwrap_or(0);
// `lo.col` is 0-based - add 1 to make it 1-based for the caller.
let colno: u32 = u32::try_from(lo.col.0 + 1).unwrap_or(0);
let colno: u32 = u32::try_from(lo.col.0.saturating_add(1)).unwrap_or(0);

let dest = this.force_allocation(dest)?;
if let ty::Adt(adt, _) = dest.layout.ty.kind() {
Expand Down
9 changes: 8 additions & 1 deletion src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
.expect("interpreting a non-executable crate");
for cnum in iter::once(LOCAL_CRATE).chain(
dependency_format.1.iter().enumerate().filter_map(|(num, &linkage)| {
// We add 1 to the number because that's what rustc also does everywhere it
// calls `CrateNum::new`...
#[allow(clippy::integer_arithmetic)]
(linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1))
}),
) {
Expand Down Expand Up @@ -542,7 +545,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
.rev()
.position(|&c| c == val)
{
let new_ptr = ptr.offset(Size::from_bytes(num - idx as u64 - 1), this)?;
let idx = u64::try_from(idx).unwrap();
#[allow(clippy::integer_arithmetic)] // idx < num, so this never wraps
let new_ptr = ptr.offset(Size::from_bytes(num - idx - 1), this)?;
this.write_pointer(new_ptr, dest)?;
} else {
this.write_null(dest)?;
Expand Down Expand Up @@ -708,7 +713,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let a = this.read_scalar(a)?.to_u64()?;
let b = this.read_scalar(b)?.to_u64()?;

#[allow(clippy::integer_arithmetic)] // adding two u64 and a u8 cannot wrap in a u128
let wide_sum = u128::from(c_in) + u128::from(a) + u128::from(b);
#[allow(clippy::integer_arithmetic)] // it's a u128, we can shift by 64
let (c_out, sum) = ((wide_sum >> 64).truncate::<u8>(), wide_sum.truncate::<u64>());

let c_out_field = this.place_field(dest, 0)?;
Expand Down
31 changes: 19 additions & 12 deletions src/shims/intrinsics/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
assert_eq!(bitmask_len, mask.layout.size.bits());
assert_eq!(dest_len, yes_len);
assert_eq!(dest_len, no_len);
let dest_len = u32::try_from(dest_len).unwrap();
let bitmask_len = u32::try_from(bitmask_len).unwrap();

let mask: u64 = this
.read_scalar(mask)?
Expand All @@ -401,18 +403,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
.try_into()
.unwrap();
for i in 0..dest_len {
let mask =
mask & (1 << simd_bitmask_index(i, dest_len, this.data_layout().endian));
let yes = this.read_immediate(&this.mplace_index(&yes, i)?.into())?;
let no = this.read_immediate(&this.mplace_index(&no, i)?.into())?;
let dest = this.mplace_index(&dest, i)?;
let mask = mask
& 1u64
.checked_shl(simd_bitmask_index(i, dest_len, this.data_layout().endian))
.unwrap();
let yes = this.read_immediate(&this.mplace_index(&yes, i.into())?.into())?;
let no = this.read_immediate(&this.mplace_index(&no, i.into())?.into())?;
let dest = this.mplace_index(&dest, i.into())?;

let val = if mask != 0 { yes } else { no };
this.write_immediate(*val, &dest.into())?;
}
for i in dest_len..bitmask_len {
// If the mask is "padded", ensure that padding is all-zero.
let mask = mask & (1 << i);
let mask = mask & 1u64.checked_shl(i).unwrap();
if mask != 0 {
throw_ub_format!(
"a SIMD bitmask less than 8 bits long must be filled with 0s for the remaining bits"
Expand Down Expand Up @@ -485,9 +489,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let val = if src_index < left_len {
this.read_immediate(&this.mplace_index(&left, src_index)?.into())?
} else if src_index < left_len.checked_add(right_len).unwrap() {
this.read_immediate(
&this.mplace_index(&right, src_index - left_len)?.into(),
)?
let right_idx = src_index.checked_sub(left_len).unwrap();
this.read_immediate(&this.mplace_index(&right, right_idx)?.into())?
} else {
span_bug!(
this.cur_span(),
Expand Down Expand Up @@ -551,12 +554,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
assert!(dest.layout.ty.is_integral());
assert!(bitmask_len <= 64);
assert_eq!(bitmask_len, dest.layout.size.bits());
let op_len = u32::try_from(op_len).unwrap();

let mut res = 0u64;
for i in 0..op_len {
let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
let op = this.read_immediate(&this.mplace_index(&op, i.into())?.into())?;
if simd_element_to_bool(op)? {
res |= 1 << simd_bitmask_index(i, op_len, this.data_layout().endian);
res |= 1u64
.checked_shl(simd_bitmask_index(i, op_len, this.data_layout().endian))
.unwrap();
}
}
this.write_int(res, dest)?;
Expand All @@ -583,10 +589,11 @@ fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult<'_, bool> {
})
}

fn simd_bitmask_index(idx: u64, vec_len: u64, endianess: Endian) -> u64 {
fn simd_bitmask_index(idx: u32, vec_len: u32, endianess: Endian) -> u32 {
assert!(idx < vec_len);
match endianess {
Endian::Little => idx,
#[allow(clippy::integer_arithmetic)] // idx < vec_len
Endian::Big => vec_len - 1 - idx, // reverse order of bits
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/shims/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![warn(clippy::integer_arithmetic)]

mod backtrace;
pub mod foreign_items;
pub mod intrinsics;
Expand Down
2 changes: 1 addition & 1 deletion src/shims/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
Ok(0)
}

#[allow(non_snake_case)]
#[allow(non_snake_case, clippy::integer_arithmetic)]
fn GetSystemTimeAsFileTime(
&mut self,
LPFILETIME_op: &OpTy<'tcx, Provenance>,
Expand Down
1 change: 1 addition & 0 deletions src/shims/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ impl<'tcx> Default for TlsData<'tcx> {
impl<'tcx> TlsData<'tcx> {
/// Generate a new TLS key with the given destructor.
/// `max_size` determines the integer size the key has to fit in.
#[allow(clippy::integer_arithmetic)]
pub fn create_tls_key(
&mut self,
dtor: Option<ty::Instance<'tcx>>,
Expand Down
1 change: 1 addition & 0 deletions src/shims/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ pub struct DirHandler {
}

impl DirHandler {
#[allow(clippy::integer_arithmetic)]
fn insert_new(&mut self, read_dir: ReadDir) -> u64 {
let id = self.next_id;
self.next_id += 1;
Expand Down
1 change: 1 addition & 0 deletions src/shims/unix/linux/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ pub fn futex<'tcx>(
// before doing the syscall.
this.atomic_fence(AtomicFenceOrd::SeqCst)?;
let mut n = 0;
#[allow(clippy::integer_arithmetic)]
for _ in 0..val {
if let Some(thread) = this.futex_wake(addr_usize, bitset) {
this.unblock_thread(thread);
Expand Down
10 changes: 7 additions & 3 deletions src/shims/windows/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl Handle {
let floor_log2 = variant_count.ilog2();

// we need to add one for non powers of two to compensate for the difference
#[allow(clippy::integer_arithmetic)] // cannot overflow
if variant_count.is_power_of_two() { floor_log2 } else { floor_log2 + 1 }
}

Expand All @@ -73,7 +74,7 @@ impl Handle {
/// None of this layout is guaranteed to applications by Windows or Miri.
fn to_packed(self) -> u32 {
let disc_size = Self::packed_disc_size();
let data_size = u32::BITS - disc_size;
let data_size = u32::BITS.checked_sub(disc_size).unwrap();

let discriminant = self.discriminant();
let data = self.data();
Expand All @@ -86,7 +87,8 @@ impl Handle {

// packs the data into the lower `data_size` bits
// and packs the discriminant right above the data
discriminant << data_size | data
#[allow(clippy::integer_arithmetic)] // cannot overflow
return discriminant << data_size | data;
}

fn new(discriminant: u32, data: u32) -> Option<Self> {
Expand All @@ -101,12 +103,14 @@ impl Handle {
/// see docs for `to_packed`
fn from_packed(handle: u32) -> Option<Self> {
let disc_size = Self::packed_disc_size();
let data_size = u32::BITS - disc_size;
let data_size = u32::BITS.checked_sub(disc_size).unwrap();

// the lower `data_size` bits of this mask are 1
#[allow(clippy::integer_arithmetic)] // cannot overflow
let data_mask = 2u32.pow(data_size) - 1;

// the discriminant is stored right above the lower `data_size` bits
#[allow(clippy::integer_arithmetic)] // cannot overflow
let discriminant = handle >> data_size;

// the data is stored in the lower `data_size` bits
Expand Down

0 comments on commit 8497fd4

Please sign in to comment.