blob: a37951346a8164034fa51aa5ce898b3dd1f5d653 [file] [log] [blame]
George Burgess IV1ca8aff2016-07-06 00:36:12 +00001//======- CFLGraph.h - Abstract stratified sets implementation. --------======//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10/// This file defines CFLGraph, an auxiliary data structure used by CFL-based
11/// alias analysis.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_ANALYSIS_CFLGRAPH_H
16#define LLVM_ANALYSIS_CFLGRAPH_H
17
18#include "StratifiedSets.h"
19
20namespace llvm {
21
22class Value;
23
24namespace cflaa {
25
26/// Edges can be one of four "weights" -- each weight must have an inverse
27/// weight (Assign has Assign; Reference has Dereference).
28enum class EdgeType {
29 /// The weight assigned when assigning from or to a value. For example, in:
30 /// %b = getelementptr %a, 0
31 /// ...The relationships are %b assign %a, and %a assign %b. This used to be
32 /// two edges, but having a distinction bought us nothing.
33 Assign,
34
35 /// The edge used when we have an edge going from some handle to a Value.
36 /// Examples of this include:
37 /// %b = load %a (%b Dereference %a)
38 /// %b = extractelement %a, 0 (%a Dereference %b)
39 Dereference,
40
41 /// The edge used when our edge goes from a value to a handle that may have
42 /// contained it at some point. Examples:
43 /// %b = load %a (%a Reference %b)
44 /// %b = extractelement %a, 0 (%b Reference %a)
45 Reference
46};
47
48/// \brief The Program Expression Graph (PEG) of CFL analysis
49/// CFLGraph is auxiliary data structure used by CFL-based alias analysis to
50/// describe flow-insensitive pointer-related behaviors. Given an LLVM function,
51/// the main purpose of this graph is to abstract away unrelated facts and
52/// translate the rest into a form that can be easily digested by CFL analyses.
53class CFLGraph {
54 typedef Value *Node;
55
56 struct Edge {
57 EdgeType Type;
58 Node Other;
59 };
60
61 typedef std::vector<Edge> EdgeList;
62
63 struct NodeInfo {
64 EdgeList Edges;
65 StratifiedAttrs Attr;
66 };
67
68 typedef DenseMap<Node, NodeInfo> NodeMap;
69 NodeMap NodeImpls;
70
71 // Gets the inverse of a given EdgeType.
72 static EdgeType flipWeight(EdgeType Initial) {
73 switch (Initial) {
74 case EdgeType::Assign:
75 return EdgeType::Assign;
76 case EdgeType::Dereference:
77 return EdgeType::Reference;
78 case EdgeType::Reference:
79 return EdgeType::Dereference;
80 }
81 llvm_unreachable("Incomplete coverage of EdgeType enum");
82 }
83
84 const NodeInfo *getNode(Node N) const {
85 auto Itr = NodeImpls.find(N);
86 if (Itr == NodeImpls.end())
87 return nullptr;
88 return &Itr->second;
89 }
90 NodeInfo *getNode(Node N) {
91 auto Itr = NodeImpls.find(N);
92 if (Itr == NodeImpls.end())
93 return nullptr;
94 return &Itr->second;
95 }
96
97 static Node nodeDeref(const NodeMap::value_type &P) { return P.first; }
98 typedef std::pointer_to_unary_function<const NodeMap::value_type &, Node>
99 NodeDerefFun;
100
101public:
102 typedef EdgeList::const_iterator const_edge_iterator;
103 typedef mapped_iterator<NodeMap::const_iterator, NodeDerefFun>
104 const_node_iterator;
105
106 bool addNode(Node N) {
107 return NodeImpls.insert(std::make_pair(N, NodeInfo{EdgeList(), 0})).second;
108 }
109
110 void addAttr(Node N, StratifiedAttrs Attr) {
111 auto *Info = getNode(N);
112 assert(Info != nullptr);
113 Info->Attr |= Attr;
114 }
115
116 void addEdge(Node From, Node To, EdgeType Type) {
117 auto *FromInfo = getNode(From);
118 assert(FromInfo != nullptr);
119 auto *ToInfo = getNode(To);
120 assert(ToInfo != nullptr);
121
122 FromInfo->Edges.push_back(Edge{Type, To});
123 ToInfo->Edges.push_back(Edge{flipWeight(Type), From});
124 }
125
126 StratifiedAttrs attrFor(Node N) const {
127 auto *Info = getNode(N);
128 assert(Info != nullptr);
129 return Info->Attr;
130 }
131
132 iterator_range<const_edge_iterator> edgesFor(Node N) const {
133 auto *Info = getNode(N);
134 assert(Info != nullptr);
135 auto &Edges = Info->Edges;
136 return make_range(Edges.begin(), Edges.end());
137 }
138
139 iterator_range<const_node_iterator> nodes() const {
140 return make_range<const_node_iterator>(
141 map_iterator(NodeImpls.begin(), NodeDerefFun(nodeDeref)),
142 map_iterator(NodeImpls.end(), NodeDerefFun(nodeDeref)));
143 }
144
145 bool empty() const { return NodeImpls.empty(); }
146 std::size_t size() const { return NodeImpls.size(); }
147};
148}
149}
150
151#endif