about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJames Miller <james@aatch.net>2015-01-11 12:58:20 +1300
committerFelix S. Klock II <pnkfelix@pnkfx.org>2015-04-10 12:23:08 +0200
commit41dd35503a358b652cfbbf7fba499cbaf1234637 (patch)
tree02479899a1c7e3fa021bf26cf22fe8636c4b323d
parent6b95d8bed8afff7262ec5623677e320bf63d2230 (diff)
downloadrust-41dd35503a358b652cfbbf7fba499cbaf1234637.tar.gz
rust-41dd35503a358b652cfbbf7fba499cbaf1234637.zip
Implement `discriminant_value` intrinsic
Implements an intrinsic for extracting the value of the discriminant
enum variant values. For non-enum types, this returns zero, otherwise it
returns the value we use for discriminant comparisons. This means that
enum types that do not have a discriminant will also work in this
arrangement.

This is (at least part of) the work on Issue #24263
-rw-r--r--src/libcore/intrinsics.rs6
-rw-r--r--src/librustc_trans/trans/intrinsic.rs12
-rw-r--r--src/librustc_typeck/check/mod.rs6
3 files changed, 24 insertions, 0 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 0e91eafce18..80f506ebc06 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -569,4 +569,10 @@ extern "rust-intrinsic" {
     pub fn overflowing_sub<T>(a: T, b: T) -> T;
     /// Returns (a * b) mod 2^N, where N is the width of N in bits.
     pub fn overflowing_mul<T>(a: T, b: T) -> T;
+
+    /// Returns the value of the discriminant for the variant in 'v',
+    /// cast to a `u64`; if `T` has no discriminant, returns 0.
+    // SNAP 5520801
+    #[cfg(not(stage0))]
+    pub fn discriminant_value<T>(v: &T) -> u64;
 }
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index 62a6ede4c2f..fc3c0841dd8 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -14,6 +14,7 @@ use llvm;
 use llvm::{SequentiallyConsistent, Acquire, Release, AtomicXchg, ValueRef, TypeKind};
 use middle::subst;
 use middle::subst::FnSpace;
+use trans::adt;
 use trans::base::*;
 use trans::build::*;
 use trans::callee;
@@ -683,6 +684,17 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             }
         }
 
+        (_, "discriminant_value") => {
+            let val_ty = substs.types.get(FnSpace, 0);
+            match val_ty.sty {
+                ty::ty_enum(..) => {
+                    let repr = adt::represent_type(ccx, *val_ty);
+                    adt::trans_get_discr(bcx, &*repr, llargs[0], Some(llret_ty))
+                }
+                _ => C_null(llret_ty)
+            }
+        }
+
         // This requires that atomic intrinsics follow a specific naming pattern:
         // "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
         (_, name) if name.starts_with("atomic_") => {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index f7bbc693ce5..31039e3abca 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -5073,6 +5073,12 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
 
             "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
 
+            "discriminant_value" => (1, vec![
+                    ty::mk_imm_rptr(tcx,
+                                    tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
+                                                                  ty::BrAnon(0))),
+                                    param(ccx, 0))], tcx.types.u64),
+
             ref other => {
                 span_err!(tcx.sess, it.span, E0093,
                     "unrecognized intrinsic function: `{}`", *other);