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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
//! SubIterator for a Module
use crate::ir::id::FunctionID;
use crate::ir::types::Location;
use crate::subiterator::function_subiterator::FuncSubIterator;
use std::collections::HashMap;
/// Sub-iterator for a Module. Keeps track of current location in a Module.
pub struct ModuleSubIterator {
/// The current function the SubIterator is at
pub(crate) curr_func: FunctionID,
/// The number of functions that have been visited thus far
visited_funcs: u32,
/// Number of functions in this module
num_funcs: u32,
/// Metadata that maps Function Index -> Instruction Index
metadata: HashMap<FunctionID, usize>,
/// The function iterator used to keep track of the location in the function.
pub(crate) func_iterator: FuncSubIterator,
/// Functions to skip. Provide an empty vector if no functions are to be skipped.
skip_funcs: Vec<FunctionID>,
}
impl ModuleSubIterator {
/// Creates a new ModuleSubIterator
pub fn new(
num_funcs: u32,
metadata: HashMap<FunctionID, usize>,
skip_funcs: Vec<FunctionID>,
) -> Self {
let mut mod_it = ModuleSubIterator {
curr_func: *metadata.keys().min().unwrap(),
visited_funcs: 0,
num_funcs,
metadata: metadata.clone(),
func_iterator: FuncSubIterator::new(
*metadata.get(metadata.keys().min().unwrap()).unwrap(),
),
skip_funcs,
};
// In case 0 is in skip func
while mod_it
.skip_funcs
.contains(&(mod_it.curr_func as FunctionID))
{
mod_it.next_function();
}
mod_it
}
/// Checks if the SubIterator has finished traversing all the functions
pub fn end(&self) -> bool {
self.visited_funcs == self.num_funcs
}
/// Returns the current Location in the Module as a Location
/// and a bool value that says whether the location is at the end of the function.
pub fn curr_loc(&self) -> (Location, bool) {
let curr_instr = self.func_iterator.curr_instr;
(
Location::Module {
func_idx: self.curr_func,
instr_idx: curr_instr,
},
self.func_iterator.is_end(curr_instr),
)
}
/// Resets the ModuleSubIterator when it is a Child SubIterator of a ComponentSubIterator
pub(crate) fn reset_from_comp_iterator(&mut self, metadata: HashMap<FunctionID, usize>) {
*self.curr_func = 0;
self.metadata = metadata;
self.func_iterator.reset(
*self
.metadata
.get(self.metadata.keys().min().unwrap())
.unwrap(),
);
}
/// Resets the ModuleSubIterator when it is not a Child SubIterator
pub fn reset(&mut self) {
*self.curr_func = 0;
self.func_iterator
.reset(*self.metadata.get(&FunctionID(0)).unwrap());
}
/// Checks if there are functions left to visit
pub fn has_next_function(&self) -> bool {
*self.curr_func + 1 < self.num_funcs
}
/// Goes to the next function in the module
fn next_function(&mut self) -> bool {
*self.curr_func += 1;
self.visited_funcs += 1;
// skip over configured funcs
while self.visited_funcs < self.num_funcs
&& self.skip_funcs.contains(&(self.curr_func as FunctionID))
{
*self.curr_func += 1;
self.visited_funcs += 1;
}
if self.visited_funcs < self.num_funcs {
self.func_iterator = FuncSubIterator::new(*self.metadata.get(&self.curr_func).unwrap());
true
} else {
false
}
}
/// Checks if there are functions left to visit
pub(crate) fn has_next(&self) -> bool {
self.func_iterator.has_next() || self.has_next_function()
}
/// Goes to the next function
pub(crate) fn next(&mut self) -> bool {
if self.func_iterator.has_next() {
self.func_iterator.next()
} else {
self.next_function()
}
}
}