From eb4961b9610beb988e51f4a6e3cf9161fa00e266 Mon Sep 17 00:00:00 2001 From: James Miller Date: Thu, 19 Feb 2015 20:36:25 +0100 Subject: [PATCH] Add support for mapping a single ast-node to multiple cfg-nodes. This is necessary for e.g. supporting the cfgs we plan to construct for match under aatch's plan. (Factoring of aatch CFG code, Part 3.) --- src/librustc/middle/dataflow.rs | 106 ++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 39 deletions(-) diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 3f0555e93e6..1718df70255 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -53,7 +53,7 @@ pub struct DataFlowContext<'a, 'tcx: 'a, O> { // mapping from node to cfg node index // FIXME (#6298): Shouldn't this go with CFG? - nodeid_to_index: NodeMap, + nodeid_to_index: NodeMap>, // Bit sets per cfg node. The following three fields (`gens`, `kills`, // and `on_entry`) all have the same structure. For each id in @@ -88,11 +88,9 @@ struct PropagationContext<'a, 'b: 'a, 'tcx: 'b, O: 'a> { changed: bool } -fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap) -> CFGIndex { - let opt_cfgindex = index.get(&id).cloned(); - opt_cfgindex.unwrap_or_else(|| { - panic!("nodeid_to_index does not have entry for NodeId {}", id); - }) +fn get_cfg_indices<'a>(id: ast::NodeId, index: &'a NodeMap>) -> &'a [CFGIndex] { + let opt_indices = index.get(&id); + opt_indices.map(|v| &v[..]).unwrap_or(&[]) } impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { @@ -114,9 +112,13 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O pprust::NodePat(pat) => pat.id }; - if self.has_bitset_for_nodeid(id) { - assert!(self.bits_per_id > 0); - let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); + if !self.has_bitset_for_nodeid(id) { + return Ok(()); + } + + assert!(self.bits_per_id > 0); + let indices = get_cfg_indices(id, &self.nodeid_to_index); + for &cfgidx in indices { let (start, end) = self.compute_id_range(cfgidx); let on_entry = &self.on_entry[start.. end]; let entry_str = bits_to_string(on_entry); @@ -144,7 +146,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O } fn build_nodeid_to_index(decl: Option<&ast::FnDecl>, - cfg: &cfg::CFG) -> NodeMap { + cfg: &cfg::CFG) -> NodeMap> { let mut index = NodeMap(); // FIXME (#6298): Would it be better to fold formals from decl @@ -157,28 +159,38 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>, } cfg.graph.each_node(|node_idx, node| { - if node.data.id() != ast::DUMMY_NODE_ID { - index.insert(node.data.id(), node_idx); + if let cfg::CFGNodeData::AST(id) = node.data { + match index.entry(id).get() { + Ok(v) => v.push(node_idx), + Err(e) => { + e.insert(vec![node_idx]); + } + } } true }); return index; - fn add_entries_from_fn_decl(index: &mut NodeMap, + fn add_entries_from_fn_decl(index: &mut NodeMap>, decl: &ast::FnDecl, entry: CFGIndex) { //! add mappings from the ast nodes for the formal bindings to //! the entry-node in the graph. struct Formals<'a> { entry: CFGIndex, - index: &'a mut NodeMap, + index: &'a mut NodeMap>, } let mut formals = Formals { entry: entry, index: index }; visit::walk_fn_decl(&mut formals, decl); impl<'a, 'v> visit::Visitor<'v> for Formals<'a> { fn visit_pat(&mut self, p: &ast::Pat) { - self.index.insert(p.id, self.entry); + match self.index.entry(p.id).get() { + Ok(v) => v.push(self.entry), + Err(e) => { + e.insert(vec![self.entry]); + } + } visit::walk_pat(self, p) } } @@ -230,10 +242,12 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { assert!(self.nodeid_to_index.contains_key(&id)); assert!(self.bits_per_id > 0); - let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); - let (start, end) = self.compute_id_range(cfgidx); - let gens = &mut self.gens[start.. end]; - set_bit(gens, bit); + let indices = get_cfg_indices(id, &self.nodeid_to_index); + for &cfgidx in indices { + let (start, end) = self.compute_id_range(cfgidx); + let gens = &mut self.gens[start.. end]; + set_bit(gens, bit); + } } pub fn add_kill(&mut self, id: ast::NodeId, bit: uint) { @@ -243,10 +257,12 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { assert!(self.nodeid_to_index.contains_key(&id)); assert!(self.bits_per_id > 0); - let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); - let (start, end) = self.compute_id_range(cfgidx); - let kills = &mut self.kills[start.. end]; - set_bit(kills, bit); + let indices = get_cfg_indices(id, &self.nodeid_to_index); + for &cfgidx in indices { + let (start, end) = self.compute_id_range(cfgidx); + let kills = &mut self.kills[start.. end]; + set_bit(kills, bit); + } } fn apply_gen_kill(&self, cfgidx: CFGIndex, bits: &mut [uint]) { @@ -279,7 +295,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } - pub fn each_bit_on_entry(&self, id: ast::NodeId, f: F) -> bool where + pub fn each_bit_on_entry(&self, id: ast::NodeId, mut f: F) -> bool where F: FnMut(uint) -> bool, { //! Iterates through each bit that is set on entry to `id`. @@ -287,8 +303,13 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { if !self.has_bitset_for_nodeid(id) { return true; } - let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); - self.each_bit_for_node(Entry, cfgidx, f) + let indices = get_cfg_indices(id, &self.nodeid_to_index); + for &cfgidx in indices { + if !self.each_bit_for_node(Entry, cfgidx, |i| f(i)) { + return false; + } + } + return true; } pub fn each_bit_for_node(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bool where @@ -320,7 +341,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { self.each_bit(slice, f) } - pub fn each_gen_bit(&self, id: ast::NodeId, f: F) -> bool where + pub fn each_gen_bit(&self, id: ast::NodeId, mut f: F) -> bool where F: FnMut(uint) -> bool, { //! Iterates through each bit in the gen set for `id`. @@ -334,12 +355,17 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { return true; } - let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); - let (start, end) = self.compute_id_range(cfgidx); - let gens = &self.gens[start.. end]; - debug!("{} each_gen_bit(id={}, gens={})", - self.analysis_name, id, bits_to_string(gens)); - self.each_bit(gens, f) + let indices = get_cfg_indices(id, &self.nodeid_to_index); + for &cfgidx in indices { + let (start, end) = self.compute_id_range(cfgidx); + let gens = &self.gens[start.. end]; + debug!("{} each_gen_bit(id={}, gens={})", + self.analysis_name, id, bits_to_string(gens)); + if !self.each_bit(gens, |i| f(i)) { + return false; + } + } + return true; } fn each_bit(&self, words: &[uint], mut f: F) -> bool where @@ -400,13 +426,15 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let mut changed = false; for &node_id in &edge.data.exiting_scopes { - let opt_cfg_idx = self.nodeid_to_index.get(&node_id).cloned(); + let opt_cfg_idx = self.nodeid_to_index.get(&node_id); match opt_cfg_idx { - Some(cfg_idx) => { - let (start, end) = self.compute_id_range(cfg_idx); - let kills = &self.kills[start.. end]; - if bitwise(&mut orig_kills, kills, &Union) { - changed = true; + Some(indices) => { + for &cfg_idx in indices { + let (start, end) = self.compute_id_range(cfg_idx); + let kills = &self.kills[start.. end]; + if bitwise(&mut orig_kills, kills, &Union) { + changed = true; + } } } None => {