]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/trans/mir/analyze.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / librustc_trans / trans / mir / analyze.rs
CommitLineData
92a42be0
SL
1// Copyright 2012-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.
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//! An analysis to determine which temporaries require allocas and
12//! which do not.
13
7453a54e 14use rustc_data_structures::bitvec::BitVector;
92a42be0
SL
15use rustc::mir::repr as mir;
16use rustc::mir::visit::{Visitor, LvalueContext};
17use trans::common::{self, Block};
18use super::rvalue;
19
20pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>,
21 mir: &mir::Mir<'tcx>)
7453a54e
SL
22 -> BitVector {
23 let mut analyzer = TempAnalyzer::new(mir.temp_decls.len());
92a42be0
SL
24
25 analyzer.visit_mir(mir);
26
27 for (index, temp_decl) in mir.temp_decls.iter().enumerate() {
28 let ty = bcx.monomorphize(&temp_decl.ty);
29 debug!("temp {:?} has type {:?}", index, ty);
30 if ty.is_scalar() ||
31 ty.is_unique() ||
32 ty.is_region_ptr() ||
33 ty.is_simd()
34 {
35 // These sorts of types are immediates that we can store
36 // in an ValueRef without an alloca.
37 assert!(common::type_is_immediate(bcx.ccx(), ty) ||
38 common::type_is_fat_ptr(bcx.tcx(), ty));
39 } else {
40 // These sorts of types require an alloca. Note that
41 // type_is_immediate() may *still* be true, particularly
42 // for newtypes, but we currently force some types
43 // (e.g. structs) into an alloca unconditionally, just so
44 // that we don't have to deal with having two pathways
45 // (gep vs extractvalue etc).
46 analyzer.mark_as_lvalue(index);
47 }
48 }
49
50 analyzer.lvalue_temps
51}
52
53struct TempAnalyzer {
7453a54e
SL
54 lvalue_temps: BitVector,
55 seen_assigned: BitVector
92a42be0
SL
56}
57
58impl TempAnalyzer {
7453a54e
SL
59 fn new(temp_count: usize) -> TempAnalyzer {
60 TempAnalyzer {
61 lvalue_temps: BitVector::new(temp_count),
62 seen_assigned: BitVector::new(temp_count)
63 }
92a42be0
SL
64 }
65
66 fn mark_as_lvalue(&mut self, temp: usize) {
67 debug!("marking temp {} as lvalue", temp);
68 self.lvalue_temps.insert(temp);
69 }
7453a54e
SL
70
71 fn mark_assigned(&mut self, temp: usize) {
72 if !self.seen_assigned.insert(temp) {
73 self.mark_as_lvalue(temp);
74 }
75 }
92a42be0
SL
76}
77
78impl<'tcx> Visitor<'tcx> for TempAnalyzer {
79 fn visit_assign(&mut self,
80 block: mir::BasicBlock,
81 lvalue: &mir::Lvalue<'tcx>,
82 rvalue: &mir::Rvalue<'tcx>) {
83 debug!("visit_assign(block={:?}, lvalue={:?}, rvalue={:?})", block, lvalue, rvalue);
84
85 match *lvalue {
86 mir::Lvalue::Temp(index) => {
7453a54e 87 self.mark_assigned(index as usize);
92a42be0
SL
88 if !rvalue::rvalue_creates_operand(rvalue) {
89 self.mark_as_lvalue(index as usize);
90 }
91 }
92 _ => {
93 self.visit_lvalue(lvalue, LvalueContext::Store);
94 }
95 }
96
97 self.visit_rvalue(rvalue);
98 }
99
100 fn visit_lvalue(&mut self,
101 lvalue: &mir::Lvalue<'tcx>,
102 context: LvalueContext) {
103 debug!("visit_lvalue(lvalue={:?}, context={:?})", lvalue, context);
104
105 match *lvalue {
106 mir::Lvalue::Temp(index) => {
107 match context {
108 LvalueContext::Consume => {
109 }
110 LvalueContext::Store |
111 LvalueContext::Drop |
112 LvalueContext::Inspect |
113 LvalueContext::Borrow { .. } |
114 LvalueContext::Slice { .. } |
115 LvalueContext::Projection => {
116 self.mark_as_lvalue(index as usize);
117 }
118 }
119 }
120 _ => {
121 }
122 }
123
124 self.super_lvalue(lvalue, context);
125 }
126}