about summary refs log tree commit diff
path: root/src/librustc_mir/interpret
diff options
context:
space:
mode:
authorMahmut Bulut <vertexclique@gmail.com>2019-06-14 16:55:36 +0300
committerOliver Scherer <github35764891676564198441@oli-obk.de>2019-12-03 10:20:15 +0100
commitf1bacb2dca610b0babeba526020e2b87899c2d44 (patch)
treedc79946f7e408b3e2d67ba1fb1df716061b85ceb /src/librustc_mir/interpret
parent4787e97475de6be9487e3d9255a9c2d3c0bf9252 (diff)
downloadrust-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.rs129
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!(