diff options
| -rw-r--r-- | src/librustc/mir/mod.rs | 7 | ||||
| -rw-r--r-- | src/librustc/mir/tcx.rs | 32 | ||||
| -rw-r--r-- | src/librustc/mir/visit.rs | 4 | ||||
| -rw-r--r-- | src/librustc_borrowck/borrowck/mir/gather_moves.rs | 1 | ||||
| -rw-r--r-- | src/librustc_mir/transform/qualify_consts.rs | 8 | ||||
| -rw-r--r-- | src/librustc_passes/mir_stats.rs | 1 | ||||
| -rw-r--r-- | src/librustc_trans/mir/rvalue.rs | 19 |
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, |
