LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
CallGraphAnalyses.cpp
Go to the documentation of this file.
1//===-- CallGraphAnalyses.cpp -----------------------------------*- 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// The contents of this file are adapted from llvm/lib/Analysis/CallGraph.cpp.
9// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
10// See https://llvm.org/LICENSE.txt for license information.
11// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
12//
13//===----------------------------------------------------------------------===//
14
16
18
19#include <mlir/Interfaces/CallInterfaces.h>
20
21#include <llvm/ADT/DepthFirstIterator.h>
22#include <llvm/ADT/SmallVector.h>
23#include <llvm/Support/ErrorHandling.h>
24
25namespace llzk {
26
27using namespace function;
28
29CallGraphAnalysis::CallGraphAnalysis(mlir::Operation *op) : cg(nullptr) {
30 if (auto modOp = llvm::dyn_cast<mlir::ModuleOp>(op)) {
31 cg = std::make_unique<llzk::CallGraph>(modOp);
32 } else {
33 const char *error_message = "CallGraphAnalysis expects provided op to be a ModuleOp!";
34 op->emitError(error_message).report();
35 llvm::report_fatal_error(error_message);
36 }
37}
38
48 mlir::Operation *, mlir::AnalysisManager &am
49)
50 // getting the CallGraphAnalysis will enforce the need for a module op
51 : callGraph(am.getAnalysis<CallGraphAnalysis>().getCallGraph()) {}
52
54 mlir::CallableOpInterface A, mlir::CallableOpInterface B
55) const {
56 if (isReachableCached(A, B)) {
57 return true;
58 }
59
60 auto *startNode = callGraph.get().lookupNode(A.getCallableRegion());
61 if (!startNode) {
62 const char *msg = "CallGraph contains no starting node!";
63 A.emitError(msg).report();
64 llvm::report_fatal_error(msg);
65 }
73 auto dfsIt = llvm::df_begin<const CallGraphNode *>(startNode);
74 auto dfsEnd = llvm::df_end<const CallGraphNode *>(startNode);
75 for (; dfsIt != dfsEnd; ++dfsIt) {
76 const CallGraphNode *currNode = *dfsIt;
77 if (currNode->isExternal()) {
78 continue;
79 }
80 mlir::CallableOpInterface current = currNode->getCalledFunction();
81
82 // Update the cache according to the path before checking if B is reachable.
83 for (unsigned i = 0; i < dfsIt.getPathLength(); i++) {
84 mlir::CallableOpInterface ancestor = dfsIt.getPath(i)->getCalledFunction();
85 reachabilityMap[ancestor].insert(current);
86 }
87
88 if (isReachableCached(current, B)) {
89 return true;
90 }
91 }
92 return false;
93}
94
95} // namespace llzk
An analysis wrapper to compute the CallGraph for a Module.
CallGraphAnalysis(mlir::Operation *op)
This is a simple port of the mlir::CallGraphNode with llzk::CallGraph as a friend class,...
Definition CallGraph.h:36
bool isExternal() const
Returns true if this node is an external node.
Definition CallGraph.cpp:39
mlir::CallableOpInterface getCalledFunction() const
Returns the called function that the callable region represents.
Definition CallGraph.cpp:48
const llzk::CallGraph & getCallGraph() const
CallGraphReachabilityAnalysis(mlir::Operation *, mlir::AnalysisManager &am)
NOTE: the need for the mlir::Operation argument is a requirement of the mlir::getAnalysis method,...
bool isReachable(mlir::CallableOpInterface A, mlir::CallableOpInterface B) const
Returns whether B is reachable from A.