diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 5924d515dda59..ccac040980f93 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -545,6 +545,11 @@ extern "rust-intrinsic" { pub fn u32_mul_with_overflow(x: u32, y: u32) -> (u32, bool); /// Performs checked `u64` multiplication. pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool); + + /// Returns the value of the discriminant for the variant in 'v'. If there is no discriminant + /// for the type, zero is returned + #[cfg(not(stage0))] + pub fn discriminant_value(v: &T) -> u64; } diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index b22c7f763f035..26cdb57d05216 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; @@ -517,6 +518,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_[_]", 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 1d184131dede3..d1bb0f80441a1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5767,6 +5767,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); diff --git a/src/test/run-pass/discriminant_value.rs b/src/test/run-pass/discriminant_value.rs new file mode 100644 index 0000000000000..531a30d658001 --- /dev/null +++ b/src/test/run-pass/discriminant_value.rs @@ -0,0 +1,62 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate core; +use core::intrinsics::discriminant_value; + +enum CLike1 { + A, + B, + C, + D +} + +enum CLike2 { + A = 5, + B = 2, + C = 19, + D +} + +enum ADT { + First(u32, u32), + Second(u64) +} + +enum NullablePointer { + Something(&'static u32), + Nothing +} + +static CONST : u32 = 0xBEEF; + +pub fn main() { + unsafe { + + assert_eq!(discriminant_value(&CLike1::A), 0); + assert_eq!(discriminant_value(&CLike1::B), 1); + assert_eq!(discriminant_value(&CLike1::C), 2); + assert_eq!(discriminant_value(&CLike1::D), 3); + + assert_eq!(discriminant_value(&CLike2::A), 5); + assert_eq!(discriminant_value(&CLike2::B), 2); + assert_eq!(discriminant_value(&CLike2::C), 19); + assert_eq!(discriminant_value(&CLike2::D), 20); + + assert_eq!(discriminant_value(&ADT::First(0,0)), 0); + assert_eq!(discriminant_value(&ADT::Second(5)), 1); + + assert_eq!(discriminant_value(&NullablePointer::Nothing), 1); + assert_eq!(discriminant_value(&NullablePointer::Something(&CONST)), 0); + + assert_eq!(discriminant_value(&10), 0); + assert_eq!(discriminant_value(&"test"), 0); + } +}