]>
Commit | Line | Data |
---|---|---|
a7813a04 XL |
1 | // Copyright 2016 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 | use build::{BlockAnd, BlockAndExtension, Builder}; | |
12 | use build::scope::LoopScope; | |
13 | use hair::*; | |
c30ab7b3 | 14 | use rustc::mir::*; |
a7813a04 XL |
15 | |
16 | impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { | |
17 | ||
18 | pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<()> { | |
19 | let this = self; | |
20 | let expr_span = expr.span; | |
3157f602 | 21 | let source_info = this.source_info(expr.span); |
a7813a04 XL |
22 | // Handle a number of expressions that don't need a destination at all. This |
23 | // avoids needing a mountain of temporary `()` variables. | |
24 | match expr.kind { | |
25 | ExprKind::Scope { extent, value } => { | |
26 | let value = this.hir.mirror(value); | |
3157f602 | 27 | this.in_scope(extent, block, |this| this.stmt_expr(block, value)) |
a7813a04 XL |
28 | } |
29 | ExprKind::Assign { lhs, rhs } => { | |
30 | let lhs = this.hir.mirror(lhs); | |
31 | let rhs = this.hir.mirror(rhs); | |
a7813a04 XL |
32 | let lhs_span = lhs.span; |
33 | ||
a7813a04 XL |
34 | // Note: we evaluate assignments right-to-left. This |
35 | // is better for borrowck interaction with overloaded | |
36 | // operators like x[j] = x[i]. | |
37 | ||
38 | // Generate better code for things that don't need to be | |
39 | // dropped. | |
3157f602 | 40 | if this.hir.needs_drop(lhs.ty) { |
8bb4bdeb | 41 | let rhs = unpack!(block = this.as_local_operand(block, rhs)); |
3157f602 XL |
42 | let lhs = unpack!(block = this.as_lvalue(block, lhs)); |
43 | unpack!(block = this.build_drop_and_replace( | |
44 | block, lhs_span, lhs, rhs | |
45 | )); | |
46 | block.unit() | |
a7813a04 | 47 | } else { |
8bb4bdeb | 48 | let rhs = unpack!(block = this.as_local_rvalue(block, rhs)); |
3157f602 XL |
49 | let lhs = unpack!(block = this.as_lvalue(block, lhs)); |
50 | this.cfg.push_assign(block, source_info, &lhs, rhs); | |
51 | block.unit() | |
52 | } | |
a7813a04 XL |
53 | } |
54 | ExprKind::AssignOp { op, lhs, rhs } => { | |
55 | // FIXME(#28160) there is an interesting semantics | |
56 | // question raised here -- should we "freeze" the | |
57 | // value of the lhs here? I'm inclined to think not, | |
58 | // since it seems closer to the semantics of the | |
59 | // overloaded version, which takes `&mut self`. This | |
60 | // only affects weird things like `x += {x += 1; x}` | |
61 | // -- is that equal to `x + (x + 1)` or `2*(x+1)`? | |
62 | ||
3157f602 XL |
63 | let lhs = this.hir.mirror(lhs); |
64 | let lhs_ty = lhs.ty; | |
65 | ||
a7813a04 | 66 | // As above, RTL. |
8bb4bdeb | 67 | let rhs = unpack!(block = this.as_local_operand(block, rhs)); |
a7813a04 XL |
68 | let lhs = unpack!(block = this.as_lvalue(block, lhs)); |
69 | ||
70 | // we don't have to drop prior contents or anything | |
71 | // because AssignOp is only legal for Copy types | |
72 | // (overloaded ops should be desugared into a call). | |
3157f602 XL |
73 | let result = unpack!(block = this.build_binary_op(block, op, expr_span, lhs_ty, |
74 | Operand::Consume(lhs.clone()), rhs)); | |
75 | this.cfg.push_assign(block, source_info, &lhs, result); | |
a7813a04 XL |
76 | |
77 | block.unit() | |
78 | } | |
79 | ExprKind::Continue { label } => { | |
476ff2be SL |
80 | let LoopScope { continue_block, extent, .. } = |
81 | *this.find_loop_scope(expr_span, label); | |
82 | this.exit_scope(expr_span, extent, block, continue_block); | |
83 | this.cfg.start_new_block().unit() | |
a7813a04 | 84 | } |
476ff2be SL |
85 | ExprKind::Break { label, value } => { |
86 | let (break_block, extent, destination) = { | |
87 | let LoopScope { | |
88 | break_block, | |
89 | extent, | |
90 | ref break_destination, | |
91 | .. | |
92 | } = *this.find_loop_scope(expr_span, label); | |
93 | (break_block, extent, break_destination.clone()) | |
94 | }; | |
95 | if let Some(value) = value { | |
96 | unpack!(block = this.into(&destination, block, value)) | |
97 | } else { | |
98 | this.cfg.push_assign_unit(block, source_info, &destination) | |
99 | } | |
100 | this.exit_scope(expr_span, extent, block, break_block); | |
101 | this.cfg.start_new_block().unit() | |
a7813a04 XL |
102 | } |
103 | ExprKind::Return { value } => { | |
104 | block = match value { | |
c30ab7b3 SL |
105 | Some(value) => { |
106 | unpack!(this.into(&Lvalue::Local(RETURN_POINTER), block, value)) | |
107 | } | |
a7813a04 | 108 | None => { |
c30ab7b3 SL |
109 | this.cfg.push_assign_unit(block, |
110 | source_info, | |
111 | &Lvalue::Local(RETURN_POINTER)); | |
a7813a04 XL |
112 | block |
113 | } | |
114 | }; | |
115 | let extent = this.extent_of_return_scope(); | |
116 | let return_block = this.return_block(); | |
117 | this.exit_scope(expr_span, extent, block, return_block); | |
118 | this.cfg.start_new_block().unit() | |
119 | } | |
8bb4bdeb XL |
120 | ExprKind::InlineAsm { asm, outputs, inputs } => { |
121 | let outputs = outputs.into_iter().map(|output| { | |
122 | unpack!(block = this.as_lvalue(block, output)) | |
123 | }).collect(); | |
124 | let inputs = inputs.into_iter().map(|input| { | |
125 | unpack!(block = this.as_local_operand(block, input)) | |
126 | }).collect(); | |
127 | this.cfg.push(block, Statement { | |
128 | source_info: source_info, | |
129 | kind: StatementKind::InlineAsm { | |
130 | asm: asm.clone(), | |
131 | outputs: outputs, | |
132 | inputs: inputs | |
133 | }, | |
134 | }); | |
135 | block.unit() | |
136 | } | |
a7813a04 | 137 | _ => { |
a7813a04 XL |
138 | let expr_ty = expr.ty; |
139 | let temp = this.temp(expr.ty.clone()); | |
140 | unpack!(block = this.into(&temp, block, expr)); | |
141 | unpack!(block = this.build_drop(block, expr_span, temp, expr_ty)); | |
142 | block.unit() | |
143 | } | |
144 | } | |
145 | } | |
146 | ||
a7813a04 | 147 | } |