]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | //! See docs in build/expr/mod.rs |
2 | ||
e9174d1e | 3 | use build::expr::category::Category; |
b7449926 | 4 | use build::{BlockAnd, BlockAndExtension, Builder}; |
e9174d1e | 5 | use hair::*; |
ea8adc8c | 6 | use rustc::middle::region; |
c30ab7b3 | 7 | use rustc::mir::*; |
e9174d1e | 8 | |
a7813a04 | 9 | impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { |
8bb4bdeb XL |
10 | /// Returns an operand suitable for use until the end of the current |
11 | /// scope expression. | |
12 | /// | |
13 | /// The operand returned from this function will *not be valid* after | |
14 | /// an ExprKind::Scope is passed, so please do *not* return it from | |
15 | /// functions to avoid bad miscompiles. | |
b7449926 XL |
16 | pub fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>> |
17 | where | |
18 | M: Mirror<'tcx, Output = Expr<'tcx>>, | |
8bb4bdeb | 19 | { |
7cac9316 XL |
20 | let local_scope = self.local_scope(); |
21 | self.as_operand(block, local_scope, expr) | |
8bb4bdeb XL |
22 | } |
23 | ||
e9174d1e | 24 | /// Compile `expr` into a value that can be used as an operand. |
ff7c6d11 | 25 | /// If `expr` is a place like `x`, this will introduce a |
e9174d1e SL |
26 | /// temporary `tmp = x`, so that we capture the value of `x` at |
27 | /// this time. | |
8bb4bdeb XL |
28 | /// |
29 | /// The operand is known to be live until the end of `scope`. | |
b7449926 XL |
30 | pub fn as_operand<M>( |
31 | &mut self, | |
32 | block: BasicBlock, | |
33 | scope: Option<region::Scope>, | |
34 | expr: M, | |
35 | ) -> BlockAnd<Operand<'tcx>> | |
36 | where | |
37 | M: Mirror<'tcx, Output = Expr<'tcx>>, | |
e9174d1e SL |
38 | { |
39 | let expr = self.hir.mirror(expr); | |
8bb4bdeb | 40 | self.expr_as_operand(block, scope, expr) |
e9174d1e SL |
41 | } |
42 | ||
b7449926 XL |
43 | fn expr_as_operand( |
44 | &mut self, | |
45 | mut block: BasicBlock, | |
46 | scope: Option<region::Scope>, | |
47 | expr: Expr<'tcx>, | |
48 | ) -> BlockAnd<Operand<'tcx>> { | |
b039eaaf | 49 | debug!("expr_as_operand(block={:?}, expr={:?})", block, expr); |
e9174d1e SL |
50 | let this = self; |
51 | ||
b7449926 XL |
52 | if let ExprKind::Scope { |
53 | region_scope, | |
54 | lint_level, | |
55 | value, | |
56 | } = expr.kind | |
57 | { | |
041b39d2 | 58 | let source_info = this.source_info(expr.span); |
ea8adc8c XL |
59 | let region_scope = (region_scope, source_info); |
60 | return this.in_scope(region_scope, lint_level, block, |this| { | |
8bb4bdeb XL |
61 | this.as_operand(block, scope, value) |
62 | }); | |
e9174d1e SL |
63 | } |
64 | ||
65 | let category = Category::of(&expr.kind).unwrap(); | |
b7449926 XL |
66 | debug!( |
67 | "expr_as_operand: category={:?} for={:?}", | |
68 | category, expr.kind | |
69 | ); | |
e9174d1e SL |
70 | match category { |
71 | Category::Constant => { | |
72 | let constant = this.as_constant(expr); | |
cc61c64b | 73 | block.and(Operand::Constant(box constant)) |
e9174d1e | 74 | } |
b7449926 XL |
75 | Category::Place | Category::Rvalue(..) => { |
76 | let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut)); | |
ff7c6d11 | 77 | block.and(Operand::Move(Place::Local(operand))) |
e9174d1e SL |
78 | } |
79 | } | |
80 | } | |
81 | } |