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 middle
::subst
::Substs
;
18 use 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