]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/build/expr/as_operand.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc_mir / build / expr / as_operand.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 //! See docs in build/expr/mod.rs
12
13 use build::{BlockAnd, BlockAndExtension, Builder};
14 use build::expr::category::Category;
15 use hair::*;
16 use rustc::middle::region::CodeExtent;
17 use rustc::mir::*;
18
19 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
20 /// Returns an operand suitable for use until the end of the current
21 /// scope expression.
22 ///
23 /// The operand returned from this function will *not be valid* after
24 /// an ExprKind::Scope is passed, so please do *not* return it from
25 /// functions to avoid bad miscompiles.
26 pub fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M)
27 -> BlockAnd<Operand<'tcx>>
28 where M: Mirror<'tcx, Output = Expr<'tcx>>
29 {
30 let topmost_scope = self.topmost_scope(); // FIXME(#6393)
31 self.as_operand(block, Some(topmost_scope), expr)
32 }
33
34 /// Compile `expr` into a value that can be used as an operand.
35 /// If `expr` is an lvalue like `x`, this will introduce a
36 /// temporary `tmp = x`, so that we capture the value of `x` at
37 /// this time.
38 ///
39 /// The operand is known to be live until the end of `scope`.
40 pub fn as_operand<M>(&mut self,
41 block: BasicBlock,
42 scope: Option<CodeExtent>,
43 expr: M) -> BlockAnd<Operand<'tcx>>
44 where M: Mirror<'tcx, Output = Expr<'tcx>>
45 {
46 let expr = self.hir.mirror(expr);
47 self.expr_as_operand(block, scope, expr)
48 }
49
50 fn expr_as_operand(&mut self,
51 mut block: BasicBlock,
52 scope: Option<CodeExtent>,
53 expr: Expr<'tcx>)
54 -> BlockAnd<Operand<'tcx>> {
55 debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
56 let this = self;
57
58 if let ExprKind::Scope { extent, value } = expr.kind {
59 return this.in_scope(extent, block, |this| {
60 this.as_operand(block, scope, value)
61 });
62 }
63
64 let category = Category::of(&expr.kind).unwrap();
65 debug!("expr_as_operand: category={:?} for={:?}", category, expr.kind);
66 match category {
67 Category::Constant => {
68 let constant = this.as_constant(expr);
69 block.and(Operand::Constant(constant))
70 }
71 Category::Lvalue |
72 Category::Rvalue(..) => {
73 let operand =
74 unpack!(block = this.as_temp(block, scope, expr));
75 block.and(Operand::Consume(operand))
76 }
77 }
78 }
79 }