]> git.proxmox.com Git - rustc.git/blob - src/librustc/mir/tcx.rs
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / librustc / mir / tcx.rs
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.
4 //
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.
10
11 /*!
12 * Methods for the various MIR types. These are intended for use after
13 * building is complete.
14 */
15
16 use mir::repr::*;
17 use middle::subst::Substs;
18 use middle::ty::{self, AdtDef, Ty};
19 use rustc_front::hir;
20
21 #[derive(Copy, Clone, Debug)]
22 pub enum LvalueTy<'tcx> {
23 /// Normal type.
24 Ty { ty: Ty<'tcx> },
25
26 /// Downcast to a particular variant of an enum.
27 Downcast { adt_def: AdtDef<'tcx>,
28 substs: &'tcx Substs<'tcx>,
29 variant_index: usize },
30 }
31
32 impl<'tcx> LvalueTy<'tcx> {
33 pub fn from_ty(ty: Ty<'tcx>) -> LvalueTy<'tcx> {
34 LvalueTy::Ty { ty: ty }
35 }
36
37 pub fn to_ty(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
38 match *self {
39 LvalueTy::Ty { ty } =>
40 ty,
41 LvalueTy::Downcast { adt_def, substs, variant_index: _ } =>
42 tcx.mk_enum(adt_def, substs),
43 }
44 }
45
46 pub fn projection_ty(self,
47 tcx: &ty::ctxt<'tcx>,
48 elem: &LvalueElem<'tcx>)
49 -> LvalueTy<'tcx>
50 {
51 match *elem {
52 ProjectionElem::Deref =>
53 LvalueTy::Ty {
54 ty: self.to_ty(tcx).builtin_deref(true, ty::LvaluePreference::NoPreference)
55 .unwrap()
56 .ty
57 },
58 ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
59 LvalueTy::Ty {
60 ty: self.to_ty(tcx).builtin_index().unwrap()
61 },
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,
68 substs: substs,
69 variant_index: index }
70 }
71 _ => {
72 tcx.sess.bug(&format!("cannot downcast non-enum type: `{:?}`", self))
73 }
74 },
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) =>
81 tys[field.index()],
82 ty::TyClosure(_, ref closure_substs) =>
83 closure_substs.upvar_tys[field.index()],
84 _ =>
85 tcx.sess.bug(&format!("cannot get field of type: `{:?}`", ty)),
86 },
87 LvalueTy::Downcast { adt_def, substs, variant_index } =>
88 adt_def.variants[variant_index].fields[field.index()].ty(tcx, substs),
89 };
90 LvalueTy::Ty { ty: field_ty }
91 }
92 }
93 }
94 }
95
96 impl<'tcx> Mir<'tcx> {
97 pub fn operand_ty(&self,
98 tcx: &ty::ctxt<'tcx>,
99 operand: &Operand<'tcx>)
100 -> Ty<'tcx>
101 {
102 match *operand {
103 Operand::Consume(ref l) => self.lvalue_ty(tcx, l).to_ty(tcx),
104 Operand::Constant(ref c) => c.ty,
105 }
106 }
107
108 pub fn binop_ty(&self,
109 tcx: &ty::ctxt<'tcx>,
110 op: BinOp,
111 lhs_ty: Ty<'tcx>,
112 rhs_ty: Ty<'tcx>)
113 -> Ty<'tcx>
114 {
115 // FIXME: handle SIMD correctly
116 match op {
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);
121 lhs_ty
122 }
123 BinOp::Shl | BinOp::Shr => {
124 lhs_ty // lhs_ty can be != rhs_ty
125 }
126 BinOp::Eq | BinOp::Lt | BinOp::Le |
127 BinOp::Ne | BinOp::Ge | BinOp::Gt => {
128 tcx.types.bool
129 }
130 }
131 }
132
133 pub fn lvalue_ty(&self,
134 tcx: &ty::ctxt<'tcx>,
135 lvalue: &Lvalue<'tcx>)
136 -> LvalueTy<'tcx>
137 {
138 match *lvalue {
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)
151 }
152 }
153 }
154
155 impl BorrowKind {
156 pub fn to_mutbl_lossy(self) -> hir::Mutability {
157 match self {
158 BorrowKind::Mut => hir::MutMutable,
159 BorrowKind::Shared => hir::MutImmutable,
160
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,
165 }
166 }
167 }
168
169 impl BinOp {
170 pub fn to_hir_binop(self) -> hir::BinOp_ {
171 match self {
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
188 }
189 }
190 }