LLZK 0.1.0
Veridise's ZK Language IR
Loading...
Searching...
No Matches
CallGraph.h
Go to the documentation of this file.
1//===-- CallGraph.h ---------------------------------------------*- C++ -*-===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2025 Veridise Inc.
6// SPDX-License-Identifier: Apache-2.0
7//
8//===----------------------------------------------------------------------===//
9
10#pragma once
11
12#include <mlir/Analysis/CallGraph.h>
13
14#include <llvm/ADT/GraphTraits.h>
15#include <llvm/ADT/MapVector.h>
16#include <llvm/ADT/PointerIntPair.h>
17#include <llvm/ADT/SCCIterator.h>
18#include <llvm/ADT/SetVector.h>
19
20namespace mlir {
21
22class Operation;
23class CallOpInterface;
24class SymbolTableCollection;
25
26} // namespace mlir
27
28namespace llzk {
29
30namespace function {
31class FuncDefOp;
32}
33
39class CallGraphNode {
40public:
42 class Edge {
43 enum class Kind {
44 // An 'Abstract' edge represents an opaque, non-operation, reference
45 // between this node and the target. Edges of this type are only valid
46 // from the external node (e.g., an external library call),
47 // as there is no valid connection to an operation in the module.
48 Abstract,
49
50 // A 'Call' edge represents a direct reference to the target node via a
51 // call-like operation within the callable region of this node.
52 Call,
53
54 // A 'Child' edge is used when the region of target node is defined inside
55 // of the callable region of this node. This means that the region of this
56 // node is an ancestor of the region for the target node. As such, this
57 // edge cannot be used on the 'external' node.
58 Child,
59 };
60
61 public:
63 bool isAbstract() const { return targetAndKind.getInt() == Kind::Abstract; }
64
66 bool isCall() const { return targetAndKind.getInt() == Kind::Call; }
67
69 bool isChild() const { return targetAndKind.getInt() == Kind::Child; }
70
73 CallGraphNode *getSource() const { return source; }
74
76 CallGraphNode *getTarget() const { return targetAndKind.getPointer(); }
77
78 bool operator==(const Edge &edge) const {
79 return source == edge.source && targetAndKind == edge.targetAndKind;
80 }
81
82 private:
83 Edge(CallGraphNode *src, CallGraphNode *target, Kind kind)
84 : source(src), targetAndKind(target, kind) {}
85 Edge(CallGraphNode *src, llvm::PointerIntPair<CallGraphNode *, 2, Kind> targetAndKind)
86 : source(src), targetAndKind(targetAndKind) {}
87
91
93 llvm::PointerIntPair<CallGraphNode *, 2, Kind> targetAndKind;
94
95 // Provide access to the constructor and Kind.
96 friend class CallGraphNode;
97 };
98
100 bool isExternal() const;
101
104 mlir::Region *getCallableRegion() const;
105
110
114 void addAbstractEdge(CallGraphNode *node);
115
117 void addCallEdge(CallGraphNode *node);
118
120 void addChildEdge(CallGraphNode *child);
121
123 using iterator = mlir::SmallVectorImpl<Edge>::const_iterator;
124 iterator begin() const { return edges.begin(); }
125 iterator end() const { return edges.end(); }
126
127 llvm::iterator_range<iterator> edgesOut() const { return llvm::make_range(begin(), end()); }
128
130 bool hasChildren() const;
131
132private:
134 struct EdgeKeyInfo {
135 using SourceInfo = mlir::DenseMapInfo<CallGraphNode *>;
136 using BaseInfo = mlir::DenseMapInfo<llvm::PointerIntPair<CallGraphNode *, 2, Edge::Kind>>;
137
138 static Edge getEmptyKey() { return Edge(nullptr, BaseInfo::getEmptyKey()); }
139 static Edge getTombstoneKey() { return Edge(nullptr, BaseInfo::getTombstoneKey()); }
140 static unsigned getHashValue(const Edge &edge) {
141 return SourceInfo::getHashValue(edge.source) ^ BaseInfo::getHashValue(edge.targetAndKind);
142 }
143 static bool isEqual(const Edge &lhs, const Edge &rhs) { return lhs == rhs; }
144 };
145
146 CallGraphNode(mlir::Region *callableRegion) : callableRegion(callableRegion) {}
147
149 void addEdge(CallGraphNode *node, Edge::Kind kind);
150
154 mlir::Region *callableRegion;
155
157 mlir::SetVector<Edge, mlir::SmallVector<Edge, 4>, llvm::SmallDenseSet<Edge, 4, EdgeKeyInfo>>
158 edges;
159
160 // Provide access to private methods.
161 friend class CallGraph;
162};
163
168 using NodeMapT = llvm::MapVector<mlir::Region *, std::unique_ptr<CallGraphNode>>;
169
172 class NodeIterator final
173 : public llvm::mapped_iterator<
174 NodeMapT::const_iterator, CallGraphNode *(*)(const NodeMapT::value_type &)> {
175 static CallGraphNode *unwrap(const NodeMapT::value_type &value) { return value.second.get(); }
176
177 public:
179 NodeIterator(NodeMapT::const_iterator it)
180 : llvm::mapped_iterator<
181 NodeMapT::const_iterator, CallGraphNode *(*)(const NodeMapT::value_type &)>(
182 it, &unwrap
183 ) {}
184 };
185
186public:
187 CallGraph(mlir::Operation *op);
188
192 CallGraphNode *getOrAddNode(mlir::Region *region, CallGraphNode *parentNode);
193
196 CallGraphNode *lookupNode(mlir::Region *region) const;
197
200 return const_cast<CallGraphNode *>(&externalCallerNode);
201 }
202
205 return const_cast<CallGraphNode *>(&unknownCalleeNode);
206 }
207
213 resolveCallable(mlir::CallOpInterface call, mlir::SymbolTableCollection &symbolTable) const;
214
216 void eraseNode(CallGraphNode *node);
217
219 using iterator = NodeIterator;
220 iterator begin() const { return nodes.begin(); }
221 iterator end() const { return nodes.end(); }
222
223 size_t size() const { return nodes.size(); }
224
226 void dump() const;
227 void print(llvm::raw_ostream &os) const;
228
229private:
231 NodeMapT nodes;
232
234 CallGraphNode externalCallerNode;
235
237 CallGraphNode unknownCalleeNode;
238};
239
240} // namespace llzk
241
242namespace llvm {
243// Provide graph traits for traversing call graphs using standard graph
244// traversals.
245template <> struct GraphTraits<const llzk::CallGraphNode *> {
247 static NodeRef getEntryNode(NodeRef node) { return node; }
248
249 static NodeRef unwrap(const llzk::CallGraphNode::Edge &edge) { return edge.getTarget(); }
250
251 // ChildIteratorType/begin/end - Allow iteration over all nodes in the graph.
252 using ChildIteratorType = mapped_iterator<llzk::CallGraphNode::iterator, decltype(&unwrap)>;
253 static ChildIteratorType child_begin(NodeRef node) { return {node->begin(), &unwrap}; }
254 static ChildIteratorType child_end(NodeRef node) { return {node->end(), &unwrap}; }
255};
256
257template <>
258struct GraphTraits<const llzk::CallGraph *> : public GraphTraits<const llzk::CallGraphNode *> {
260 static NodeRef getEntryNode(const llzk::CallGraph *cg) { return cg->getExternalCallerNode(); }
261
262 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
264 static nodes_iterator nodes_begin(llzk::CallGraph *cg) { return cg->begin(); }
265 static nodes_iterator nodes_end(llzk::CallGraph *cg) { return cg->end(); }
266};
267} // namespace llvm
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation source
Definition LICENSE.txt:28
This class represents a directed edge between two nodes in the callgraph.
Definition CallGraph.h:42
bool isChild() const
Returns true if this edge represents a Child edge.
Definition CallGraph.h:69
CallGraphNode * getTarget() const
Returns the target node for this edge.
Definition CallGraph.h:76
bool operator==(const Edge &edge) const
Definition CallGraph.h:78
bool isCall() const
Returns true if this edge represents a Call edge.
Definition CallGraph.h:66
CallGraphNode * getSource() const
Returns the source node of this edge.
Definition CallGraph.h:73
bool isAbstract() const
Returns true if this edge represents an Abstract edge.
Definition CallGraph.h:63
friend class CallGraphNode
Definition CallGraph.h:96
This is a simple port of the mlir::CallGraphNode with llzk::CallGraph as a friend class,...
Definition CallGraph.h:39
friend class CallGraph
Definition CallGraph.h:161
bool isExternal() const
Returns true if this node is an external node.
Definition CallGraph.cpp:38
mlir::SmallVectorImpl< Edge >::const_iterator iterator
Iterator over the outgoing edges of this node.
Definition CallGraph.h:123
iterator begin() const
Definition CallGraph.h:124
llvm::iterator_range< iterator > edgesOut() const
Definition CallGraph.h:127
mlir::Region * getCallableRegion() const
Returns the callable region this node represents.
Definition CallGraph.cpp:42
void addChildEdge(CallGraphNode *child)
Adds a reference edge to the given child node.
Definition CallGraph.cpp:62
bool hasChildren() const
Returns true if this node has any child edges.
Definition CallGraph.cpp:65
void addCallEdge(CallGraphNode *node)
Add an outgoing call edge from this node.
Definition CallGraph.cpp:59
void addAbstractEdge(CallGraphNode *node)
Adds an abstract reference edge to the given node.
Definition CallGraph.cpp:53
iterator end() const
Definition CallGraph.h:125
llzk::function::FuncDefOp getCalledFunction() const
Returns the called function that the callable region represents.
Definition CallGraph.cpp:47
This is a port of mlir::CallGraph that has been adapted to use the custom symbol lookup helpers (see ...
Definition CallGraph.h:167
size_t size() const
Definition CallGraph.h:223
CallGraph(mlir::Operation *op)
iterator begin() const
Definition CallGraph.h:220
iterator end() const
Definition CallGraph.h:221
CallGraphNode * getExternalCallerNode() const
Return the callgraph node representing an external caller.
Definition CallGraph.h:199
NodeIterator iterator
An iterator over the nodes of the graph.
Definition CallGraph.h:219
void dump() const
Dump the graph in a human readable format.
void print(llvm::raw_ostream &os) const
void eraseNode(CallGraphNode *node)
Erase the given node from the callgraph.
CallGraphNode * resolveCallable(mlir::CallOpInterface call, mlir::SymbolTableCollection &symbolTable) const
Resolve the callable for given callee to a node in the callgraph, or the external node if a valid nod...
CallGraphNode * lookupNode(mlir::Region *region) const
Lookup a call graph node for the given region, or nullptr if none is registered.
CallGraphNode * getUnknownCalleeNode() const
Return the callgraph node representing an indirect callee.
Definition CallGraph.h:204
CallGraphNode * getOrAddNode(mlir::Region *region, CallGraphNode *parentNode)
Get or add a call graph node for the given region.
static ChildIteratorType child_begin(NodeRef node)
Definition CallGraph.h:253
static NodeRef getEntryNode(NodeRef node)
Definition CallGraph.h:247
mapped_iterator< llzk::CallGraphNode::iterator, decltype(&unwrap)> ChildIteratorType
Definition CallGraph.h:252
static NodeRef unwrap(const llzk::CallGraphNode::Edge &edge)
Definition CallGraph.h:249
static ChildIteratorType child_end(NodeRef node)
Definition CallGraph.h:254
static nodes_iterator nodes_begin(llzk::CallGraph *cg)
Definition CallGraph.h:264
static nodes_iterator nodes_end(llzk::CallGraph *cg)
Definition CallGraph.h:265
static NodeRef getEntryNode(const llzk::CallGraph *cg)
The entry node into the graph is the external node.
Definition CallGraph.h:260
llzk::CallGraph::iterator nodes_iterator
Definition CallGraph.h:263