LLZK 2.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 <llvm/ADT/DepthFirstIterator.h>
20#include <llvm/ADT/SmallVector.h>
21#include <llvm/Support/ErrorHandling.h>
22
23namespace llzk {
24
25using namespace function;
26
27CallGraphAnalysis::CallGraphAnalysis(mlir::Operation *op) : cg(nullptr) {
28 if (auto modOp = llvm::dyn_cast<mlir::ModuleOp>(op)) {
29 cg = std::make_unique<llzk::CallGraph>(modOp);
30 } else {
31 const char *error_message = "CallGraphAnalysis expects provided op to be a ModuleOp!";
32 op->emitError(error_message).report();
33 llvm::report_fatal_error(error_message);
34 }
35}
36
46 mlir::Operation *, mlir::AnalysisManager &am
47)
48 // getting the CallGraphAnalysis will enforce the need for a module op
49 : callGraph(am.getAnalysis<CallGraphAnalysis>().getCallGraph()) {}
50
52 if (isReachableCached(A, B)) {
53 return true;
54 }
55
56 auto *startNode = callGraph.get().lookupNode(A.getCallableRegion());
57 if (!startNode) {
58 const char *msg = "CallGraph contains no starting node!";
59 A.emitError(msg).report();
60 llvm::report_fatal_error(msg);
61 }
69 auto dfsIt = llvm::df_begin<const CallGraphNode *>(startNode);
70 auto dfsEnd = llvm::df_end<const CallGraphNode *>(startNode);
71 for (; dfsIt != dfsEnd; ++dfsIt) {
72 const CallGraphNode *currNode = *dfsIt;
73 if (currNode->isExternal()) {
74 continue;
75 }
76 FuncDefOp currFn = currNode->getCalledFunction();
77
78 // Update the cache according to the path before checking if B is reachable.
79 for (unsigned i = 0; i < dfsIt.getPathLength(); i++) {
80 FuncDefOp ancestorFn = dfsIt.getPath(i)->getCalledFunction();
81 reachabilityMap[ancestorFn].insert(currFn);
82 }
83
84 if (isReachableCached(currFn, B)) {
85 return true;
86 }
87 }
88 return false;
89}
90
91} // 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:39
bool isExternal() const
Returns true if this node is an external node.
Definition CallGraph.cpp:39
llzk::function::FuncDefOp 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(function::FuncDefOp &A, function::FuncDefOp &B) const
Returns whether B is reachable from A.
::mlir::Region * getCallableRegion()
Required by FunctionOpInterface.
Definition Ops.h.inc:834