]>
Commit | Line | Data |
---|---|---|
1 | //! Module that constructs a control-flow graph representing an item. | |
2 | //! Uses `Graph` as the underlying representation. | |
3 | ||
4 | use rustc_data_structures::graph::implementation as graph; | |
5 | use crate::ty::TyCtxt; | |
6 | use crate::hir; | |
7 | use crate::hir::def_id::DefId; | |
8 | ||
9 | mod construct; | |
10 | pub mod graphviz; | |
11 | ||
12 | pub struct CFG { | |
13 | pub owner_def_id: DefId, | |
14 | pub graph: CFGGraph, | |
15 | pub entry: CFGIndex, | |
16 | pub exit: CFGIndex, | |
17 | } | |
18 | ||
19 | #[derive(Copy, Clone, Debug, PartialEq)] | |
20 | pub enum CFGNodeData { | |
21 | AST(hir::ItemLocalId), | |
22 | Entry, | |
23 | Exit, | |
24 | Dummy, | |
25 | Unreachable, | |
26 | } | |
27 | ||
28 | impl CFGNodeData { | |
29 | pub fn id(&self) -> hir::ItemLocalId { | |
30 | if let CFGNodeData::AST(id) = *self { | |
31 | id | |
32 | } else { | |
33 | hir::DUMMY_ITEM_LOCAL_ID | |
34 | } | |
35 | } | |
36 | } | |
37 | ||
38 | #[derive(Debug)] | |
39 | pub struct CFGEdgeData { | |
40 | pub exiting_scopes: Vec<hir::ItemLocalId> | |
41 | } | |
42 | ||
43 | pub type CFGIndex = graph::NodeIndex; | |
44 | ||
45 | pub type CFGGraph = graph::Graph<CFGNodeData, CFGEdgeData>; | |
46 | ||
47 | pub type CFGNode = graph::Node<CFGNodeData>; | |
48 | ||
49 | pub type CFGEdge = graph::Edge<CFGEdgeData>; | |
50 | ||
51 | impl CFG { | |
52 | pub fn new(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG { | |
53 | construct::construct(tcx, body) | |
54 | } | |
55 | ||
56 | pub fn node_is_reachable(&self, id: hir::ItemLocalId) -> bool { | |
57 | self.graph.depth_traverse(self.entry, graph::OUTGOING) | |
58 | .any(|idx| self.graph.node_data(idx).id() == id) | |
59 | } | |
60 | } |