Skip to content

Commit

Permalink
share BinOp::Offset between CTFE and Miri
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Apr 28, 2023
1 parent 8b8110e commit 586d17d
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 25 deletions.
17 changes: 4 additions & 13 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,20 +559,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}

fn binary_ptr_op(
ecx: &InterpCx<'mir, 'tcx, Self>,
bin_op: mir::BinOp,
left: &ImmTy<'tcx>,
right: &ImmTy<'tcx>,
_ecx: &InterpCx<'mir, 'tcx, Self>,
_bin_op: mir::BinOp,
_left: &ImmTy<'tcx>,
_right: &ImmTy<'tcx>,
) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
if bin_op == mir::BinOp::Offset {
let ptr = left.to_scalar().to_pointer(ecx)?;
let offset_count = right.to_scalar().to_target_isize(ecx)?;
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;

let offset_ptr = ecx.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
return Ok((Scalar::from_maybe_pointer(offset_ptr, ecx), false, left.layout.ty));
}

throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
}

Expand Down
26 changes: 25 additions & 1 deletion compiler/rustc_const_eval/src/interpret/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok((val, false, ty))
}

fn binary_ptr_op(
&self,
bin_op: mir::BinOp,
left: &ImmTy<'tcx, M::Provenance>,
right: &ImmTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, (Scalar<M::Provenance>, bool, Ty<'tcx>)> {
use rustc_middle::mir::BinOp::*;

match bin_op {
// Pointer ops that are always supported.
Offset => {
let ptr = left.to_scalar().to_pointer(self)?;
let offset_count = right.to_scalar().to_target_isize(self)?;
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;

let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
Ok((Scalar::from_maybe_pointer(offset_ptr, self), false, left.layout.ty))
}

// Fall back to machine hook so Miri can support more pointer ops.
_ => M::binary_ptr_op(self, bin_op, left, right),
}
}

/// Returns the result of the specified operation, whether it overflowed, and
/// the result type.
pub fn overflowing_binary_op(
Expand Down Expand Up @@ -368,7 +392,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
right.layout.ty
);

M::binary_ptr_op(self, bin_op, left, right)
self.binary_ptr_op(bin_op, left, right)
}
_ => span_bug!(
self.cur_span(),
Expand Down
11 changes: 0 additions & 11 deletions src/tools/miri/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,6 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriInterpCx<'mir, 'tcx> {
(Scalar::from_bool(res), false, self.tcx.types.bool)
}

Offset => {
assert!(left.layout.ty.is_unsafe_ptr());
let ptr = left.to_scalar().to_pointer(self)?;
let offset = right.to_scalar().to_target_isize(self)?;

let pointee_ty =
left.layout.ty.builtin_deref(true).expect("Offset called on non-ptr type").ty;
let ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset)?;
(Scalar::from_maybe_pointer(ptr, self), false, left.layout.ty)
}

// Some more operations are possible with atomics.
// The return value always has the provenance of the *left* operand.
Add | Sub | BitOr | BitAnd | BitXor => {
Expand Down

0 comments on commit 586d17d

Please sign in to comment.