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 ty
::subst
::{Subst, Substs}
;
18 use ty
::{self, AdtDef, Ty, TyCtxt}
;
19 use ty
::fold
::{TypeFoldable, TypeFolder, TypeVisitor}
;
22 #[derive(Copy, Clone, Debug)]
23 pub enum LvalueTy
<'tcx
> {
27 /// Downcast to a particular variant of an enum.
28 Downcast
{ adt_def
: AdtDef
<'tcx
>,
29 substs
: &'tcx Substs
<'tcx
>,
30 variant_index
: usize },
33 impl<'tcx
> LvalueTy
<'tcx
> {
34 pub fn from_ty(ty
: Ty
<'tcx
>) -> LvalueTy
<'tcx
> {
35 LvalueTy
::Ty { ty: ty }
38 pub fn to_ty(&self, tcx
: &TyCtxt
<'tcx
>) -> Ty
<'tcx
> {
40 LvalueTy
::Ty { ty }
=>
42 LvalueTy
::Downcast { adt_def, substs, variant_index: _ }
=>
43 tcx
.mk_enum(adt_def
, substs
),
47 pub fn projection_ty(self,
49 elem
: &LvalueElem
<'tcx
>)
53 ProjectionElem
::Deref
=>
55 ty
: self.to_ty(tcx
).builtin_deref(true, ty
::LvaluePreference
::NoPreference
)
59 ProjectionElem
::Index(_
) | ProjectionElem
::ConstantIndex { .. }
=>
61 ty
: self.to_ty(tcx
).builtin_index().unwrap()
63 ProjectionElem
::Downcast(adt_def1
, index
) =>
64 match self.to_ty(tcx
).sty
{
65 ty
::TyEnum(adt_def
, substs
) => {
66 assert
!(index
< adt_def
.variants
.len());
67 assert_eq
!(adt_def
, adt_def1
);
68 LvalueTy
::Downcast
{ adt_def
: adt_def
,
70 variant_index
: index
}
73 bug
!("cannot downcast non-enum type: `{:?}`", self)
76 ProjectionElem
::Field(_
, fty
) => LvalueTy
::Ty { ty: fty }
81 impl<'tcx
> TypeFoldable
<'tcx
> for LvalueTy
<'tcx
> {
82 fn super_fold_with
<F
: TypeFolder
<'tcx
>>(&self, folder
: &mut F
) -> Self {
84 LvalueTy
::Ty { ty }
=> LvalueTy
::Ty { ty: ty.fold_with(folder) }
,
85 LvalueTy
::Downcast { adt_def, substs, variant_index }
=> {
86 let substs
= substs
.fold_with(folder
);
89 substs
: folder
.tcx().mk_substs(substs
),
90 variant_index
: variant_index
96 fn super_visit_with
<V
: TypeVisitor
<'tcx
>>(&self, visitor
: &mut V
) -> bool
{
98 LvalueTy
::Ty { ty }
=> ty
.visit_with(visitor
),
99 LvalueTy
::Downcast { substs, .. }
=> substs
.visit_with(visitor
)
104 impl<'tcx
> Mir
<'tcx
> {
105 pub fn operand_ty(&self,
107 operand
: &Operand
<'tcx
>)
111 Operand
::Consume(ref l
) => self.lvalue_ty(tcx
, l
).to_ty(tcx
),
112 Operand
::Constant(ref c
) => c
.ty
,
116 pub fn binop_ty(&self,
123 // FIXME: handle SIMD correctly
125 BinOp
::Add
| BinOp
::Sub
| BinOp
::Mul
| BinOp
::Div
| BinOp
::Rem
|
126 BinOp
::BitXor
| BinOp
::BitAnd
| BinOp
::BitOr
=> {
127 // these should be integers or floats of the same size.
128 assert_eq
!(lhs_ty
, rhs_ty
);
131 BinOp
::Shl
| BinOp
::Shr
=> {
132 lhs_ty
// lhs_ty can be != rhs_ty
134 BinOp
::Eq
| BinOp
::Lt
| BinOp
::Le
|
135 BinOp
::Ne
| BinOp
::Ge
| BinOp
::Gt
=> {
141 pub fn lvalue_ty(&self,
143 lvalue
: &Lvalue
<'tcx
>)
147 Lvalue
::Var(index
) =>
148 LvalueTy
::Ty { ty: self.var_decls[index as usize].ty }
,
149 Lvalue
::Temp(index
) =>
150 LvalueTy
::Ty { ty: self.temp_decls[index as usize].ty }
,
151 Lvalue
::Arg(index
) =>
152 LvalueTy
::Ty { ty: self.arg_decls[index as usize].ty }
,
153 Lvalue
::Static(def_id
) =>
154 LvalueTy
::Ty { ty: tcx.lookup_item_type(def_id).ty }
,
155 Lvalue
::ReturnPointer
=>
156 LvalueTy
::Ty { ty: self.return_ty.unwrap() }
,
157 Lvalue
::Projection(ref proj
) =>
158 self.lvalue_ty(tcx
, &proj
.base
).projection_ty(tcx
, &proj
.elem
)
162 pub fn rvalue_ty(&self,
164 rvalue
: &Rvalue
<'tcx
>)
168 Rvalue
::Use(ref operand
) => Some(self.operand_ty(tcx
, operand
)),
169 Rvalue
::Repeat(ref operand
, ref count
) => {
170 let op_ty
= self.operand_ty(tcx
, operand
);
171 let count
= count
.value
.as_u64(tcx
.sess
.target
.uint_type
);
172 assert_eq
!(count
as usize as u64, count
);
173 Some(tcx
.mk_array(op_ty
, count
as usize))
175 Rvalue
::Ref(reg
, bk
, ref lv
) => {
176 let lv_ty
= self.lvalue_ty(tcx
, lv
).to_ty(tcx
);
181 mutbl
: bk
.to_mutbl_lossy()
185 Rvalue
::Len(..) => Some(tcx
.types
.usize),
186 Rvalue
::Cast(_
, _
, ty
) => Some(ty
),
187 Rvalue
::BinaryOp(op
, ref lhs
, ref rhs
) => {
188 let lhs_ty
= self.operand_ty(tcx
, lhs
);
189 let rhs_ty
= self.operand_ty(tcx
, rhs
);
190 Some(self.binop_ty(tcx
, op
, lhs_ty
, rhs_ty
))
192 Rvalue
::UnaryOp(_
, ref operand
) => {
193 Some(self.operand_ty(tcx
, operand
))
198 Rvalue
::Aggregate(ref ak
, ref ops
) => {
200 AggregateKind
::Vec
=> {
201 if let Some(operand
) = ops
.get(0) {
202 let ty
= self.operand_ty(tcx
, operand
);
203 Some(tcx
.mk_array(ty
, ops
.len()))
208 AggregateKind
::Tuple
=> {
210 ops
.iter().map(|op
| self.operand_ty(tcx
, op
)).collect()
213 AggregateKind
::Adt(def
, _
, substs
) => {
214 Some(def
.type_scheme(tcx
).ty
.subst(tcx
, substs
))
216 AggregateKind
::Closure(did
, substs
) => {
217 Some(tcx
.mk_closure_from_closure_substs(
218 did
, Box
::new(substs
.clone())))
222 Rvalue
::Slice { .. }
=> None
,
223 Rvalue
::InlineAsm { .. }
=> None
229 pub fn to_mutbl_lossy(self) -> hir
::Mutability
{
231 BorrowKind
::Mut
=> hir
::MutMutable
,
232 BorrowKind
::Shared
=> hir
::MutImmutable
,
234 // We have no type corresponding to a unique imm borrow, so
235 // use `&mut`. It gives all the capabilities of an `&uniq`
236 // and hence is a safe "over approximation".
237 BorrowKind
::Unique
=> hir
::MutMutable
,
243 pub fn to_hir_binop(self) -> hir
::BinOp_
{
245 BinOp
::Add
=> hir
::BinOp_
::BiAdd
,
246 BinOp
::Sub
=> hir
::BinOp_
::BiSub
,
247 BinOp
::Mul
=> hir
::BinOp_
::BiMul
,
248 BinOp
::Div
=> hir
::BinOp_
::BiDiv
,
249 BinOp
::Rem
=> hir
::BinOp_
::BiRem
,
250 BinOp
::BitXor
=> hir
::BinOp_
::BiBitXor
,
251 BinOp
::BitAnd
=> hir
::BinOp_
::BiBitAnd
,
252 BinOp
::BitOr
=> hir
::BinOp_
::BiBitOr
,
253 BinOp
::Shl
=> hir
::BinOp_
::BiShl
,
254 BinOp
::Shr
=> hir
::BinOp_
::BiShr
,
255 BinOp
::Eq
=> hir
::BinOp_
::BiEq
,
256 BinOp
::Ne
=> hir
::BinOp_
::BiNe
,
257 BinOp
::Lt
=> hir
::BinOp_
::BiLt
,
258 BinOp
::Gt
=> hir
::BinOp_
::BiGt
,
259 BinOp
::Le
=> hir
::BinOp_
::BiLe
,
260 BinOp
::Ge
=> hir
::BinOp_
::BiGe