1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use crate::analysis::{use_def, LocationSet};
use crate::error::*;
use crate::ir;
use std::collections::HashMap;
pub fn variable_use_def<'f, V: ir::Value>(
function: &'f ir::Function<V>,
) -> Result<HashMap<ir::ProgramLocation, HashMap<ir::Variable, LocationSet>>> {
variable_use_def_ud(function, &use_def(function)?)
}
pub fn variable_use_def_ud<'f, V: ir::Value>(
function: &'f ir::Function<V>,
ud: &HashMap<ir::ProgramLocation, LocationSet>,
) -> Result<HashMap<ir::ProgramLocation, HashMap<ir::Variable, LocationSet>>> {
let mut result: HashMap<ir::ProgramLocation, HashMap<ir::Variable, LocationSet>> =
HashMap::new();
for location in function.program_locations() {
let variables = location
.instruction()
.map(|instruction| instruction.variables_read())
.unwrap_or(
location
.edge()
.and_then(|edge| edge.condition().map(|c| c.variables())),
);
let variables = match variables {
Some(variables) => variables,
None => continue,
};
let mut location_result = HashMap::new();
for variable in variables {
let mut variable_result = LocationSet::new();
for write_location in ud[&location.clone().into()].locations() {
let writes_variable = write_location
.apply(function)?
.instruction()
.unwrap()
.variables_written()
.unwrap()
.contains(&variable);
if writes_variable {
variable_result.insert(write_location.to_owned());
}
}
location_result.insert(variable.to_owned(), variable_result);
}
result.insert(location.clone().into(), location_result);
}
Ok(result)
}