]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans/mir/analyze.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_trans / mir / analyze.rs
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
14 use rustc_data_structures::bitvec::BitVector;
15 use rustc::mir::repr as mir;
16 use rustc::mir::visit::{Visitor, LvalueContext};
17 use common::{self, Block};
18 use super::rvalue;
19
20 pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>,
21 mir: &mir::Mir<'tcx>)
22 -> BitVector {
23 let mut analyzer = TempAnalyzer::new(mir.temp_decls.len());
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
53 struct TempAnalyzer {
54 lvalue_temps: BitVector,
55 seen_assigned: BitVector
56 }
57
58 impl TempAnalyzer {
59 fn new(temp_count: usize) -> TempAnalyzer {
60 TempAnalyzer {
61 lvalue_temps: BitVector::new(temp_count),
62 seen_assigned: BitVector::new(temp_count)
63 }
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 }
70
71 fn mark_assigned(&mut self, temp: usize) {
72 if !self.seen_assigned.insert(temp) {
73 self.mark_as_lvalue(temp);
74 }
75 }
76 }
77
78 impl<'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) => {
87 self.mark_assigned(index as usize);
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::Call => {
109 self.mark_assigned(index as usize);
110 }
111 LvalueContext::Consume => {
112 }
113 LvalueContext::Store |
114 LvalueContext::Drop |
115 LvalueContext::Inspect |
116 LvalueContext::Borrow { .. } |
117 LvalueContext::Slice { .. } |
118 LvalueContext::Projection => {
119 self.mark_as_lvalue(index as usize);
120 }
121 }
122 }
123 _ => {
124 }
125 }
126
127 self.super_lvalue(lvalue, context);
128 }
129 }