From edabd477f86c48929f12b4c2f5a15d58cde120a5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 3 Dec 2023 11:51:58 +0100 Subject: [PATCH] interpret: make numeric_intrinsic accessible from Miri --- .../src/interpret/intrinsics.rs | 82 ++++++++----------- 1 file changed, 36 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 80e14f5a884..c29f23b913f 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -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(name: Symbol, bits: u128, kind: Primitive) -> Scalar { - 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, + layout: TyAndLayout<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + 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>,