1 // Copyright 2014 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.
11 use graphviz
::IntoCow
;
12 use middle
::const_val
::ConstVal
;
13 use rustc_const_math
::{ConstUsize, ConstInt}
;
14 use hir
::def_id
::DefId
;
15 use ty
::subst
::Substs
;
16 use ty
::{self, AdtDef, ClosureSubsts, FnOutput, Region, Ty}
;
18 use rustc_back
::slice
;
21 use std
::borrow
::{Cow}
;
22 use std
::fmt
::{self, Debug, Formatter, Write}
;
24 use std
::ops
::{Index, IndexMut}
;
25 use syntax
::ast
::{self, Name}
;
26 use syntax
::codemap
::Span
;
28 /// Lowered representation of a single function.
29 #[derive(Clone, RustcEncodable, RustcDecodable)]
30 pub struct Mir
<'tcx
> {
31 /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
32 /// that indexes into this vector.
33 pub basic_blocks
: Vec
<BasicBlockData
<'tcx
>>,
35 /// List of lexical scopes; these are referenced by statements and
36 /// used (eventually) for debuginfo. Indexed by a `ScopeId`.
37 pub scopes
: Vec
<ScopeData
>,
39 /// Return type of the function.
40 pub return_ty
: FnOutput
<'tcx
>,
42 /// Variables: these are stack slots corresponding to user variables. They may be
43 /// assigned many times.
44 pub var_decls
: Vec
<VarDecl
<'tcx
>>,
46 /// Args: these are stack slots corresponding to the input arguments.
47 pub arg_decls
: Vec
<ArgDecl
<'tcx
>>,
49 /// Temp declarations: stack slots that for temporaries created by
50 /// the compiler. These are assigned once, but they are not SSA
51 /// values in that it is possible to borrow them and mutate them
52 /// through the resulting reference.
53 pub temp_decls
: Vec
<TempDecl
<'tcx
>>,
55 /// A span representing this MIR, for error reporting
59 /// where execution begins
60 pub const START_BLOCK
: BasicBlock
= BasicBlock(0);
62 /// where execution ends, on normal return
63 pub const END_BLOCK
: BasicBlock
= BasicBlock(1);
65 impl<'tcx
> Mir
<'tcx
> {
66 pub fn all_basic_blocks(&self) -> Vec
<BasicBlock
> {
67 (0..self.basic_blocks
.len())
68 .map(|i
| BasicBlock
::new(i
))
72 pub fn basic_block_data(&self, bb
: BasicBlock
) -> &BasicBlockData
<'tcx
> {
73 &self.basic_blocks
[bb
.index()]
76 pub fn basic_block_data_mut(&mut self, bb
: BasicBlock
) -> &mut BasicBlockData
<'tcx
> {
77 &mut self.basic_blocks
[bb
.index()]
81 impl<'tcx
> Index
<BasicBlock
> for Mir
<'tcx
> {
82 type Output
= BasicBlockData
<'tcx
>;
85 fn index(&self, index
: BasicBlock
) -> &BasicBlockData
<'tcx
> {
86 self.basic_block_data(index
)
90 impl<'tcx
> IndexMut
<BasicBlock
> for Mir
<'tcx
> {
92 fn index_mut(&mut self, index
: BasicBlock
) -> &mut BasicBlockData
<'tcx
> {
93 self.basic_block_data_mut(index
)
97 ///////////////////////////////////////////////////////////////////////////
98 // Mutability and borrow kinds
100 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
101 pub enum Mutability
{
106 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
107 pub enum BorrowKind
{
108 /// Data must be immutable and is aliasable.
111 /// Data must be immutable but not aliasable. This kind of borrow
112 /// cannot currently be expressed by the user and is used only in
113 /// implicit closure bindings. It is needed when you the closure
114 /// is borrowing or mutating a mutable referent, e.g.:
116 /// let x: &mut isize = ...;
117 /// let y = || *x += 5;
119 /// If we were to try to translate this closure into a more explicit
120 /// form, we'd encounter an error with the code as written:
122 /// struct Env { x: & &mut isize }
123 /// let x: &mut isize = ...;
124 /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
125 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
127 /// This is then illegal because you cannot mutate a `&mut` found
128 /// in an aliasable location. To solve, you'd have to translate with
129 /// an `&mut` borrow:
131 /// struct Env { x: & &mut isize }
132 /// let x: &mut isize = ...;
133 /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
134 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
136 /// Now the assignment to `**env.x` is legal, but creating a
137 /// mutable pointer to `x` is not because `x` is not mutable. We
138 /// could fix this by declaring `x` as `let mut x`. This is ok in
139 /// user code, if awkward, but extra weird for closures, since the
140 /// borrow is hidden.
142 /// So we introduce a "unique imm" borrow -- the referent is
143 /// immutable, but not aliasable. This solves the problem. For
144 /// simplicity, we don't give users the way to express this
145 /// borrow, it's just used when translating closures.
148 /// Data is mutable and not aliasable.
152 ///////////////////////////////////////////////////////////////////////////
153 // Variables and temps
155 /// A "variable" is a binding declared by the user as part of the fn
156 /// decl, a let, etc.
157 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
158 pub struct VarDecl
<'tcx
> {
159 /// `let mut x` vs `let x`
160 pub mutability
: Mutability
,
162 /// name that user gave the variable; not that, internally,
163 /// mir references variables by index
166 /// type inferred for this variable (`let x: ty = ...`)
169 /// scope in which variable was declared
172 /// span where variable was declared
176 /// A "temp" is a temporary that we place on the stack. They are
177 /// anonymous, always mutable, and have only a type.
178 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
179 pub struct TempDecl
<'tcx
> {
183 /// A "arg" is one of the function's formal arguments. These are
184 /// anonymous and distinct from the bindings that the user declares.
186 /// For example, in this function:
189 /// fn foo((x, y): (i32, u32)) { ... }
192 /// there is only one argument, of type `(i32, u32)`, but two bindings
194 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
195 pub struct ArgDecl
<'tcx
> {
198 /// If true, this argument is a tuple after monomorphization,
199 /// and has to be collected from multiple actual arguments.
203 ///////////////////////////////////////////////////////////////////////////
206 /// The index of a particular basic block. The index is into the `basic_blocks`
207 /// list of the `Mir`.
209 /// (We use a `u32` internally just to save memory.)
210 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
211 pub struct BasicBlock(u32);
214 pub fn new(index
: usize) -> BasicBlock
{
215 assert
!(index
< (u32::MAX
as usize));
216 BasicBlock(index
as u32)
219 /// Extract the index.
220 pub fn index(self) -> usize {
225 impl Debug
for BasicBlock
{
226 fn fmt(&self, fmt
: &mut Formatter
) -> fmt
::Result
{
227 write
!(fmt
, "bb{}", self.0)
231 ///////////////////////////////////////////////////////////////////////////
232 // BasicBlockData and Terminator
234 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
235 pub struct BasicBlockData
<'tcx
> {
236 /// List of statements in this block.
237 pub statements
: Vec
<Statement
<'tcx
>>,
239 /// Terminator for this block.
241 /// NB. This should generally ONLY be `None` during construction.
242 /// Therefore, you should generally access it via the
243 /// `terminator()` or `terminator_mut()` methods. The only
244 /// exception is that certain passes, such as `simplify_cfg`, swap
245 /// out the terminator temporarily with `None` while they continue
246 /// to recurse over the set of basic blocks.
247 pub terminator
: Option
<Terminator
<'tcx
>>,
249 /// If true, this block lies on an unwind path. This is used
250 /// during trans where distinct kinds of basic blocks may be
251 /// generated (particularly for MSVC cleanup). Unwind blocks must
252 /// only branch to other unwind blocks.
253 pub is_cleanup
: bool
,
256 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
257 pub struct Terminator
<'tcx
> {
260 pub kind
: TerminatorKind
<'tcx
>
263 #[derive(Clone, RustcEncodable, RustcDecodable)]
264 pub enum TerminatorKind
<'tcx
> {
265 /// block should have one successor in the graph; we jump there
270 /// jump to branch 0 if this lvalue evaluates to true
273 targets
: (BasicBlock
, BasicBlock
),
276 /// lvalue evaluates to some enum; jump depending on the branch
279 adt_def
: AdtDef
<'tcx
>,
280 targets
: Vec
<BasicBlock
>,
283 /// operand evaluates to an integer; jump depending on its value
284 /// to one of the targets, and otherwise fallback to `otherwise`
286 /// discriminant value being tested
289 /// type of value being tested
292 /// Possible values. The locations to branch to in each case
293 /// are found in the corresponding indices from the `targets` vector.
294 values
: Vec
<ConstVal
>,
296 /// Possible branch sites. The length of this vector should be
297 /// equal to the length of the `values` vector plus 1 -- the
298 /// extra item is the block to branch to if none of the values
300 targets
: Vec
<BasicBlock
>,
303 /// Indicates that the landing pad is finished and unwinding should
304 /// continue. Emitted by build::scope::diverge_cleanup.
307 /// Indicates a normal return. The ReturnPointer lvalue should
308 /// have been filled in by now. This should only occur in the
316 unwind
: Option
<BasicBlock
>
319 /// Block ends with a call of a converging function
321 /// The function that’s being called
323 /// Arguments the function is called with
324 args
: Vec
<Operand
<'tcx
>>,
325 /// Destination for the return value. If some, the call is converging.
326 destination
: Option
<(Lvalue
<'tcx
>, BasicBlock
)>,
327 /// Cleanups to be done if the call unwinds.
328 cleanup
: Option
<BasicBlock
>
332 impl<'tcx
> Terminator
<'tcx
> {
333 pub fn successors(&self) -> Cow
<[BasicBlock
]> {
334 self.kind
.successors()
337 pub fn successors_mut(&mut self) -> Vec
<&mut BasicBlock
> {
338 self.kind
.successors_mut()
342 impl<'tcx
> TerminatorKind
<'tcx
> {
343 pub fn successors(&self) -> Cow
<[BasicBlock
]> {
344 use self::TerminatorKind
::*;
346 Goto { target: ref b }
=> slice
::ref_slice(b
).into_cow(),
347 If { targets: (b1, b2), .. }
=> vec
![b1
, b2
].into_cow(),
348 Switch { targets: ref b, .. }
=> b
[..].into_cow(),
349 SwitchInt { targets: ref b, .. }
=> b
[..].into_cow(),
350 Resume
=> (&[]).into_cow(),
351 Return
=> (&[]).into_cow(),
352 Call { destination: Some((_, t)), cleanup: Some(c), .. }
=> vec
![t
, c
].into_cow(),
353 Call { destination: Some((_, ref t)), cleanup: None, .. }
=>
354 slice
::ref_slice(t
).into_cow(),
355 Call { destination: None, cleanup: Some(ref c), .. }
=> slice
::ref_slice(c
).into_cow(),
356 Call { destination: None, cleanup: None, .. }
=> (&[]).into_cow(),
357 Drop { target, unwind: Some(unwind), .. }
=> vec
![target
, unwind
].into_cow(),
358 Drop { ref target, .. }
=> slice
::ref_slice(target
).into_cow(),
362 // FIXME: no mootable cow. I’m honestly not sure what a “cow” between `&mut [BasicBlock]` and
363 // `Vec<&mut BasicBlock>` would look like in the first place.
364 pub fn successors_mut(&mut self) -> Vec
<&mut BasicBlock
> {
365 use self::TerminatorKind
::*;
367 Goto { target: ref mut b }
=> vec
![b
],
368 If { targets: (ref mut b1, ref mut b2), .. }
=> vec
![b1
, b2
],
369 Switch { targets: ref mut b, .. }
=> b
.iter_mut().collect(),
370 SwitchInt { targets: ref mut b, .. }
=> b
.iter_mut().collect(),
371 Resume
=> Vec
::new(),
372 Return
=> Vec
::new(),
373 Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut c), .. }
=> vec
![t
, c
],
374 Call { destination: Some((_, ref mut t)), cleanup: None, .. }
=> vec
![t
],
375 Call { destination: None, cleanup: Some(ref mut c), .. }
=> vec
![c
],
376 Call { destination: None, cleanup: None, .. }
=> vec
![],
377 Drop { ref mut target, unwind: Some(ref mut unwind), .. }
=> vec
![target
, unwind
],
378 Drop { ref mut target, .. }
=> vec
![target
]
383 impl<'tcx
> BasicBlockData
<'tcx
> {
384 pub fn new(terminator
: Option
<Terminator
<'tcx
>>) -> BasicBlockData
<'tcx
> {
387 terminator
: terminator
,
392 /// Accessor for terminator.
394 /// Terminator may not be None after construction of the basic block is complete. This accessor
395 /// provides a convenience way to reach the terminator.
396 pub fn terminator(&self) -> &Terminator
<'tcx
> {
397 self.terminator
.as_ref().expect("invalid terminator state")
400 pub fn terminator_mut(&mut self) -> &mut Terminator
<'tcx
> {
401 self.terminator
.as_mut().expect("invalid terminator state")
405 impl<'tcx
> Debug
for TerminatorKind
<'tcx
> {
406 fn fmt(&self, fmt
: &mut Formatter
) -> fmt
::Result
{
408 let successors
= self.successors();
409 let labels
= self.fmt_successor_labels();
410 assert_eq
!(successors
.len(), labels
.len());
412 match successors
.len() {
415 1 => write
!(fmt
, " -> {:?}", successors
[0]),
418 write
!(fmt
, " -> [")?
;
419 for (i
, target
) in successors
.iter().enumerate() {
423 write
!(fmt
, "{}: {:?}", labels
[i
], target
)?
;
432 impl<'tcx
> TerminatorKind
<'tcx
> {
433 /// Write the "head" part of the terminator; that is, its name and the data it uses to pick the
434 /// successor basic block, if any. The only information not inlcuded is the list of possible
435 /// successors, which may be rendered differently between the text and the graphviz format.
436 pub fn fmt_head
<W
: Write
>(&self, fmt
: &mut W
) -> fmt
::Result
{
437 use self::TerminatorKind
::*;
439 Goto { .. }
=> write
!(fmt
, "goto"),
440 If { cond: ref lv, .. }
=> write
!(fmt
, "if({:?})", lv
),
441 Switch { discr: ref lv, .. }
=> write
!(fmt
, "switch({:?})", lv
),
442 SwitchInt { discr: ref lv, .. }
=> write
!(fmt
, "switchInt({:?})", lv
),
443 Return
=> write
!(fmt
, "return"),
444 Resume
=> write
!(fmt
, "resume"),
445 Drop { ref value, .. }
=> write
!(fmt
, "drop({:?})", value
),
446 Call { ref func, ref args, ref destination, .. }
=> {
447 if let Some((ref destination
, _
)) = *destination
{
448 write
!(fmt
, "{:?} = ", destination
)?
;
450 write
!(fmt
, "{:?}(", func
)?
;
451 for (index
, arg
) in args
.iter().enumerate() {
455 write
!(fmt
, "{:?}", arg
)?
;
462 /// Return the list of labels for the edges to the successor basic blocks.
463 pub fn fmt_successor_labels(&self) -> Vec
<Cow
<'
static, str>> {
464 use self::TerminatorKind
::*;
466 Return
| Resume
=> vec
![],
467 Goto { .. }
=> vec
!["".into()],
468 If { .. }
=> vec
!["true".into(), "false".into()],
469 Switch { ref adt_def, .. }
=> {
472 .map(|variant
| variant
.name
.to_string().into())
475 SwitchInt { ref values, .. }
=> {
478 let mut buf
= String
::new();
479 fmt_const_val(&mut buf
, const_val
).unwrap();
482 .chain(iter
::once(String
::from("otherwise").into()))
485 Call { destination: Some(_), cleanup: Some(_), .. }
=>
486 vec
!["return".into_cow(), "unwind".into_cow()],
487 Call { destination: Some(_), cleanup: None, .. }
=> vec
!["return".into_cow()],
488 Call { destination: None, cleanup: Some(_), .. }
=> vec
!["unwind".into_cow()],
489 Call { destination: None, cleanup: None, .. }
=> vec
![],
490 Drop { unwind: None, .. }
=> vec
!["return".into_cow()],
491 Drop { .. }
=> vec
!["return".into_cow(), "unwind".into_cow()],
497 ///////////////////////////////////////////////////////////////////////////
500 #[derive(Clone, RustcEncodable, RustcDecodable)]
501 pub struct Statement
<'tcx
> {
504 pub kind
: StatementKind
<'tcx
>,
507 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
508 pub enum StatementKind
<'tcx
> {
509 Assign(Lvalue
<'tcx
>, Rvalue
<'tcx
>),
512 impl<'tcx
> Debug
for Statement
<'tcx
> {
513 fn fmt(&self, fmt
: &mut Formatter
) -> fmt
::Result
{
514 use self::StatementKind
::*;
516 Assign(ref lv
, ref rv
) => write
!(fmt
, "{:?} = {:?}", lv
, rv
)
521 ///////////////////////////////////////////////////////////////////////////
524 /// A path to a value; something that can be evaluated without
525 /// changing or disturbing program state.
526 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
527 pub enum Lvalue
<'tcx
> {
528 /// local variable declared by the user
531 /// temporary introduced during lowering into MIR
534 /// formal parameter of the function; note that these are NOT the
535 /// bindings that the user declares, which are vars
538 /// static or static mut variable
541 /// the return pointer of the fn
544 /// projection out of an lvalue (access a field, deref a pointer, etc)
545 Projection(Box
<LvalueProjection
<'tcx
>>),
548 /// The `Projection` data structure defines things of the form `B.x`
549 /// or `*B` or `B[index]`. Note that it is parameterized because it is
550 /// shared between `Constant` and `Lvalue`. See the aliases
551 /// `LvalueProjection` etc below.
552 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
553 pub struct Projection
<'tcx
, B
, V
> {
555 pub elem
: ProjectionElem
<'tcx
, V
>,
558 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
559 pub enum ProjectionElem
<'tcx
, V
> {
561 Field(Field
, Ty
<'tcx
>),
564 /// These indices are generated by slice patterns. Easiest to explain
568 /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
569 /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
570 /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
571 /// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true },
574 /// index or -index (in Python terms), depending on from_end
576 /// thing being indexed must be at least this long
578 /// counting backwards from end?
582 /// "Downcast" to a variant of an ADT. Currently, we only introduce
583 /// this for ADTs with more than one variant. It may be better to
584 /// just introduce it always, or always for enums.
585 Downcast(AdtDef
<'tcx
>, usize),
588 /// Alias for projections as they appear in lvalues, where the base is an lvalue
589 /// and the index is an operand.
590 pub type LvalueProjection
<'tcx
> = Projection
<'tcx
, Lvalue
<'tcx
>, Operand
<'tcx
>>;
592 /// Alias for projections as they appear in lvalues, where the base is an lvalue
593 /// and the index is an operand.
594 pub type LvalueElem
<'tcx
> = ProjectionElem
<'tcx
, Operand
<'tcx
>>;
596 /// Index into the list of fields found in a `VariantDef`
597 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
598 pub struct Field(u32);
601 pub fn new(value
: usize) -> Field
{
602 assert
!(value
< (u32::MAX
) as usize);
606 pub fn index(self) -> usize {
611 impl<'tcx
> Lvalue
<'tcx
> {
612 pub fn field(self, f
: Field
, ty
: Ty
<'tcx
>) -> Lvalue
<'tcx
> {
613 self.elem(ProjectionElem
::Field(f
, ty
))
616 pub fn deref(self) -> Lvalue
<'tcx
> {
617 self.elem(ProjectionElem
::Deref
)
620 pub fn index(self, index
: Operand
<'tcx
>) -> Lvalue
<'tcx
> {
621 self.elem(ProjectionElem
::Index(index
))
624 pub fn elem(self, elem
: LvalueElem
<'tcx
>) -> Lvalue
<'tcx
> {
625 Lvalue
::Projection(Box
::new(LvalueProjection
{
632 impl<'tcx
> Debug
for Lvalue
<'tcx
> {
633 fn fmt(&self, fmt
: &mut Formatter
) -> fmt
::Result
{
638 write
!(fmt
, "var{:?}", id
),
640 write
!(fmt
, "arg{:?}", id
),
642 write
!(fmt
, "tmp{:?}", id
),
644 write
!(fmt
, "{}", ty
::tls
::with(|tcx
| tcx
.item_path_str(def_id
))),
646 write
!(fmt
, "return"),
647 Projection(ref data
) =>
649 ProjectionElem
::Downcast(ref adt_def
, index
) =>
650 write
!(fmt
, "({:?} as {})", data
.base
, adt_def
.variants
[index
].name
),
651 ProjectionElem
::Deref
=>
652 write
!(fmt
, "(*{:?})", data
.base
),
653 ProjectionElem
::Field(field
, ty
) =>
654 write
!(fmt
, "({:?}.{:?}: {:?})", data
.base
, field
.index(), ty
),
655 ProjectionElem
::Index(ref index
) =>
656 write
!(fmt
, "{:?}[{:?}]", data
.base
, index
),
657 ProjectionElem
::ConstantIndex { offset, min_length, from_end: false }
=>
658 write
!(fmt
, "{:?}[{:?} of {:?}]", data
.base
, offset
, min_length
),
659 ProjectionElem
::ConstantIndex { offset, min_length, from_end: true }
=>
660 write
!(fmt
, "{:?}[-{:?} of {:?}]", data
.base
, offset
, min_length
),
666 ///////////////////////////////////////////////////////////////////////////
669 impl Index
<ScopeId
> for Vec
<ScopeData
> {
670 type Output
= ScopeData
;
673 fn index(&self, index
: ScopeId
) -> &ScopeData
{
678 impl IndexMut
<ScopeId
> for Vec
<ScopeData
> {
680 fn index_mut(&mut self, index
: ScopeId
) -> &mut ScopeData
{
681 &mut self[index
.index()]
685 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
686 pub struct ScopeId(u32);
689 pub fn new(index
: usize) -> ScopeId
{
690 assert
!(index
< (u32::MAX
as usize));
691 ScopeId(index
as u32)
694 pub fn index(self) -> usize {
699 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
700 pub struct ScopeData
{
701 pub parent_scope
: Option
<ScopeId
>,
704 ///////////////////////////////////////////////////////////////////////////
707 /// These are values that can appear inside an rvalue (or an index
708 /// lvalue). They are intentionally limited to prevent rvalues from
709 /// being nested in one another.
710 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
711 pub enum Operand
<'tcx
> {
712 Consume(Lvalue
<'tcx
>),
713 Constant(Constant
<'tcx
>),
716 impl<'tcx
> Debug
for Operand
<'tcx
> {
717 fn fmt(&self, fmt
: &mut Formatter
) -> fmt
::Result
{
718 use self::Operand
::*;
720 Constant(ref a
) => write
!(fmt
, "{:?}", a
),
721 Consume(ref lv
) => write
!(fmt
, "{:?}", lv
),
726 ///////////////////////////////////////////////////////////////////////////
729 #[derive(Clone, RustcEncodable, RustcDecodable)]
730 pub enum Rvalue
<'tcx
> {
731 /// x (either a move or copy, depending on type of x)
735 Repeat(Operand
<'tcx
>, TypedConstVal
<'tcx
>),
738 Ref(Region
, BorrowKind
, Lvalue
<'tcx
>),
740 /// length of a [X] or [X;n] value
743 Cast(CastKind
, Operand
<'tcx
>, Ty
<'tcx
>),
745 BinaryOp(BinOp
, Operand
<'tcx
>, Operand
<'tcx
>),
747 UnaryOp(UnOp
, Operand
<'tcx
>),
749 /// Creates an *uninitialized* Box
752 /// Create an aggregate value, like a tuple or struct. This is
753 /// only needed because we want to distinguish `dest = Foo { x:
754 /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
755 /// that `Foo` has a destructor. These rvalues can be optimized
756 /// away after type-checking and before lowering.
757 Aggregate(AggregateKind
<'tcx
>, Vec
<Operand
<'tcx
>>),
759 /// Generates a slice of the form `&input[from_start..L-from_end]`
760 /// where `L` is the length of the slice. This is only created by
761 /// slice pattern matching, so e.g. a pattern of the form `[x, y,
762 /// .., z]` might create a slice with `from_start=2` and
772 outputs
: Vec
<Lvalue
<'tcx
>>,
773 inputs
: Vec
<Operand
<'tcx
>>
777 #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
781 /// Convert unique, zero-sized type for a fn to fn()
784 /// Convert safe fn() to unsafe fn()
787 /// "Unsize" -- convert a thin-or-fat pointer to a fat pointer.
788 /// trans must figure out the details once full monomorphization
789 /// is known. For example, this could be used to cast from a
790 /// `&[i32;N]` to a `&[i32]`, or a `Box<T>` to a `Box<Trait>`
791 /// (presuming `T: Trait`).
795 #[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
796 pub enum AggregateKind
<'tcx
> {
799 Adt(AdtDef
<'tcx
>, usize, &'tcx Substs
<'tcx
>),
800 Closure(DefId
, &'tcx ClosureSubsts
<'tcx
>),
803 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
805 /// The `+` operator (addition)
807 /// The `-` operator (subtraction)
809 /// The `*` operator (multiplication)
811 /// The `/` operator (division)
813 /// The `%` operator (modulus)
815 /// The `^` operator (bitwise xor)
817 /// The `&` operator (bitwise and)
819 /// The `|` operator (bitwise or)
821 /// The `<<` operator (shift left)
823 /// The `>>` operator (shift right)
825 /// The `==` operator (equality)
827 /// The `<` operator (less than)
829 /// The `<=` operator (less than or equal to)
831 /// The `!=` operator (not equal to)
833 /// The `>=` operator (greater than or equal to)
835 /// The `>` operator (greater than)
839 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
841 /// The `!` operator for logical inversion
843 /// The `-` operator for negation
847 impl<'tcx
> Debug
for Rvalue
<'tcx
> {
848 fn fmt(&self, fmt
: &mut Formatter
) -> fmt
::Result
{
852 Use(ref lvalue
) => write
!(fmt
, "{:?}", lvalue
),
853 Repeat(ref a
, ref b
) => write
!(fmt
, "[{:?}; {:?}]", a
, b
),
854 Len(ref a
) => write
!(fmt
, "Len({:?})", a
),
855 Cast(ref kind
, ref lv
, ref ty
) => write
!(fmt
, "{:?} as {:?} ({:?})", lv
, ty
, kind
),
856 BinaryOp(ref op
, ref a
, ref b
) => write
!(fmt
, "{:?}({:?}, {:?})", op
, a
, b
),
857 UnaryOp(ref op
, ref a
) => write
!(fmt
, "{:?}({:?})", op
, a
),
858 Box(ref t
) => write
!(fmt
, "Box({:?})", t
),
859 InlineAsm { ref asm, ref outputs, ref inputs }
=> {
860 write
!(fmt
, "asm!({:?} : {:?} : {:?})", asm
, outputs
, inputs
)
862 Slice { ref input, from_start, from_end }
=>
863 write
!(fmt
, "{:?}[{:?}..-{:?}]", input
, from_start
, from_end
),
865 Ref(_
, borrow_kind
, ref lv
) => {
866 let kind_str
= match borrow_kind
{
867 BorrowKind
::Shared
=> "",
868 BorrowKind
::Mut
| BorrowKind
::Unique
=> "mut ",
870 write
!(fmt
, "&{}{:?}", kind_str
, lv
)
873 Aggregate(ref kind
, ref lvs
) => {
874 use self::AggregateKind
::*;
876 fn fmt_tuple(fmt
: &mut Formatter
, lvs
: &[Operand
]) -> fmt
::Result
{
877 let mut tuple_fmt
= fmt
.debug_tuple("");
885 Vec
=> write
!(fmt
, "{:?}", lvs
),
889 0 => write
!(fmt
, "()"),
890 1 => write
!(fmt
, "({:?},)", lvs
[0]),
891 _
=> fmt_tuple(fmt
, lvs
),
895 Adt(adt_def
, variant
, substs
) => {
896 let variant_def
= &adt_def
.variants
[variant
];
898 ppaux
::parameterized(fmt
, substs
, variant_def
.did
,
899 ppaux
::Ns
::Value
, &[],
901 tcx
.lookup_item_type(variant_def
.did
).generics
904 match variant_def
.kind() {
905 ty
::VariantKind
::Unit
=> Ok(()),
906 ty
::VariantKind
::Tuple
=> fmt_tuple(fmt
, lvs
),
907 ty
::VariantKind
::Struct
=> {
908 let mut struct_fmt
= fmt
.debug_struct("");
909 for (field
, lv
) in variant_def
.fields
.iter().zip(lvs
) {
910 struct_fmt
.field(&field
.name
.as_str(), lv
);
917 Closure(def_id
, _
) => ty
::tls
::with(|tcx
| {
918 if let Some(node_id
) = tcx
.map
.as_local_node_id(def_id
) {
919 let name
= format
!("[closure@{:?}]", tcx
.map
.span(node_id
));
920 let mut struct_fmt
= fmt
.debug_struct(&name
);
922 tcx
.with_freevars(node_id
, |freevars
| {
923 for (freevar
, lv
) in freevars
.iter().zip(lvs
) {
924 let var_name
= tcx
.local_var_name_str(freevar
.def
.var_id());
925 struct_fmt
.field(&var_name
, lv
);
931 write
!(fmt
, "[closure]")
940 ///////////////////////////////////////////////////////////////////////////
943 /// Two constants are equal if they are the same constant. Note that
944 /// this does not necessarily mean that they are "==" in Rust -- in
945 /// particular one must be wary of `NaN`!
947 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
948 pub struct Constant
<'tcx
> {
951 pub literal
: Literal
<'tcx
>,
954 #[derive(Clone, RustcEncodable, RustcDecodable)]
955 pub struct TypedConstVal
<'tcx
> {
958 pub value
: ConstUsize
,
961 impl<'tcx
> Debug
for TypedConstVal
<'tcx
> {
962 fn fmt(&self, fmt
: &mut Formatter
) -> fmt
::Result
{
963 write
!(fmt
, "const {}", ConstInt
::Usize(self.value
))
967 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
968 pub enum Literal
<'tcx
> {
971 substs
: &'tcx Substs
<'tcx
>,
978 impl<'tcx
> Debug
for Constant
<'tcx
> {
979 fn fmt(&self, fmt
: &mut Formatter
) -> fmt
::Result
{
980 write
!(fmt
, "{:?}", self.literal
)
984 impl<'tcx
> Debug
for Literal
<'tcx
> {
985 fn fmt(&self, fmt
: &mut Formatter
) -> fmt
::Result
{
986 use self::Literal
::*;
988 Item { def_id, substs }
=> {
989 ppaux
::parameterized(fmt
, substs
, def_id
, ppaux
::Ns
::Value
, &[],
990 |tcx
| tcx
.lookup_item_type(def_id
).generics
)
992 Value { ref value }
=> {
993 write
!(fmt
, "const ")?
;
994 fmt_const_val(fmt
, value
)
1000 /// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
1001 fn fmt_const_val
<W
: Write
>(fmt
: &mut W
, const_val
: &ConstVal
) -> fmt
::Result
{
1002 use middle
::const_val
::ConstVal
::*;
1004 Float(f
) => write
!(fmt
, "{:?}", f
),
1005 Integral(n
) => write
!(fmt
, "{}", n
),
1006 Str(ref s
) => write
!(fmt
, "{:?}", s
),
1007 ByteStr(ref bytes
) => {
1008 let escaped
: String
= bytes
1010 .flat_map(|&ch
| ascii
::escape_default(ch
).map(|c
| c
as char))
1012 write
!(fmt
, "b\"{}\"", escaped
)
1014 Bool(b
) => write
!(fmt
, "{:?}", b
),
1015 Function(def_id
) => write
!(fmt
, "{}", item_path_str(def_id
)),
1016 Struct(node_id
) | Tuple(node_id
) | Array(node_id
, _
) | Repeat(node_id
, _
) =>
1017 write
!(fmt
, "{}", node_to_string(node_id
)),
1018 Char(c
) => write
!(fmt
, "{:?}", c
),
1023 fn node_to_string(node_id
: ast
::NodeId
) -> String
{
1024 ty
::tls
::with(|tcx
| tcx
.map
.node_to_user_string(node_id
))
1027 fn item_path_str(def_id
: DefId
) -> String
{
1028 ty
::tls
::with(|tcx
| tcx
.item_path_str(def_id
))