3 use rustc_index
::vec
::IndexVec
;
4 use rustc_middle
::mir
::visit
::{MutVisitor, PlaceContext, Visitor}
;
5 use rustc_middle
::mir
::{Body, Local, Location, VarDebugInfo}
;
6 use rustc_middle
::ty
::TyCtxt
;
9 pub struct DefUseAnalysis
{
10 info
: IndexVec
<Local
, Info
>,
15 // FIXME(eddyb) use smallvec where possible.
16 pub defs_and_uses
: Vec
<Use
>,
17 var_debug_info_indices
: Vec
<usize>,
22 pub context
: PlaceContext
,
23 pub location
: Location
,
27 pub fn new(body
: &Body
<'_
>) -> DefUseAnalysis
{
28 DefUseAnalysis { info: IndexVec::from_elem_n(Info::new(), body.local_decls.len()) }
31 pub fn analyze(&mut self, body
: &Body
<'_
>) {
34 let mut finder
= DefUseFinder
{
35 info
: mem
::take(&mut self.info
),
36 var_debug_info_index
: 0,
37 in_var_debug_info
: false,
39 finder
.visit_body(&body
);
40 self.info
= finder
.info
44 for info
in &mut self.info
{
49 pub fn local_info(&self, local
: Local
) -> &Info
{
53 fn mutate_defs_and_uses(
56 body
: &mut Body
<'tcx
>,
60 let mut visitor
= MutateUseVisitor
::new(local
, new_local
, tcx
);
61 let info
= &self.info
[local
];
62 for place_use
in &info
.defs_and_uses
{
63 visitor
.visit_location(body
, place_use
.location
)
65 // Update debuginfo as well, alongside defs/uses.
66 for &i
in &info
.var_debug_info_indices
{
67 visitor
.visit_var_debug_info(&mut body
.var_debug_info
[i
]);
71 // FIXME(pcwalton): this should update the def-use chains.
72 pub fn replace_all_defs_and_uses_with(
75 body
: &mut Body
<'tcx
>,
79 self.mutate_defs_and_uses(local
, body
, new_local
, tcx
)
84 info
: IndexVec
<Local
, Info
>,
85 var_debug_info_index
: usize,
86 in_var_debug_info
: bool
,
89 impl Visitor
<'_
> for DefUseFinder
{
90 fn visit_local(&mut self, &local
: &Local
, context
: PlaceContext
, location
: Location
) {
91 let info
= &mut self.info
[local
];
92 if self.in_var_debug_info
{
93 info
.var_debug_info_indices
.push(self.var_debug_info_index
);
95 info
.defs_and_uses
.push(Use { context, location }
);
98 fn visit_var_debug_info(&mut self, var_debug_info
: &VarDebugInfo
<'tcx
>) {
99 assert
!(!self.in_var_debug_info
);
100 self.in_var_debug_info
= true;
101 self.super_var_debug_info(var_debug_info
);
102 self.in_var_debug_info
= false;
103 self.var_debug_info_index
+= 1;
109 Info { defs_and_uses: vec![], var_debug_info_indices: vec![] }
112 fn clear(&mut self) {
113 self.defs_and_uses
.clear();
114 self.var_debug_info_indices
.clear();
117 pub fn def_count(&self) -> usize {
118 self.defs_and_uses
.iter().filter(|place_use
| place_use
.context
.is_mutating_use()).count()
121 pub fn def_count_not_including_drop(&self) -> usize {
122 self.defs_not_including_drop().count()
125 pub fn defs_not_including_drop(&self) -> impl Iterator
<Item
= &Use
> {
128 .filter(|place_use
| place_use
.context
.is_mutating_use() && !place_use
.context
.is_drop())
131 pub fn use_count(&self) -> usize {
132 self.defs_and_uses
.iter().filter(|place_use
| place_use
.context
.is_nonmutating_use()).count()
136 struct MutateUseVisitor
<'tcx
> {
142 impl MutateUseVisitor
<'tcx
> {
143 fn new(query
: Local
, new_local
: Local
, tcx
: TyCtxt
<'tcx
>) -> MutateUseVisitor
<'tcx
> {
144 MutateUseVisitor { query, new_local, tcx }
148 impl MutVisitor
<'tcx
> for MutateUseVisitor
<'tcx
> {
149 fn tcx(&self) -> TyCtxt
<'tcx
> {
153 fn visit_local(&mut self, local
: &mut Local
, _context
: PlaceContext
, _location
: Location
) {
154 if *local
== self.query
{
155 *local
= self.new_local
;