1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 * Methods for the various MIR types. These are intended for use after
13 * building is complete.
17 use rustc::middle::subst::Substs;
18 use rustc::middle::ty::{self, AdtDef, Ty};
21 #[derive(Copy, Clone, Debug)]
22 pub enum LvalueTy<'tcx> {
26 /// Downcast to a particular variant of an enum.
27 Downcast { adt_def: AdtDef<'tcx>,
28 substs: &'tcx Substs<'tcx>,
29 variant_index: usize },
32 impl<'tcx> LvalueTy<'tcx> {
33 pub fn from_ty(ty: Ty<'tcx>) -> LvalueTy<'tcx> {
34 LvalueTy::Ty { ty: ty }
37 pub fn to_ty(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
39 LvalueTy::Ty { ty } =>
41 LvalueTy::Downcast { adt_def, substs, variant_index: _ } =>
42 tcx.mk_enum(adt_def, substs),
46 pub fn projection_ty(self,
48 elem: &LvalueElem<'tcx>)
52 ProjectionElem::Deref =>
54 ty: self.to_ty(tcx).builtin_deref(true, ty::LvaluePreference::NoPreference)
58 ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
60 ty: self.to_ty(tcx).builtin_index().unwrap()
62 ProjectionElem::Downcast(adt_def1, index) =>
63 match self.to_ty(tcx).sty {
64 ty::TyEnum(adt_def, substs) => {
65 assert!(index < adt_def.variants.len());
66 assert_eq!(adt_def, adt_def1);
67 LvalueTy::Downcast { adt_def: adt_def,
69 variant_index: index }
72 tcx.sess.bug(&format!("cannot downcast non-enum type: `{:?}`", self))
75 ProjectionElem::Field(field) => {
76 let field_ty = match self {
77 LvalueTy::Ty { ty } => match ty.sty {
78 ty::TyStruct(adt_def, substs) =>
79 adt_def.struct_variant().fields[field.index()].ty(tcx, substs),
80 ty::TyTuple(ref tys) =>
82 ty::TyClosure(_, ref closure_substs) =>
83 closure_substs.upvar_tys[field.index()],
85 tcx.sess.bug(&format!("cannot get field of type: `{:?}`", ty)),
87 LvalueTy::Downcast { adt_def, substs, variant_index } =>
88 adt_def.variants[variant_index].fields[field.index()].ty(tcx, substs),
90 LvalueTy::Ty { ty: field_ty }
96 impl<'tcx> Mir<'tcx> {
97 pub fn operand_ty(&self,
99 operand: &Operand<'tcx>)
103 Operand::Consume(ref l) => self.lvalue_ty(tcx, l).to_ty(tcx),
104 Operand::Constant(ref c) => c.ty,
108 pub fn binop_ty(&self,
109 tcx: &ty::ctxt<'tcx>,
115 // FIXME: handle SIMD correctly
117 BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div | BinOp::Rem |
118 BinOp::BitXor | BinOp::BitAnd | BinOp::BitOr => {
119 // these should be integers or floats of the same size.
120 assert_eq!(lhs_ty, rhs_ty);
123 BinOp::Shl | BinOp::Shr => {
124 lhs_ty // lhs_ty can be != rhs_ty
126 BinOp::Eq | BinOp::Lt | BinOp::Le |
127 BinOp::Ne | BinOp::Ge | BinOp::Gt => {
133 pub fn lvalue_ty(&self,
134 tcx: &ty::ctxt<'tcx>,
135 lvalue: &Lvalue<'tcx>)
139 Lvalue::Var(index) =>
140 LvalueTy::Ty { ty: self.var_decls[index as usize].ty },
141 Lvalue::Temp(index) =>
142 LvalueTy::Ty { ty: self.temp_decls[index as usize].ty },
143 Lvalue::Arg(index) =>
144 LvalueTy::Ty { ty: self.arg_decls[index as usize].ty },
145 Lvalue::Static(def_id) =>
146 LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
147 Lvalue::ReturnPointer =>
148 LvalueTy::Ty { ty: self.return_ty.unwrap() },
149 Lvalue::Projection(ref proj) =>
150 self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem)
156 pub fn to_mutbl_lossy(self) -> hir::Mutability {
158 BorrowKind::Mut => hir::MutMutable,
159 BorrowKind::Shared => hir::MutImmutable,
161 // We have no type corresponding to a unique imm borrow, so
162 // use `&mut`. It gives all the capabilities of an `&uniq`
163 // and hence is a safe "over approximation".
164 BorrowKind::Unique => hir::MutMutable,
170 pub fn to_hir_binop(self) -> hir::BinOp_ {
172 BinOp::Add => hir::BinOp_::BiAdd,
173 BinOp::Sub => hir::BinOp_::BiSub,
174 BinOp::Mul => hir::BinOp_::BiMul,
175 BinOp::Div => hir::BinOp_::BiDiv,
176 BinOp::Rem => hir::BinOp_::BiRem,
177 BinOp::BitXor => hir::BinOp_::BiBitXor,
178 BinOp::BitAnd => hir::BinOp_::BiBitAnd,
179 BinOp::BitOr => hir::BinOp_::BiBitOr,
180 BinOp::Shl => hir::BinOp_::BiShl,
181 BinOp::Shr => hir::BinOp_::BiShr,
182 BinOp::Eq => hir::BinOp_::BiEq,
183 BinOp::Ne => hir::BinOp_::BiNe,
184 BinOp::Lt => hir::BinOp_::BiLt,
185 BinOp::Gt => hir::BinOp_::BiGt,
186 BinOp::Le => hir::BinOp_::BiLe,
187 BinOp::Ge => hir::BinOp_::BiGe