[midend-CallGraph]增加调用图分析遍
This commit is contained in:
242
src/include/midend/Pass/Analysis/CallGraphAnalysis.h
Normal file
242
src/include/midend/Pass/Analysis/CallGraphAnalysis.h
Normal file
@ -0,0 +1,242 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
#include "Pass.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明
|
||||
class CallGraphAnalysisResult;
|
||||
|
||||
/**
|
||||
* @brief 调用图节点信息
|
||||
* 存储单个函数在调用图中的信息
|
||||
*/
|
||||
struct CallGraphNode {
|
||||
Function* function; // 关联的函数
|
||||
std::set<Function*> callers; // 调用此函数的函数集合
|
||||
std::set<Function*> callees; // 此函数调用的函数集合
|
||||
|
||||
// 递归信息
|
||||
bool isRecursive; // 是否参与递归调用
|
||||
bool isSelfRecursive; // 是否自递归
|
||||
int recursiveDepth; // 递归深度(-1表示无限递归)
|
||||
|
||||
// 调用统计
|
||||
size_t totalCallers; // 调用者总数
|
||||
size_t totalCallees; // 被调用函数总数
|
||||
size_t callSiteCount; // 调用点总数
|
||||
|
||||
CallGraphNode(Function* f) : function(f), isRecursive(false),
|
||||
isSelfRecursive(false), recursiveDepth(0), totalCallers(0),
|
||||
totalCallees(0), callSiteCount(0) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 调用图分析结果类
|
||||
* 包含整个模块的调用图信息和查询接口
|
||||
*/
|
||||
class CallGraphAnalysisResult : public AnalysisResultBase {
|
||||
public:
|
||||
CallGraphAnalysisResult(Module* M) : AssociatedModule(M) {}
|
||||
~CallGraphAnalysisResult() override = default;
|
||||
|
||||
// ========== 基础查询接口 ==========
|
||||
|
||||
/**
|
||||
* 获取函数的调用图节点
|
||||
*/
|
||||
const CallGraphNode* getNode(Function* F) const {
|
||||
auto it = nodes.find(F);
|
||||
return (it != nodes.end()) ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取函数的调用图节点(非const版本)
|
||||
*/
|
||||
CallGraphNode* getMutableNode(Function* F) {
|
||||
auto it = nodes.find(F);
|
||||
return (it != nodes.end()) ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有函数节点
|
||||
*/
|
||||
const std::map<Function*, std::unique_ptr<CallGraphNode>>& getAllNodes() const {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查函数是否存在于调用图中
|
||||
*/
|
||||
bool hasFunction(Function* F) const {
|
||||
return nodes.find(F) != nodes.end();
|
||||
}
|
||||
|
||||
// ========== 调用关系查询 ==========
|
||||
|
||||
/**
|
||||
* 检查是否存在从caller到callee的调用
|
||||
*/
|
||||
bool hasCallEdge(Function* caller, Function* callee) const {
|
||||
auto node = getNode(caller);
|
||||
return node && node->callees.count(callee) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取函数的所有调用者
|
||||
*/
|
||||
std::vector<Function*> getCallers(Function* F) const {
|
||||
auto node = getNode(F);
|
||||
if (!node) return {};
|
||||
return std::vector<Function*>(node->callers.begin(), node->callers.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取函数的所有被调用函数
|
||||
*/
|
||||
std::vector<Function*> getCallees(Function* F) const {
|
||||
auto node = getNode(F);
|
||||
if (!node) return {};
|
||||
return std::vector<Function*>(node->callees.begin(), node->callees.end());
|
||||
}
|
||||
|
||||
// ========== 递归分析查询 ==========
|
||||
|
||||
/**
|
||||
* 检查函数是否参与递归调用
|
||||
*/
|
||||
bool isRecursive(Function* F) const {
|
||||
auto node = getNode(F);
|
||||
return node && node->isRecursive;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查函数是否自递归
|
||||
*/
|
||||
bool isSelfRecursive(Function* F) const {
|
||||
auto node = getNode(F);
|
||||
return node && node->isSelfRecursive;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取递归深度
|
||||
*/
|
||||
int getRecursiveDepth(Function* F) const {
|
||||
auto node = getNode(F);
|
||||
return node ? node->recursiveDepth : 0;
|
||||
}
|
||||
|
||||
// ========== 拓扑排序和SCC ==========
|
||||
|
||||
/**
|
||||
* 获取函数的拓扑排序结果
|
||||
* 保证被调用函数在调用函数之前
|
||||
*/
|
||||
const std::vector<Function*>& getTopologicalOrder() const {
|
||||
return topologicalOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取强连通分量列表
|
||||
* 每个SCC表示一个递归函数群
|
||||
*/
|
||||
const std::vector<std::vector<Function*>>& getStronglyConnectedComponents() const {
|
||||
return sccs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取函数所在的SCC索引
|
||||
*/
|
||||
int getSCCIndex(Function* F) const {
|
||||
auto it = functionToSCC.find(F);
|
||||
return (it != functionToSCC.end()) ? it->second : -1;
|
||||
}
|
||||
|
||||
// ========== 统计信息 ==========
|
||||
|
||||
struct Statistics {
|
||||
size_t totalFunctions;
|
||||
size_t totalCallEdges;
|
||||
size_t recursiveFunctions;
|
||||
size_t selfRecursiveFunctions;
|
||||
size_t stronglyConnectedComponents;
|
||||
size_t maxSCCSize;
|
||||
double avgCallersPerFunction;
|
||||
double avgCalleesPerFunction;
|
||||
};
|
||||
|
||||
Statistics getStatistics() const;
|
||||
|
||||
/**
|
||||
* 打印调用图分析结果
|
||||
*/
|
||||
void print() const;
|
||||
|
||||
// ========== 内部构建接口 ==========
|
||||
|
||||
void addNode(Function* F);
|
||||
void addCallEdge(Function* caller, Function* callee);
|
||||
void computeTopologicalOrder();
|
||||
void computeStronglyConnectedComponents();
|
||||
void analyzeRecursion();
|
||||
|
||||
private:
|
||||
Module* AssociatedModule; // 关联的模块
|
||||
std::map<Function*, std::unique_ptr<CallGraphNode>> nodes; // 调用图节点
|
||||
std::vector<Function*> topologicalOrder; // 拓扑排序结果
|
||||
std::vector<std::vector<Function*>> sccs; // 强连通分量
|
||||
std::map<Function*, int> functionToSCC; // 函数到SCC的映射
|
||||
|
||||
// 内部辅助方法
|
||||
void dfsTopological(Function* F, std::unordered_set<Function*>& visited,
|
||||
std::vector<Function*>& result);
|
||||
void tarjanSCC();
|
||||
void tarjanDFS(Function* F, int& index, std::vector<int>& indices,
|
||||
std::vector<int>& lowlinks, std::vector<Function*>& stack,
|
||||
std::unordered_set<Function*>& onStack);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief SysY调用图分析Pass
|
||||
* Module级别的分析Pass,构建整个模块的函数调用图
|
||||
*/
|
||||
class CallGraphAnalysisPass : public AnalysisPass {
|
||||
public:
|
||||
// 唯一的 Pass ID
|
||||
static void* ID;
|
||||
|
||||
CallGraphAnalysisPass() : AnalysisPass("CallGraphAnalysis", Pass::Granularity::Module) {}
|
||||
|
||||
// 实现 getPassID
|
||||
void* getPassID() const override { return &ID; }
|
||||
|
||||
// 核心运行方法
|
||||
bool runOnModule(Module* M, AnalysisManager& AM) override;
|
||||
|
||||
// 获取分析结果
|
||||
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<CallGraphAnalysisResult> CurrentResult; // 当前模块的分析结果
|
||||
|
||||
// ========== 主要分析流程 ==========
|
||||
|
||||
void buildCallGraph(Module* M); // 构建调用图
|
||||
void scanFunctionCalls(Function* F); // 扫描函数的调用
|
||||
void processCallInstruction(CallInst* call, Function* caller); // 处理调用指令
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
bool isLibraryFunction(Function* F) const; // 判断是否为标准库函数
|
||||
bool isIntrinsicFunction(Function* F) const; // 判断是否为内置函数
|
||||
void printStatistics() const; // 打印统计信息
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
Reference in New Issue
Block a user