diff --git a/src/back/msl/writer.rs b/src/back/msl/writer.rs index 17d2751fd9..f1be296952 100644 --- a/src/back/msl/writer.rs +++ b/src/back/msl/writer.rs @@ -70,6 +70,7 @@ pub struct Writer { out: W, names: FastHashMap, named_expressions: BitSet, + visit_mask: BitSet, typifier: Typifier, namer: Namer, temp_bake_handles: Vec>, @@ -177,6 +178,7 @@ impl Writer { out, names: FastHashMap::default(), named_expressions: BitSet::new(), + visit_mask: BitSet::new(), typifier: Typifier::new(), namer: Namer::default(), temp_bake_handles: Vec::new(), @@ -709,6 +711,7 @@ impl Writer { exclude_root: bool, ) -> Result<(), Error> { // set up the search + self.visit_mask.clear(); let mut interface = Interface { expressions: &context.expression.function.expressions, local_variables: &context.expression.function.local_variables, @@ -722,6 +725,7 @@ impl Writer { None }, }, + mask: &mut self.visit_mask, }; // populate the bake handles interface.traverse_expr(root_handle); diff --git a/src/front/global_usage.rs b/src/front/global_usage.rs index e5a43509c0..99fe7fa738 100644 --- a/src/front/global_usage.rs +++ b/src/front/global_usage.rs @@ -2,6 +2,7 @@ use crate::{ arena::{Arena, Handle}, proc::{Interface, Visitor}, }; +use bit_set::BitSet; struct GlobalUseVisitor<'a> { usage: &'a mut [crate::GlobalUse], @@ -30,6 +31,7 @@ impl Visitor for GlobalUseVisitor<'_> { impl crate::Function { pub fn fill_global_use(&mut self, globals_num: usize, functions: &Arena) { + let mut mask = BitSet::with_capacity(self.expressions.len()); self.global_usage.clear(); self.global_usage .resize(globals_num, crate::GlobalUse::empty()); @@ -41,6 +43,7 @@ impl crate::Function { usage: &mut self.global_usage, functions, }, + mask: &mut mask, }; io.traverse(&self.body); } diff --git a/src/proc/call_graph.rs b/src/proc/call_graph.rs index 1c580d5c15..9c604bfe9b 100644 --- a/src/proc/call_graph.rs +++ b/src/proc/call_graph.rs @@ -3,6 +3,7 @@ use crate::{ proc::{Interface, Visitor}, Function, }; +use bit_set::BitSet; use petgraph::{ graph::{DefaultIx, NodeIndex}, Graph, @@ -18,6 +19,7 @@ impl<'a> CallGraphBuilder<'a> { pub fn process(&self, func: &Function) -> CallGraph { let mut graph = Graph::new(); let mut children = Vec::new(); + let mut mask = BitSet::with_capacity(func.expressions.len()); let visitor = CallGraphVisitor { children: &mut children, @@ -27,29 +29,38 @@ impl<'a> CallGraphBuilder<'a> { expressions: &func.expressions, local_variables: &func.local_variables, visitor, + mask: &mut mask, }; interface.traverse(&func.body); for handle in children { let id = graph.add_node(handle); - self.collect(handle, id, &mut graph); + self.collect(handle, id, &mut graph, &mut mask); } graph } - fn collect(&self, handle: Handle, id: NodeIndex, graph: &mut CallGraph) { + fn collect( + &self, + handle: Handle, + id: NodeIndex, + graph: &mut CallGraph, + mask: &mut BitSet, + ) { let mut children = Vec::new(); let visitor = CallGraphVisitor { children: &mut children, }; let func = &self.functions[handle]; + mask.clear(); let mut interface = Interface { expressions: &func.expressions, local_variables: &func.local_variables, visitor, + mask, }; interface.traverse(&func.body); @@ -58,7 +69,7 @@ impl<'a> CallGraphBuilder<'a> { let child_id = graph.add_node(handle); graph.add_edge(id, child_id, ()); - self.collect(handle, child_id, graph); + self.collect(handle, child_id, graph, mask); } } } diff --git a/src/proc/interface.rs b/src/proc/interface.rs index 051d42e1be..fd7436251b 100644 --- a/src/proc/interface.rs +++ b/src/proc/interface.rs @@ -1,9 +1,11 @@ use crate::arena::{Arena, Handle}; +use bit_set::BitSet; pub struct Interface<'a, T> { + pub visitor: T, pub expressions: &'a Arena, pub local_variables: &'a Arena, - pub visitor: T, + pub mask: &'a mut BitSet, } pub trait Visitor { @@ -12,13 +14,13 @@ pub trait Visitor { fn visit_fun(&mut self, _: Handle) {} } -impl<'a, T> Interface<'a, T> -where - T: Visitor, -{ +impl<'a, T: Visitor> Interface<'a, T> { pub fn traverse_expr(&mut self, handle: Handle) { use crate::Expression as E; + if !self.mask.insert(handle.index()) { + return; + } let expr = &self.expressions[handle]; self.visitor.visit_expr(handle, expr);