]>
git.proxmox.com Git - rustc.git/blob - 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.
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.
11 //! An analysis to determine which temporaries require allocas and
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}
;
20 pub fn lvalue_temps
<'bcx
,'tcx
>(bcx
: Block
<'bcx
,'tcx
>,
23 let mut analyzer
= TempAnalyzer
::new(mir
.temp_decls
.len());
25 analyzer
.visit_mir(mir
);
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
);
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
));
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
);
54 lvalue_temps
: BitVector
,
55 seen_assigned
: BitVector
59 fn new(temp_count
: usize) -> TempAnalyzer
{
61 lvalue_temps
: BitVector
::new(temp_count
),
62 seen_assigned
: BitVector
::new(temp_count
)
66 fn mark_as_lvalue(&mut self, temp
: usize) {
67 debug
!("marking temp {} as lvalue", temp
);
68 self.lvalue_temps
.insert(temp
);
71 fn mark_assigned(&mut self, temp
: usize) {
72 if !self.seen_assigned
.insert(temp
) {
73 self.mark_as_lvalue(temp
);
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
);
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);
93 self.visit_lvalue(lvalue
, LvalueContext
::Store
);
97 self.visit_rvalue(rvalue
);
100 fn visit_lvalue(&mut self,
101 lvalue
: &mir
::Lvalue
<'tcx
>,
102 context
: LvalueContext
) {
103 debug
!("visit_lvalue(lvalue={:?}, context={:?})", lvalue
, context
);
106 mir
::Lvalue
::Temp(index
) => {
108 LvalueContext
::Call
=> {
109 self.mark_assigned(index
as usize);
111 LvalueContext
::Consume
=> {
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);
127 self.super_lvalue(lvalue
, context
);