mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
interpret: make numeric_intrinsic accessible from Miri
This commit is contained in:
parent
71940e0a8a
commit
edabd477f8
@ -3,17 +3,22 @@
|
||||
//! and miri.
|
||||
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::mir::{
|
||||
self,
|
||||
interpret::{Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar},
|
||||
BinOp, ConstValue, NonDivergingIntrinsic,
|
||||
};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
use rustc_middle::{
|
||||
mir::{
|
||||
self,
|
||||
interpret::{
|
||||
Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar,
|
||||
},
|
||||
BinOp, ConstValue, NonDivergingIntrinsic,
|
||||
},
|
||||
ty::layout::TyAndLayout,
|
||||
};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_target::abi::{Abi, Primitive, Size};
|
||||
use rustc_target::abi::Size;
|
||||
|
||||
use super::{
|
||||
util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
|
||||
@ -22,23 +27,6 @@ use super::{
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<Prov> {
|
||||
let size = match kind {
|
||||
Primitive::Int(integer, _) => integer.size(),
|
||||
_ => bug!("invalid `{}` argument: {:?}", name, bits),
|
||||
};
|
||||
let extra = 128 - u128::from(size.bits());
|
||||
let bits_out = match name {
|
||||
sym::ctpop => u128::from(bits.count_ones()),
|
||||
sym::ctlz => u128::from(bits.leading_zeros()) - extra,
|
||||
sym::cttz => u128::from((bits << extra).trailing_zeros()) - extra,
|
||||
sym::bswap => (bits << extra).swap_bytes(),
|
||||
sym::bitreverse => (bits << extra).reverse_bits(),
|
||||
_ => bug!("not a numeric intrinsic: {}", name),
|
||||
};
|
||||
Scalar::from_uint(bits_out, size)
|
||||
}
|
||||
|
||||
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
|
||||
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
|
||||
let path = crate::util::type_name(tcx, ty);
|
||||
@ -179,30 +167,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
| sym::bswap
|
||||
| sym::bitreverse => {
|
||||
let ty = instance_args.type_at(0);
|
||||
let layout_of = self.layout_of(ty)?;
|
||||
let layout = self.layout_of(ty)?;
|
||||
let val = self.read_scalar(&args[0])?;
|
||||
let bits = val.to_bits(layout_of.size)?;
|
||||
let kind = match layout_of.abi {
|
||||
Abi::Scalar(scalar) => scalar.primitive(),
|
||||
_ => span_bug!(
|
||||
self.cur_span(),
|
||||
"{} called on invalid type {:?}",
|
||||
intrinsic_name,
|
||||
ty
|
||||
),
|
||||
};
|
||||
let (nonzero, actual_intrinsic_name) = match intrinsic_name {
|
||||
sym::cttz_nonzero => (true, sym::cttz),
|
||||
sym::ctlz_nonzero => (true, sym::ctlz),
|
||||
other => (false, other),
|
||||
};
|
||||
if nonzero && bits == 0 {
|
||||
throw_ub_custom!(
|
||||
fluent::const_eval_call_nonzero_intrinsic,
|
||||
name = intrinsic_name,
|
||||
);
|
||||
}
|
||||
let out_val = numeric_intrinsic(actual_intrinsic_name, bits, kind);
|
||||
let out_val = self.numeric_intrinsic(intrinsic_name, val, layout)?;
|
||||
self.write_scalar(out_val, dest)?;
|
||||
}
|
||||
sym::saturating_add | sym::saturating_sub => {
|
||||
@ -493,6 +460,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn numeric_intrinsic(
|
||||
&self,
|
||||
name: Symbol,
|
||||
val: Scalar<M::Provenance>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
|
||||
assert!(layout.ty.is_integral(), "invalid type for numeric intrinsic: {}", layout.ty);
|
||||
let bits = val.to_bits(layout.size)?;
|
||||
let extra = 128 - u128::from(layout.size.bits());
|
||||
let bits_out = match name {
|
||||
sym::ctpop => u128::from(bits.count_ones()),
|
||||
sym::ctlz_nonzero | sym::cttz_nonzero if bits == 0 => {
|
||||
throw_ub_custom!(fluent::const_eval_call_nonzero_intrinsic, name = name,);
|
||||
}
|
||||
sym::ctlz | sym::ctlz_nonzero => u128::from(bits.leading_zeros()) - extra,
|
||||
sym::cttz | sym::cttz_nonzero => u128::from((bits << extra).trailing_zeros()) - extra,
|
||||
sym::bswap => (bits << extra).swap_bytes(),
|
||||
sym::bitreverse => (bits << extra).reverse_bits(),
|
||||
_ => bug!("not a numeric intrinsic: {}", name),
|
||||
};
|
||||
Ok(Scalar::from_uint(bits_out, layout.size))
|
||||
}
|
||||
|
||||
pub fn exact_div(
|
||||
&mut self,
|
||||
a: &ImmTy<'tcx, M::Provenance>,
|
||||
|
Loading…
Reference in New Issue
Block a user