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