]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/util/def_use.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / librustc_mir / util / def_use.rs
CommitLineData
9e0c209e
SL
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//! Def-use analysis.
12
ea8adc8c 13use rustc::mir::{Local, Location, Mir};
9e0c209e 14use rustc::mir::visit::{LvalueContext, MutVisitor, Visitor};
c30ab7b3 15use rustc_data_structures::indexed_vec::IndexVec;
9e0c209e
SL
16use std::marker::PhantomData;
17use std::mem;
abe05a73
XL
18use std::slice;
19use std::iter;
9e0c209e
SL
20
21pub struct DefUseAnalysis<'tcx> {
22 info: IndexVec<Local, Info<'tcx>>,
9e0c209e
SL
23}
24
25#[derive(Clone)]
26pub struct Info<'tcx> {
27 pub defs_and_uses: Vec<Use<'tcx>>,
28}
29
30#[derive(Clone)]
31pub struct Use<'tcx> {
32 pub context: LvalueContext<'tcx>,
33 pub location: Location,
34}
35
36impl<'tcx> DefUseAnalysis<'tcx> {
37 pub fn new(mir: &Mir<'tcx>) -> DefUseAnalysis<'tcx> {
38 DefUseAnalysis {
c30ab7b3 39 info: IndexVec::from_elem_n(Info::new(), mir.local_decls.len()),
9e0c209e
SL
40 }
41 }
42
43 pub fn analyze(&mut self, mir: &Mir<'tcx>) {
abe05a73
XL
44 self.clear();
45
9e0c209e
SL
46 let mut finder = DefUseFinder {
47 info: mem::replace(&mut self.info, IndexVec::new()),
9e0c209e
SL
48 };
49 finder.visit_mir(mir);
50 self.info = finder.info
51 }
52
abe05a73
XL
53 fn clear(&mut self) {
54 for info in &mut self.info {
55 info.clear();
56 }
57 }
58
9e0c209e
SL
59 pub fn local_info(&self, local: Local) -> &Info<'tcx> {
60 &self.info[local]
61 }
62
9e0c209e 63 fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Mir<'tcx>, mut callback: F)
ea8adc8c 64 where F: for<'a> FnMut(&'a mut Local,
9e0c209e
SL
65 LvalueContext<'tcx>,
66 Location) {
67 for lvalue_use in &self.info[local].defs_and_uses {
68 MutateUseVisitor::new(local,
69 &mut callback,
9e0c209e
SL
70 mir).visit_location(mir, lvalue_use.location)
71 }
72 }
73
74 /// FIXME(pcwalton): This should update the def-use chains.
75 pub fn replace_all_defs_and_uses_with(&self,
76 local: Local,
77 mir: &mut Mir<'tcx>,
ea8adc8c
XL
78 new_local: Local) {
79 self.mutate_defs_and_uses(local, mir, |local, _, _| *local = new_local)
9e0c209e
SL
80 }
81}
82
83struct DefUseFinder<'tcx> {
84 info: IndexVec<Local, Info<'tcx>>,
9e0c209e
SL
85}
86
9e0c209e 87impl<'tcx> Visitor<'tcx> for DefUseFinder<'tcx> {
ea8adc8c
XL
88 fn visit_local(&mut self,
89 &local: &Local,
90 context: LvalueContext<'tcx>,
91 location: Location) {
92 self.info[local].defs_and_uses.push(Use {
93 context,
94 location,
95 });
9e0c209e
SL
96 }
97}
98
99impl<'tcx> Info<'tcx> {
100 fn new() -> Info<'tcx> {
101 Info {
102 defs_and_uses: vec![],
103 }
104 }
105
abe05a73
XL
106 fn clear(&mut self) {
107 self.defs_and_uses.clear();
108 }
109
9e0c209e
SL
110 pub fn def_count(&self) -> usize {
111 self.defs_and_uses.iter().filter(|lvalue_use| lvalue_use.context.is_mutating_use()).count()
112 }
113
114 pub fn def_count_not_including_drop(&self) -> usize {
abe05a73
XL
115 self.defs_not_including_drop().count()
116 }
117
118 pub fn defs_not_including_drop(
119 &self,
120 ) -> iter::Filter<slice::Iter<Use<'tcx>>, fn(&&Use<'tcx>) -> bool> {
9e0c209e
SL
121 self.defs_and_uses.iter().filter(|lvalue_use| {
122 lvalue_use.context.is_mutating_use() && !lvalue_use.context.is_drop()
abe05a73 123 })
9e0c209e
SL
124 }
125
126 pub fn use_count(&self) -> usize {
127 self.defs_and_uses.iter().filter(|lvalue_use| {
128 lvalue_use.context.is_nonmutating_use()
129 }).count()
130 }
131}
132
133struct MutateUseVisitor<'tcx, F> {
134 query: Local,
135 callback: F,
9e0c209e
SL
136 phantom: PhantomData<&'tcx ()>,
137}
138
139impl<'tcx, F> MutateUseVisitor<'tcx, F> {
c30ab7b3 140 fn new(query: Local, callback: F, _: &Mir<'tcx>)
9e0c209e 141 -> MutateUseVisitor<'tcx, F>
ea8adc8c 142 where F: for<'a> FnMut(&'a mut Local, LvalueContext<'tcx>, Location) {
9e0c209e 143 MutateUseVisitor {
3b2f2976
XL
144 query,
145 callback,
9e0c209e
SL
146 phantom: PhantomData,
147 }
148 }
149}
150
151impl<'tcx, F> MutVisitor<'tcx> for MutateUseVisitor<'tcx, F>
ea8adc8c
XL
152 where F: for<'a> FnMut(&'a mut Local, LvalueContext<'tcx>, Location) {
153 fn visit_local(&mut self,
154 local: &mut Local,
9e0c209e
SL
155 context: LvalueContext<'tcx>,
156 location: Location) {
ea8adc8c
XL
157 if *local == self.query {
158 (self.callback)(local, context, location)
9e0c209e
SL
159 }
160 }
161}