delete dead code
This commit is contained in:
parent
2fa1ba3e7e
commit
74b2783877
@ -26,15 +26,12 @@
|
||||
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::option;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::iter::{self, Once};
|
||||
use std::mem;
|
||||
use std::collections::BTreeMap;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::vec;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use syntax::symbol::Symbol;
|
||||
|
||||
@ -161,67 +158,6 @@ fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
trait IntoKeyValues<K: Key, V> {
|
||||
type KeyValues: IntoIterator<Item=(K, V)>;
|
||||
|
||||
fn into_key_values(key: &K, value: Self) -> Self::KeyValues;
|
||||
}
|
||||
|
||||
impl<K: Key, V> IntoKeyValues<K, V> for V {
|
||||
type KeyValues = Once<(K, V)>;
|
||||
|
||||
fn into_key_values(key: &K, value: Self) -> Self::KeyValues {
|
||||
iter::once((key.clone(), value))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return type for a multi-query, which is a query which may (if it
|
||||
/// chooses) return more than one (key, value) pair. Construct a
|
||||
/// `Multi` using `Multi::from(...)`.
|
||||
pub struct Multi<K: Key, V> {
|
||||
single: Option<V>,
|
||||
map: Vec<(K, V)>,
|
||||
}
|
||||
|
||||
impl<K: Key, V> Multi<K, V> {
|
||||
pub fn iter<'a>(&'a self, key: &'a K) -> impl Iterator<Item = (&'a K, &'a V)> + 'a {
|
||||
self.single.iter()
|
||||
.map(move |v| (key, v))
|
||||
.chain(self.map.iter().map(move |&(ref k, ref v)| (k, v)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a `Multi` from a single value.
|
||||
impl<K: Key, V> From<V> for Multi<K, V> {
|
||||
fn from(value: V) -> Self {
|
||||
Multi {
|
||||
single: Some(value),
|
||||
map: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a `Multi` from a hashmap of (K, V) pairs.
|
||||
impl<K: Key, V> From<Vec<(K, V)>> for Multi<K, V> {
|
||||
fn from(value: Vec<(K, V)>) -> Self {
|
||||
Multi {
|
||||
single: None,
|
||||
map: value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Key, V> IntoKeyValues<K, V> for Multi<K, V> {
|
||||
type KeyValues = iter::Chain<option::IntoIter<(K, V)>, vec::IntoIter<(K, V)>>;
|
||||
|
||||
fn into_key_values(key: &K, value: Self) -> Self::KeyValues {
|
||||
value.single
|
||||
.map(|v| (key.clone(), v))
|
||||
.into_iter()
|
||||
.chain(value.map)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CycleError<'a, 'tcx: 'a> {
|
||||
span: Span,
|
||||
cycle: RefMut<'a, [(Span, Query<'tcx>)]>,
|
||||
@ -490,14 +426,7 @@ fn try_get_with<F, R>(tcx: TyCtxt<'a, $tcx, 'lcx>,
|
||||
provider(tcx.global_tcx(), key)
|
||||
})?;
|
||||
|
||||
{
|
||||
let map = &mut *tcx.maps.$name.borrow_mut();
|
||||
for (k, v) in IntoKeyValues::<$K, $V>::into_key_values(&key, result) {
|
||||
map.insert(k, v);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(f(tcx.maps.$name.borrow().get(&key).expect("value just generated")))
|
||||
Ok(f(tcx.maps.$name.borrow_mut().entry(key).or_insert(result)))
|
||||
}
|
||||
|
||||
pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
|
||||
@ -683,20 +612,6 @@ fn default() -> Self {
|
||||
}
|
||||
};
|
||||
|
||||
// The `multi` modifier indicates a **multiquery**, in which case
|
||||
// the function returns a `Multi<K,V>` instead of just a value
|
||||
// `V`.
|
||||
(tcx: $tcx:tt,
|
||||
input: (([multi $($other_modifiers:tt)*] $name:tt [$K:ty] [$V:ty]) $($input:tt)*),
|
||||
output: $output:tt) => {
|
||||
define_provider_struct! {
|
||||
tcx: $tcx,
|
||||
ready: ($name [$K] [Multi<$K,$V>]),
|
||||
input: ($($input)*),
|
||||
output: $output
|
||||
}
|
||||
};
|
||||
|
||||
// Regular queries produce a `V` only.
|
||||
(tcx: $tcx:tt,
|
||||
input: (([] $name:tt $K:tt $V:tt) $($input:tt)*),
|
||||
@ -709,7 +624,7 @@ fn default() -> Self {
|
||||
}
|
||||
};
|
||||
|
||||
// Skip modifiers other than `multi`.
|
||||
// Skip modifiers.
|
||||
(tcx: $tcx:tt,
|
||||
input: (([$other_modifier:tt $($modifiers:tt)*] $($fields:tt)*) $($input:tt)*),
|
||||
output: $output:tt) => {
|
||||
|
@ -1,249 +0,0 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! MIR-based callgraph.
|
||||
//!
|
||||
//! This only considers direct calls
|
||||
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_data_structures::graph;
|
||||
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::visit::*;
|
||||
|
||||
use rustc::ty;
|
||||
|
||||
use rustc::util::nodemap::DefIdMap;
|
||||
|
||||
use transform::interprocedural::InterproceduralCx;
|
||||
|
||||
pub struct CallGraph {
|
||||
node_map: DefIdMap<graph::NodeIndex>,
|
||||
graph: graph::Graph<DefId, ()>
|
||||
}
|
||||
|
||||
impl CallGraph {
|
||||
pub fn build<'a, 'tcx>(cx: &mut InterproceduralCx<'a, 'tcx>) -> CallGraph {
|
||||
let mut callgraph = CallGraph {
|
||||
node_map: DefIdMap(),
|
||||
graph: graph::Graph::new()
|
||||
};
|
||||
|
||||
for &def_id in cx.tcx.mir_keys(LOCAL_CRATE).iter() {
|
||||
let idx = callgraph.add_node(def_id);
|
||||
|
||||
let mut call_visitor = CallVisitor {
|
||||
caller: idx,
|
||||
graph: &mut callgraph
|
||||
};
|
||||
|
||||
if let Some(mir) = cx.ensure_mir_and_read(def_id) {
|
||||
call_visitor.visit_mir(mir);
|
||||
}
|
||||
}
|
||||
|
||||
callgraph
|
||||
}
|
||||
|
||||
// Iterate over the strongly-connected components of the graph
|
||||
pub fn scc_iter(&self) -> SCCIterator {
|
||||
SCCIterator::new(&self.graph)
|
||||
}
|
||||
|
||||
// Get the def_id for the given graph node
|
||||
pub fn def_id(&self, node: graph::NodeIndex) -> DefId {
|
||||
*self.graph.node_data(node)
|
||||
}
|
||||
|
||||
fn add_node(&mut self, id: DefId) -> graph::NodeIndex {
|
||||
let graph = &mut self.graph;
|
||||
*self.node_map.entry(id).or_insert_with(|| {
|
||||
graph.add_node(id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct CallVisitor<'a> {
|
||||
caller: graph::NodeIndex,
|
||||
graph: &'a mut CallGraph
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for CallVisitor<'a> {
|
||||
fn visit_terminator_kind(&mut self, _block: BasicBlock,
|
||||
kind: &TerminatorKind<'tcx>, _loc: Location) {
|
||||
if let TerminatorKind::Call {
|
||||
func: Operand::Constant(ref f)
|
||||
, .. } = *kind {
|
||||
if let ty::TyFnDef(def_id, _, _) = f.ty.sty {
|
||||
let callee = self.graph.add_node(def_id);
|
||||
self.graph.graph.add_edge(self.caller, callee, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct StackElement<'g> {
|
||||
node: graph::NodeIndex,
|
||||
lowlink: usize,
|
||||
children: graph::AdjacentTargets<'g, DefId, ()>
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator over strongly-connected-components using Tarjan's algorithm[1]
|
||||
*
|
||||
* [1]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
|
||||
*/
|
||||
pub struct SCCIterator<'g> {
|
||||
graph: &'g graph::Graph<DefId, ()>,
|
||||
index: usize,
|
||||
node_indices: Vec<Option<usize>>,
|
||||
scc_stack: Vec<graph::NodeIndex>,
|
||||
current_scc: Vec<graph::NodeIndex>,
|
||||
visit_stack: Vec<StackElement<'g>>,
|
||||
}
|
||||
|
||||
impl<'g> SCCIterator<'g> {
|
||||
pub fn new(graph: &'g graph::Graph<DefId, ()>) -> SCCIterator<'g> {
|
||||
if graph.len_nodes() == 0 {
|
||||
return SCCIterator {
|
||||
graph: graph,
|
||||
index: 0,
|
||||
node_indices: Vec::new(),
|
||||
scc_stack: Vec::new(),
|
||||
current_scc: Vec::new(),
|
||||
visit_stack: Vec::new()
|
||||
};
|
||||
}
|
||||
|
||||
let first = graph::NodeIndex(0);
|
||||
|
||||
SCCIterator::with_entry(graph, first)
|
||||
}
|
||||
|
||||
pub fn with_entry(graph: &'g graph::Graph<DefId, ()>,
|
||||
entry: graph::NodeIndex) -> SCCIterator<'g> {
|
||||
let mut iter = SCCIterator {
|
||||
graph: graph,
|
||||
index: 0,
|
||||
node_indices: Vec::with_capacity(graph.len_nodes()),
|
||||
scc_stack: Vec::new(),
|
||||
current_scc: Vec::new(),
|
||||
visit_stack: Vec::new()
|
||||
};
|
||||
|
||||
iter.visit_one(entry);
|
||||
|
||||
iter
|
||||
}
|
||||
|
||||
fn get_next(&mut self) {
|
||||
self.current_scc.clear();
|
||||
|
||||
while !self.visit_stack.is_empty() {
|
||||
self.visit_children();
|
||||
|
||||
let node = self.visit_stack.pop().unwrap();
|
||||
|
||||
if let Some(last) = self.visit_stack.last_mut() {
|
||||
if last.lowlink > node.lowlink {
|
||||
last.lowlink = node.lowlink;
|
||||
}
|
||||
}
|
||||
|
||||
debug!("TarjanSCC: Popped node {:?} : lowlink = {:?}; index = {:?}",
|
||||
node.node, node.lowlink, self.node_index(node.node).unwrap());
|
||||
|
||||
if node.lowlink != self.node_index(node.node).unwrap() {
|
||||
continue;
|
||||
}
|
||||
|
||||
loop {
|
||||
let n = self.scc_stack.pop().unwrap();
|
||||
self.current_scc.push(n);
|
||||
self.set_node_index(n, !0);
|
||||
if n == node.node { return; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_one(&mut self, node: graph::NodeIndex) {
|
||||
self.index += 1;
|
||||
let idx = self.index;
|
||||
self.set_node_index(node, idx);
|
||||
self.scc_stack.push(node);
|
||||
self.visit_stack.push(StackElement {
|
||||
node: node,
|
||||
lowlink: self.index,
|
||||
children: self.graph.successor_nodes(node)
|
||||
});
|
||||
debug!("TarjanSCC: Node {:?} : index = {:?}", node, idx);
|
||||
}
|
||||
|
||||
fn visit_children(&mut self) {
|
||||
while let Some(child) = self.visit_stack.last_mut().unwrap().children.next() {
|
||||
if let Some(child_num) = self.node_index(child) {
|
||||
let cur = self.visit_stack.last_mut().unwrap();
|
||||
if cur.lowlink > child_num {
|
||||
cur.lowlink = child_num;
|
||||
}
|
||||
} else {
|
||||
self.visit_one(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn node_index(&self, node: graph::NodeIndex) -> Option<usize> {
|
||||
self.node_indices.get(node.node_id()).and_then(|&idx| idx)
|
||||
}
|
||||
|
||||
fn set_node_index(&mut self, node: graph::NodeIndex, idx: usize) {
|
||||
let i = node.node_id();
|
||||
if i >= self.node_indices.len() {
|
||||
self.node_indices.resize(i + 1, None);
|
||||
}
|
||||
self.node_indices[i] = Some(idx);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'g> Iterator for SCCIterator<'g> {
|
||||
type Item = Vec<graph::NodeIndex>;
|
||||
|
||||
fn next(&mut self) -> Option<Vec<graph::NodeIndex>> {
|
||||
self.get_next();
|
||||
|
||||
if self.current_scc.is_empty() {
|
||||
// Try a new root for the next SCC, if the node_indices
|
||||
// map is doesn't contain all nodes, use the smallest one
|
||||
// with no entry, otherwise find the first empty node.
|
||||
//
|
||||
// FIXME: This should probably use a set of precomputed
|
||||
// roots instead
|
||||
if self.node_indices.len() < self.graph.len_nodes() {
|
||||
let idx = graph::NodeIndex(self.node_indices.len());
|
||||
self.visit_one(idx);
|
||||
} else {
|
||||
for idx in 0..self.node_indices.len() {
|
||||
if self.node_indices[idx].is_none() {
|
||||
let idx = graph::NodeIndex(idx);
|
||||
self.visit_one(idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.get_next();
|
||||
}
|
||||
|
||||
if self.current_scc.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(self.current_scc.clone())
|
||||
}
|
||||
}
|
||||
}
|
@ -46,8 +46,7 @@
|
||||
|
||||
pub mod diagnostics;
|
||||
|
||||
pub mod build;
|
||||
pub mod callgraph;
|
||||
mod build;
|
||||
mod hair;
|
||||
mod shim;
|
||||
mod queries;
|
||||
|
@ -1,88 +0,0 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir::Mir;
|
||||
use rustc::mir::transform::{PassId};
|
||||
use rustc::ty::steal::Steal;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
||||
/// When writing inter-procedural analyses etc, we need to read (and
|
||||
/// steal) the MIR for a number of def-ids at once, not all of which
|
||||
/// are local. This little cache code attempts to remember what you've
|
||||
/// stolen and so forth. It is more of a placeholder meant to get
|
||||
/// inlining up and going again, and is probably going to need heavy
|
||||
/// revision as we scale up to more interesting optimizations.
|
||||
pub struct InterproceduralCx<'a, 'tcx: 'a> {
|
||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
local_cache: FxHashMap<DefId, Mir<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InterproceduralCx<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
|
||||
InterproceduralCx {
|
||||
tcx: tcx,
|
||||
local_cache: FxHashMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_local_mirs(self) -> Vec<(PassId, &'tcx Steal<Mir<'tcx>>)> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Ensures that the mir for `def_id` is available, if it can be
|
||||
/// made available.
|
||||
pub fn ensure_mir(&mut self, def_id: DefId) {
|
||||
if def_id.is_local() {
|
||||
self.ensure_mir_and_read(def_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensures that the mir for `def_id` is available and returns it if possible;
|
||||
/// returns `None` if this is a cross-crate MIR that is not
|
||||
/// available from metadata.
|
||||
pub fn ensure_mir_and_read(&mut self, def_id: DefId) -> Option<&Mir<'tcx>> {
|
||||
if def_id.is_local() {
|
||||
Some(self.mir_mut(def_id))
|
||||
} else {
|
||||
self.tcx.maybe_item_mir(def_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// True if the local cache contains MIR for `def-id`.
|
||||
pub fn contains_mir(&self, def_id: DefId) -> bool {
|
||||
if def_id.is_local() {
|
||||
self.local_cache.contains_key(&def_id)
|
||||
} else {
|
||||
self.tcx.is_item_mir_available(def_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads the MIR for `def-id`. If the MIR is local, this will
|
||||
/// panic if you have not previously invoked `ensure_mir`.
|
||||
pub fn mir(&self, def_id: DefId) -> Option<&Mir<'tcx>> {
|
||||
if def_id.is_local() {
|
||||
match self.local_cache.get(&def_id) {
|
||||
Some(p) => Some(p),
|
||||
None => {
|
||||
panic!("MIR for local def-id `{:?}` not previously ensured", def_id)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.tcx.maybe_item_mir(def_id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mir_mut(&mut self, def_id: DefId) -> &mut Mir<'tcx> {
|
||||
assert!(def_id.is_local(), "cannot get mutable mir of remote entry");
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
@ -26,7 +26,6 @@
|
||||
pub mod instcombine;
|
||||
pub mod copy_prop;
|
||||
pub mod inline;
|
||||
pub mod interprocedural;
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
self::qualify_consts::provide(providers);
|
||||
|
Loading…
Reference in New Issue
Block a user