···99mod typecheck;
10101111pub use ctx::{Ctx, Symbol};
1212-pub use mir::{Function, visualize};
1313-pub use span::{Diagnostic, DUMMY_SPAN, SourceMap, Span, SpanExt, Spanned};
1412pub use lex::BinOp;
1313+pub use mir::{Function, visualize};
1414+pub use span::{Diagnostic, SourceMap, Span, SpanExt, Spanned};
15151616use ast_visitor::{AstToMIR, AstVisitor};
1717use std::collections::VecDeque;
1818use std::fs::File;
1919use std::io::Read;
20202121-pub fn do_frontend(file: &str) -> Result<(mir::Module, Ctx), String> {
2121+pub fn do_frontend(file: &str, output_mir: bool) -> Result<(mir::Module, Ctx), String> {
2222 let mut file = File::open(file).map_err(|e| format!("failed to open file: {}", e))?;
23232424 let mut contents = String::new();
2525- file.read_to_string(&mut contents).map_err(|e| format!("failed to read file: {}", e))?;
2525+ file.read_to_string(&mut contents)
2626+ .map_err(|e| format!("failed to read file: {}", e))?;
2627 contents = contents.trim().to_string();
27282829 let source_map = SourceMap::new(contents.clone());
···4243 let mut ast_visitor = AstToMIR::new(&ctx);
4344 ast_visitor.visit_module(module);
44454545- Ok((ast_visitor.produce_module(), ctx))
4646+ let module = mir::run_passes(ast_visitor.produce_module(), output_mir);
4747+ Ok((module, ctx))
4648}
+123
frontend/src/mir/domtree.rs
···11+use std::collections::HashMap;
22+33+pub trait Searchable<V: Clone> {
44+ type NodeId: Clone + Eq + std::hash::Hash;
55+66+ /// Required methods:
77+ /// Depth-first search traversal of the graph starting from the given node, applying the visit
88+ /// function to each node
99+ fn dfs<F>(&self, start: Self::NodeId, visit: &mut F)
1010+ where
1111+ F: FnMut(Self::NodeId);
1212+1313+ /// Returns the nodes in the graph, order is not guaranteed
1414+ fn nodes(&self) -> Vec<Self::NodeId>;
1515+1616+ /// Derived method:
1717+ /// Collects the nodes in post order starting from the given node
1818+ fn post_order_collect(&self, start: Self::NodeId) -> Vec<Self::NodeId> {
1919+ let mut visited = Vec::new();
2020+ self.dfs(start, &mut |id| {
2121+ visited.push(id.clone());
2222+ });
2323+ visited
2424+ }
2525+}
2626+2727+pub trait DomTree<V>: Searchable<V>
2828+where
2929+ V: Clone + Eq + std::hash::Hash,
3030+{
3131+ /// Required methods:
3232+ ///
3333+ /// Returns the dominator of a node in the dominator tree
3434+ fn dom(&self, start: Self::NodeId) -> Option<Self::NodeId>;
3535+ /// Sets the dominator of a node in the dominator tree
3636+ fn set_dom(&mut self, node: Self::NodeId, dom: Option<Self::NodeId>);
3737+ /// Clears the dominator tree, which is a precondition for computing the dominator tree
3838+ fn reset_dom(&mut self);
3939+ /// Returns the predecessors of a node in the dominator tree
4040+ fn preds(&self, node: Self::NodeId) -> Vec<Self::NodeId>;
4141+4242+ /// Derived methods:
4343+ /// Helper method to compute the dominance intersection of two nodes
4444+ fn intersect(
4545+ &self,
4646+ order_map: &HashMap<Self::NodeId, usize>,
4747+ mut node1: Self::NodeId,
4848+ mut node2: Self::NodeId,
4949+ ) -> Self::NodeId {
5050+ while node1 != node2 {
5151+ if order_map[&node1] > order_map[&node2] {
5252+ node1 = self
5353+ .dom(node1.clone())
5454+ .expect("Every node must eventually have a dominator");
5555+ } else {
5656+ node2 = self
5757+ .dom(node2.clone())
5858+ .expect("Every node must eventually have a dominator");
5959+ }
6060+ }
6161+ node1
6262+ }
6363+6464+ /// Computes the dominator tree starting from the given node
6565+ /// https://en.wikipedia.org/wiki/Dominator_(graph_theory)#Algorithms
6666+ fn compute_dom_tree(&mut self, start: Self::NodeId) {
6767+ self.reset_dom();
6868+ self.set_dom(start.clone(), Some(start.clone()));
6969+7070+ let mut order: Vec<Self::NodeId> = self.post_order_collect(start);
7171+ order.reverse();
7272+7373+ let order_map: HashMap<Self::NodeId, usize> = order
7474+ .iter()
7575+ .enumerate()
7676+ .map(|(i, id)| (id.clone(), i))
7777+ .collect();
7878+7979+ let mut changed = true;
8080+ while changed {
8181+ changed = false;
8282+8383+ // for each n in N - {n0}:
8484+ for node in order.iter().skip(1) {
8585+ let preds = &self.preds(node.clone());
8686+8787+ let mut new_dominator_opt = None;
8888+ for pred in preds {
8989+ if self.dom(pred.clone()).is_some() {
9090+ new_dominator_opt = Some(pred.clone());
9191+ break;
9292+ }
9393+ }
9494+ let mut new_dominator = match new_dominator_opt {
9595+ Some(n) => n,
9696+ None => continue, // if no predecessor has a computed dominator, skip
9797+ };
9898+9999+ for pred in preds {
100100+ if self.dom(pred.clone()).is_some() {
101101+ new_dominator = self.intersect(&order_map, new_dominator, pred.clone());
102102+ }
103103+ }
104104+105105+ if self.dom(node.clone()) != Some(new_dominator.clone()) {
106106+ self.set_dom(node.clone(), Some(new_dominator));
107107+ changed = true;
108108+ }
109109+ }
110110+ }
111111+ }
112112+113113+ /// Returns the dominator tree as a HashMap
114114+ fn dom_tree(&self) -> HashMap<Self::NodeId, Self::NodeId> {
115115+ let mut dom_tree = HashMap::new();
116116+ for node in self.nodes() {
117117+ if let Some(dom) = self.dom(node.clone()) {
118118+ dom_tree.insert(node.clone(), dom);
119119+ }
120120+ }
121121+ dom_tree
122122+ }
123123+}