Skip to content

Commit 4128809

Browse files
Rollup merge of #118565 - RalfJung:numeric_intrinsic, r=davidtwco
interpret: make numeric_intrinsic accessible from Miri This will let us share the code of the cttz and simd_cttz intrinsics (and same for ctlz).
2 parents 963e8e8 + edabd47 commit 4128809

File tree

1 file changed

+36
-46
lines changed

1 file changed

+36
-46
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+36-46
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,22 @@
33
//! and miri.
44
55
use rustc_hir::def_id::DefId;
6-
use rustc_middle::mir::{
7-
self,
8-
interpret::{Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar},
9-
BinOp, ConstValue, NonDivergingIntrinsic,
10-
};
116
use rustc_middle::ty;
127
use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
138
use rustc_middle::ty::GenericArgsRef;
149
use rustc_middle::ty::{Ty, TyCtxt};
10+
use rustc_middle::{
11+
mir::{
12+
self,
13+
interpret::{
14+
Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar,
15+
},
16+
BinOp, ConstValue, NonDivergingIntrinsic,
17+
},
18+
ty::layout::TyAndLayout,
19+
};
1520
use rustc_span::symbol::{sym, Symbol};
16-
use rustc_target::abi::{Abi, Primitive, Size};
21+
use rustc_target::abi::Size;
1722

1823
use super::{
1924
util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
@@ -22,23 +27,6 @@ use super::{
2227

2328
use crate::fluent_generated as fluent;
2429

25-
fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<Prov> {
26-
let size = match kind {
27-
Primitive::Int(integer, _) => integer.size(),
28-
_ => bug!("invalid `{}` argument: {:?}", name, bits),
29-
};
30-
let extra = 128 - u128::from(size.bits());
31-
let bits_out = match name {
32-
sym::ctpop => u128::from(bits.count_ones()),
33-
sym::ctlz => u128::from(bits.leading_zeros()) - extra,
34-
sym::cttz => u128::from((bits << extra).trailing_zeros()) - extra,
35-
sym::bswap => (bits << extra).swap_bytes(),
36-
sym::bitreverse => (bits << extra).reverse_bits(),
37-
_ => bug!("not a numeric intrinsic: {}", name),
38-
};
39-
Scalar::from_uint(bits_out, size)
40-
}
41-
4230
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
4331
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
4432
let path = crate::util::type_name(tcx, ty);
@@ -179,30 +167,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
179167
| sym::bswap
180168
| sym::bitreverse => {
181169
let ty = instance_args.type_at(0);
182-
let layout_of = self.layout_of(ty)?;
170+
let layout = self.layout_of(ty)?;
183171
let val = self.read_scalar(&args[0])?;
184-
let bits = val.to_bits(layout_of.size)?;
185-
let kind = match layout_of.abi {
186-
Abi::Scalar(scalar) => scalar.primitive(),
187-
_ => span_bug!(
188-
self.cur_span(),
189-
"{} called on invalid type {:?}",
190-
intrinsic_name,
191-
ty
192-
),
193-
};
194-
let (nonzero, actual_intrinsic_name) = match intrinsic_name {
195-
sym::cttz_nonzero => (true, sym::cttz),
196-
sym::ctlz_nonzero => (true, sym::ctlz),
197-
other => (false, other),
198-
};
199-
if nonzero && bits == 0 {
200-
throw_ub_custom!(
201-
fluent::const_eval_call_nonzero_intrinsic,
202-
name = intrinsic_name,
203-
);
204-
}
205-
let out_val = numeric_intrinsic(actual_intrinsic_name, bits, kind);
172+
let out_val = self.numeric_intrinsic(intrinsic_name, val, layout)?;
206173
self.write_scalar(out_val, dest)?;
207174
}
208175
sym::saturating_add | sym::saturating_sub => {
@@ -493,6 +460,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
493460
}
494461
}
495462

463+
pub fn numeric_intrinsic(
464+
&self,
465+
name: Symbol,
466+
val: Scalar<M::Provenance>,
467+
layout: TyAndLayout<'tcx>,
468+
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
469+
assert!(layout.ty.is_integral(), "invalid type for numeric intrinsic: {}", layout.ty);
470+
let bits = val.to_bits(layout.size)?;
471+
let extra = 128 - u128::from(layout.size.bits());
472+
let bits_out = match name {
473+
sym::ctpop => u128::from(bits.count_ones()),
474+
sym::ctlz_nonzero | sym::cttz_nonzero if bits == 0 => {
475+
throw_ub_custom!(fluent::const_eval_call_nonzero_intrinsic, name = name,);
476+
}
477+
sym::ctlz | sym::ctlz_nonzero => u128::from(bits.leading_zeros()) - extra,
478+
sym::cttz | sym::cttz_nonzero => u128::from((bits << extra).trailing_zeros()) - extra,
479+
sym::bswap => (bits << extra).swap_bytes(),
480+
sym::bitreverse => (bits << extra).reverse_bits(),
481+
_ => bug!("not a numeric intrinsic: {}", name),
482+
};
483+
Ok(Scalar::from_uint(bits_out, layout.size))
484+
}
485+
496486
pub fn exact_div(
497487
&mut self,
498488
a: &ImmTy<'tcx, M::Provenance>,

0 commit comments

Comments
 (0)