diff options
| author | Mahmut Bulut <vertexclique@gmail.com> | 2019-06-14 16:55:36 +0300 |
|---|---|---|
| committer | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2019-12-03 10:20:15 +0100 |
| commit | f1bacb2dca610b0babeba526020e2b87899c2d44 (patch) | |
| tree | dc79946f7e408b3e2d67ba1fb1df716061b85ceb /src/librustc_mir/interpret | |
| parent | 4787e97475de6be9487e3d9255a9c2d3c0bf9252 (diff) | |
| download | rust-f1bacb2dca610b0babeba526020e2b87899c2d44.tar.gz rust-f1bacb2dca610b0babeba526020e2b87899c2d44.zip | |
Check intrinsics for callability in const fns
Diffstat (limited to 'src/librustc_mir/interpret')
| -rw-r--r-- | src/librustc_mir/interpret/intrinsics.rs | 129 |
1 files changed, 66 insertions, 63 deletions
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 118dfcb3d9a..f6fdc51a8c2 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -2,7 +2,7 @@ //! looking at their MIR. Intrinsics/functions supported here are shared by CTFE //! and miri. -use syntax::symbol::Symbol; +use syntax_pos::symbol::{sym, Symbol}; use syntax_pos::Span; use rustc::ty; use rustc::ty::layout::{LayoutOf, Primitive, Size}; @@ -22,7 +22,7 @@ mod caller_location; mod type_name; fn numeric_intrinsic<'tcx, Tag>( - name: &str, + name: Symbol, bits: u128, kind: Primitive, ) -> InterpResult<'tcx, Scalar<Tag>> { @@ -32,11 +32,11 @@ fn numeric_intrinsic<'tcx, Tag>( }; let extra = 128 - size.bits() as u128; let bits_out = match name { - "ctpop" => bits.count_ones() as u128, - "ctlz" => bits.leading_zeros() as u128 - extra, - "cttz" => (bits << extra).trailing_zeros() as u128 - extra, - "bswap" => (bits << extra).swap_bytes(), - "bitreverse" => (bits << extra).reverse_bits(), + sym::ctpop => bits.count_ones() as u128, + sym::ctlz => bits.leading_zeros() as u128 - extra, + sym::cttz => (bits << extra).trailing_zeros() as u128 - 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, size)) @@ -51,9 +51,9 @@ crate fn eval_nullary_intrinsic<'tcx>( substs: SubstsRef<'tcx>, ) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> { let tp_ty = substs.type_at(0); - let name = &*tcx.item_name(def_id).as_str(); + let name = tcx.item_name(def_id); Ok(match name { - "type_name" => { + sym::type_name => { let alloc = type_name::alloc_type_name(tcx, tp_ty); tcx.mk_const(ty::Const { val: ty::ConstKind::Value(ConstValue::Slice { @@ -64,20 +64,20 @@ crate fn eval_nullary_intrinsic<'tcx>( ty: tcx.mk_static_str(), }) }, - "needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)), - "size_of" | - "min_align_of" | - "pref_align_of" => { + sym::needs_drop => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)), + sym::size_of | + sym::min_align_of | + sym::pref_align_of => { let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?; let n = match name { - "pref_align_of" => layout.align.pref.bytes(), - "min_align_of" => layout.align.abi.bytes(), - "size_of" => layout.size.bytes(), + sym::pref_align_of => layout.align.pref.bytes(), + sym::min_align_of => layout.align.abi.bytes(), + sym::size_of => layout.size.bytes(), _ => bug!(), }; ty::Const::from_usize(tcx, n) }, - "type_id" => ty::Const::from_bits( + sym::type_id => ty::Const::from_bits( tcx, tcx.type_id_hash(tp_ty).into(), param_env.and(tcx.types.u64), @@ -96,30 +96,32 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>, ) -> InterpResult<'tcx, bool> { let substs = instance.substs; - let intrinsic_name = &*self.tcx.item_name(instance.def_id()).as_str(); + let intrinsic_name = self.tcx.item_name(instance.def_id()); // We currently do not handle any intrinsics that are *allowed* to diverge, // but `transmute` could lack a return place in case of UB. let (dest, ret) = match ret { Some(p) => p, None => match intrinsic_name { - "transmute" => throw_ub!(Unreachable), + sym::transmute => throw_ub!(Unreachable), _ => return Ok(false), } }; + // Keep the patterns in this match ordered the same as the list in + // `src/librustc/ty/constness.rs` match intrinsic_name { - "caller_location" => { + sym::caller_location => { let location = self.alloc_caller_location_for_span(span); self.write_scalar(location.ptr, dest)?; } - "min_align_of" | - "pref_align_of" | - "needs_drop" | - "size_of" | - "type_id" | - "type_name" => { + sym::min_align_of | + sym::pref_align_of | + sym::needs_drop | + sym::size_of | + sym::type_id | + sym::type_name => { let gid = GlobalId { instance, promoted: None, @@ -129,13 +131,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.copy_op(val, dest)?; } - | "ctpop" - | "cttz" - | "cttz_nonzero" - | "ctlz" - | "ctlz_nonzero" - | "bswap" - | "bitreverse" => { + | sym::ctpop + | sym::cttz + | sym::cttz_nonzero + | sym::ctlz + | sym::ctlz_nonzero + | sym::bswap + | sym::bitreverse => { let ty = substs.type_at(0); let layout_of = self.layout_of(ty)?; let val = self.read_scalar(args[0])?.not_undef()?; @@ -144,31 +146,32 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::layout::Abi::Scalar(ref scalar) => scalar.value, _ => throw_unsup!(TypeNotPrimitive(ty)), }; - let out_val = if intrinsic_name.ends_with("_nonzero") { - if bits == 0 { - throw_ub_format!("`{}` called on 0", intrinsic_name); - } - numeric_intrinsic(intrinsic_name.trim_end_matches("_nonzero"), bits, kind)? - } else { - numeric_intrinsic(intrinsic_name, bits, kind)? + let (nonzero, 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_format!("`{}_nonzero` called on 0", intrinsic_name); + } + let out_val = numeric_intrinsic(intrinsic_name, bits, kind)?; self.write_scalar(out_val, dest)?; } - | "wrapping_add" - | "wrapping_sub" - | "wrapping_mul" - | "add_with_overflow" - | "sub_with_overflow" - | "mul_with_overflow" => { + | sym::wrapping_add + | sym::wrapping_sub + | sym::wrapping_mul + | sym::add_with_overflow + | sym::sub_with_overflow + | sym::mul_with_overflow => { let lhs = self.read_immediate(args[0])?; let rhs = self.read_immediate(args[1])?; let (bin_op, ignore_overflow) = match intrinsic_name { - "wrapping_add" => (BinOp::Add, true), - "wrapping_sub" => (BinOp::Sub, true), - "wrapping_mul" => (BinOp::Mul, true), - "add_with_overflow" => (BinOp::Add, false), - "sub_with_overflow" => (BinOp::Sub, false), - "mul_with_overflow" => (BinOp::Mul, false), + sym::wrapping_add => (BinOp::Add, true), + sym::wrapping_sub => (BinOp::Sub, true), + sym::wrapping_mul => (BinOp::Mul, true), + sym::add_with_overflow => (BinOp::Add, false), + sym::sub_with_overflow => (BinOp::Sub, false), + sym::mul_with_overflow => (BinOp::Mul, false), _ => bug!("Already checked for int ops") }; if ignore_overflow { @@ -177,10 +180,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.binop_with_overflow(bin_op, lhs, rhs, dest)?; } } - "saturating_add" | "saturating_sub" => { + sym::saturating_add | sym::saturating_sub => { let l = self.read_immediate(args[0])?; let r = self.read_immediate(args[1])?; - let is_add = intrinsic_name == "saturating_add"; + let is_add = intrinsic_name == sym::saturating_add; let (val, overflowed, _ty) = self.overflowing_binary_op(if is_add { BinOp::Add } else { @@ -220,12 +223,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; self.write_scalar(val, dest)?; } - "unchecked_shl" | "unchecked_shr" => { + sym::unchecked_shl | sym::unchecked_shr => { let l = self.read_immediate(args[0])?; let r = self.read_immediate(args[1])?; let bin_op = match intrinsic_name { - "unchecked_shl" => BinOp::Shl, - "unchecked_shr" => BinOp::Shr, + sym::unchecked_shl => BinOp::Shl, + sym::unchecked_shr => BinOp::Shr, _ => bug!("Already checked for int ops") }; let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, l, r)?; @@ -236,7 +239,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } self.write_scalar(val, dest)?; } - "rotate_left" | "rotate_right" => { + sym::rotate_left | sym::rotate_right => { // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW)) // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW)) let layout = self.layout_of(substs.type_at(0))?; @@ -247,7 +250,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let width_bits = layout.size.bits() as u128; let shift_bits = raw_shift_bits % width_bits; let inv_shift_bits = (width_bits - shift_bits) % width_bits; - let result_bits = if intrinsic_name == "rotate_left" { + let result_bits = if intrinsic_name == sym::rotate_left { (val_bits << shift_bits) | (val_bits >> inv_shift_bits) } else { (val_bits >> shift_bits) | (val_bits << inv_shift_bits) @@ -257,7 +260,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(result, dest)?; } - "ptr_offset_from" => { + sym::ptr_offset_from => { let isize_layout = self.layout_of(self.tcx.types.isize)?; let a = self.read_immediate(args[0])?.to_scalar()?; let b = self.read_immediate(args[1])?.to_scalar()?; @@ -303,10 +306,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - "transmute" => { + sym::transmute => { self.copy_op_transmute(args[0], dest)?; } - "simd_insert" => { + sym::simd_insert => { let index = u64::from(self.read_scalar(args[1])?.to_u32()?); let elem = args[2]; let input = args[0]; @@ -337,7 +340,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.copy_op(value, place)?; } } - "simd_extract" => { + sym::simd_extract => { let index = u64::from(self.read_scalar(args[1])?.to_u32()?); let (len, e_ty) = args[0].layout.ty.simd_size_and_type(self.tcx.tcx); assert!( |
