]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/build/expr/as_lvalue.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_mir / build / expr / as_lvalue.rs
CommitLineData
e9174d1e
SL
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
92a42be0 13use build::{BlockAnd, BlockAndExtension, Builder};
e9174d1e
SL
14use build::expr::category::Category;
15use hair::*;
92a42be0 16use rustc::mir::repr::*;
e9174d1e 17
b039eaaf 18impl<'a,'tcx> Builder<'a,'tcx> {
e9174d1e
SL
19 /// Compile `expr`, yielding an lvalue that we can move from etc.
20 pub fn as_lvalue<M>(&mut self,
21 block: BasicBlock,
22 expr: M)
b039eaaf
SL
23 -> BlockAnd<Lvalue<'tcx>>
24 where M: Mirror<'tcx, Output=Expr<'tcx>>
e9174d1e
SL
25 {
26 let expr = self.hir.mirror(expr);
27 self.expr_as_lvalue(block, expr)
28 }
29
30 fn expr_as_lvalue(&mut self,
31 mut block: BasicBlock,
b039eaaf
SL
32 expr: Expr<'tcx>)
33 -> BlockAnd<Lvalue<'tcx>> {
34 debug!("expr_as_lvalue(block={:?}, expr={:?})", block, expr);
e9174d1e
SL
35
36 let this = self;
54a0048b 37 let scope_id = this.innermost_scope_id();
e9174d1e
SL
38 let expr_span = expr.span;
39 match expr.kind {
40 ExprKind::Scope { extent, value } => {
54a0048b 41 this.in_scope(extent, block, |this, _| this.as_lvalue(block, value))
e9174d1e
SL
42 }
43 ExprKind::Field { lhs, name } => {
44 let lvalue = unpack!(block = this.as_lvalue(block, lhs));
7453a54e 45 let lvalue = lvalue.field(name, expr.ty);
e9174d1e
SL
46 block.and(lvalue)
47 }
48 ExprKind::Deref { arg } => {
49 let lvalue = unpack!(block = this.as_lvalue(block, arg));
50 let lvalue = lvalue.deref();
51 block.and(lvalue)
52 }
53 ExprKind::Index { lhs, index } => {
54 let (usize_ty, bool_ty) = (this.hir.usize_ty(), this.hir.bool_ty());
55
56 let slice = unpack!(block = this.as_lvalue(block, lhs));
57
58 let idx = unpack!(block = this.as_operand(block, index));
59
60 // bounds check:
61 let (len, lt) = (this.temp(usize_ty.clone()), this.temp(bool_ty));
54a0048b 62 this.cfg.push_assign(block, scope_id, expr_span, // len = len(slice)
e9174d1e 63 &len, Rvalue::Len(slice.clone()));
54a0048b 64 this.cfg.push_assign(block, scope_id, expr_span, // lt = idx < len
e9174d1e
SL
65 &lt, Rvalue::BinaryOp(BinOp::Lt,
66 idx.clone(),
9cc50fc6 67 Operand::Consume(len.clone())));
e9174d1e 68
b039eaaf 69 let (success, failure) = (this.cfg.start_new_block(), this.cfg.start_new_block());
e9174d1e 70 this.cfg.terminate(block,
54a0048b
SL
71 scope_id,
72 expr_span,
73 TerminatorKind::If {
e9174d1e 74 cond: Operand::Consume(lt),
9cc50fc6 75 targets: (success, failure),
e9174d1e 76 });
9cc50fc6 77 this.panic_bounds_check(failure, idx.clone(), Operand::Consume(len), expr_span);
e9174d1e
SL
78 success.and(slice.index(idx))
79 }
80 ExprKind::SelfRef => {
81 block.and(Lvalue::Arg(0))
82 }
83 ExprKind::VarRef { id } => {
84 let index = this.var_indices[&id];
85 block.and(Lvalue::Var(index))
86 }
87 ExprKind::StaticRef { id } => {
88 block.and(Lvalue::Static(id))
89 }
90
91 ExprKind::Vec { .. } |
92 ExprKind::Tuple { .. } |
93 ExprKind::Adt { .. } |
94 ExprKind::Closure { .. } |
95 ExprKind::Unary { .. } |
96 ExprKind::Binary { .. } |
97 ExprKind::LogicalOp { .. } |
98 ExprKind::Box { .. } |
99 ExprKind::Cast { .. } |
100 ExprKind::ReifyFnPointer { .. } |
101 ExprKind::UnsafeFnPointer { .. } |
102 ExprKind::Unsize { .. } |
103 ExprKind::Repeat { .. } |
104 ExprKind::Borrow { .. } |
105 ExprKind::If { .. } |
106 ExprKind::Match { .. } |
107 ExprKind::Loop { .. } |
108 ExprKind::Block { .. } |
109 ExprKind::Assign { .. } |
110 ExprKind::AssignOp { .. } |
111 ExprKind::Break { .. } |
112 ExprKind::Continue { .. } |
113 ExprKind::Return { .. } |
114 ExprKind::Literal { .. } |
115 ExprKind::InlineAsm { .. } |
116 ExprKind::Call { .. } => {
117 // these are not lvalues, so we need to make a temporary.
118 debug_assert!(match Category::of(&expr.kind) {
119 Some(Category::Lvalue) => false,
120 _ => true,
121 });
122 this.as_temp(block, expr)
123 }
124 }
125 }
126}