about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/mir/mod.rs7
-rw-r--r--src/librustc/mir/tcx.rs32
-rw-r--r--src/librustc/mir/visit.rs4
-rw-r--r--src/librustc_borrowck/borrowck/mir/gather_moves.rs1
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs8
-rw-r--r--src/librustc_passes/mir_stats.rs1
-rw-r--r--src/librustc_trans/mir/rvalue.rs19
7 files changed, 60 insertions, 12 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index cbb7b2710f5..a3580352261 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -997,6 +997,12 @@ pub enum Rvalue<'tcx> {
 
     UnaryOp(UnOp, Operand<'tcx>),
 
+    /// Read the discriminant of an ADT.
+    ///
+    /// Undefined (i.e. no effort is made to make it defined, but there’s no reason why it cannot
+    /// be defined to return, say, a 0) if ADT is not an enum.
+    Discriminant(Lvalue<'tcx>),
+
     /// Creates an *uninitialized* Box
     Box(Ty<'tcx>),
 
@@ -1111,6 +1117,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                 write!(fmt, "Checked{:?}({:?}, {:?})", op, a, b)
             }
             UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
+            Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval),
             Box(ref t) => write!(fmt, "Box({:?})", t),
             InlineAsm { ref asm, ref outputs, ref inputs } => {
                 write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index f1268521d67..68fbadd5d60 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -135,15 +135,15 @@ impl<'tcx> Lvalue<'tcx> {
 impl<'tcx> Rvalue<'tcx> {
     pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>>
     {
-        match self {
-            &Rvalue::Use(ref operand) => Some(operand.ty(mir, tcx)),
-            &Rvalue::Repeat(ref operand, ref count) => {
+        match *self {
+            Rvalue::Use(ref operand) => Some(operand.ty(mir, tcx)),
+            Rvalue::Repeat(ref operand, ref count) => {
                 let op_ty = operand.ty(mir, tcx);
                 let count = count.value.as_u64(tcx.sess.target.uint_type);
                 assert_eq!(count as usize as u64, count);
                 Some(tcx.mk_array(op_ty, count as usize))
             }
-            &Rvalue::Ref(reg, bk, ref lv) => {
+            Rvalue::Ref(reg, bk, ref lv) => {
                 let lv_ty = lv.ty(mir, tcx).to_ty(tcx);
                 Some(tcx.mk_ref(reg,
                     ty::TypeAndMut {
@@ -152,27 +152,35 @@ impl<'tcx> Rvalue<'tcx> {
                     }
                 ))
             }
-            &Rvalue::Len(..) => Some(tcx.types.usize),
-            &Rvalue::Cast(.., ty) => Some(ty),
-            &Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
+            Rvalue::Len(..) => Some(tcx.types.usize),
+            Rvalue::Cast(.., ty) => Some(ty),
+            Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
                 let lhs_ty = lhs.ty(mir, tcx);
                 let rhs_ty = rhs.ty(mir, tcx);
                 Some(op.ty(tcx, lhs_ty, rhs_ty))
             }
-            &Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
+            Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
                 let lhs_ty = lhs.ty(mir, tcx);
                 let rhs_ty = rhs.ty(mir, tcx);
                 let ty = op.ty(tcx, lhs_ty, rhs_ty);
                 let ty = tcx.intern_tup(&[ty, tcx.types.bool], false);
                 Some(ty)
             }
-            &Rvalue::UnaryOp(_, ref operand) => {
+            Rvalue::UnaryOp(_, ref operand) => {
                 Some(operand.ty(mir, tcx))
             }
-            &Rvalue::Box(t) => {
+            Rvalue::Discriminant(ref lval) => {
+                if let ty::TyAdt(_, _) = lval.ty(mir, tcx).to_ty(tcx).sty {
+                    // TODO
+                    None
+                } else {
+                    None
+                }
+            }
+            Rvalue::Box(t) => {
                 Some(tcx.mk_box(t))
             }
-            &Rvalue::Aggregate(ref ak, ref ops) => {
+            Rvalue::Aggregate(ref ak, ref ops) => {
                 match *ak {
                     AggregateKind::Array => {
                         if let Some(operand) = ops.get(0) {
@@ -196,7 +204,7 @@ impl<'tcx> Rvalue<'tcx> {
                     }
                 }
             }
-            &Rvalue::InlineAsm { .. } => None
+            Rvalue::InlineAsm { .. } => None
         }
     }
 }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index b5da304a109..921b4e78b32 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -506,6 +506,10 @@ macro_rules! make_mir_visitor {
                         self.visit_operand(op, location);
                     }
 
+                    Rvalue::Discriminant(ref $($mutability)* lvalue) => {
+                        self.visit_lvalue(lvalue, LvalueContext::Inspect, location);
+                    }
+
                     Rvalue::Box(ref $($mutability)* ty) => {
                         self.visit_ty(ty);
                     }
diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
index 7cf6ab2999c..806395c857a 100644
--- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
@@ -435,6 +435,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
                 }
             }
             Rvalue::Ref(..) |
+            Rvalue::Discriminant(..) |
             Rvalue::Len(..) |
             Rvalue::InlineAsm { .. } => {}
             Rvalue::Box(..) => {
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 9c1107344f2..16371be576b 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -739,6 +739,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                 }
             }
 
+            Rvalue::Discriminant(..) => {
+                // FIXME discriminant
+                self.add(Qualif::NOT_CONST);
+                if self.mode != Mode::Fn {
+                    bug!("implement discriminant const qualify");
+                }
+            }
+
             Rvalue::Box(_) => {
                 self.add(Qualif::NOT_CONST);
                 if self.mode != Mode::Fn {
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index cec1c20519b..e29febdb712 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -186,6 +186,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
             Rvalue::BinaryOp(..) => "Rvalue::BinaryOp",
             Rvalue::CheckedBinaryOp(..) => "Rvalue::CheckedBinaryOp",
             Rvalue::UnaryOp(..) => "Rvalue::UnaryOp",
+            Rvalue::Discriminant(..) => "Rvalue::Discriminant",
             Rvalue::Box(..) => "Rvalue::Box",
             Rvalue::Aggregate(ref kind, ref _operands) => {
                 // AggregateKind is not distinguished by visit API, so
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 0a8e676b078..fe11e0426df 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -433,6 +433,24 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 })
             }
 
+            mir::Rvalue::Discriminant(ref lvalue) => {
+                let discr_lvalue = self.trans_lvalue(&bcx, lvalue);
+                let enum_ty = discr_lvalue.ty.to_ty(bcx.tcx());
+                let discr_ty = rvalue.ty(&*self.mir, bcx.tcx()).unwrap();
+                let discr_type = type_of::immediate_type_of(bcx.ccx, discr_ty);
+                // FIXME: inline this
+                let discr = adt::trans_get_discr(&bcx, enum_ty, discr_lvalue.llval, None, true);
+                let discr = if common::val_ty(discr) == Type::i1(bcx.ccx) {
+                    bcx.zext(discr, discr_type)
+                } else {
+                    bcx.trunc(discr, discr_type)
+                };
+                (bcx, OperandRef {
+                    val: OperandValue::Immediate(discr),
+                    ty: discr_ty
+                })
+            }
+
             mir::Rvalue::Box(content_ty) => {
                 let content_ty: Ty<'tcx> = self.monomorphize(&content_ty);
                 let llty = type_of::type_of(bcx.ccx, content_ty);
@@ -661,6 +679,7 @@ pub fn rvalue_creates_operand(rvalue: &mir::Rvalue) -> bool {
         mir::Rvalue::BinaryOp(..) |
         mir::Rvalue::CheckedBinaryOp(..) |
         mir::Rvalue::UnaryOp(..) |
+        mir::Rvalue::Discriminant(..) |
         mir::Rvalue::Box(..) |
         mir::Rvalue::Use(..) =>
             true,