LLVM-tutor 学习笔记4: StaticCallCounter

这篇文章详细介绍了如何创建一个基于LLVM的analysispass,StaticCallCounter,用于统计模块中函数调用次数。它通过遍历IR模块,利用动态分派技术检测call指令,存储并累加每个函数的调用计数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Basic

这是一个analysis pass, 在程序的编译器静态分析每个函数的调用次数。

与之前一样,为了输出 analysis pass 的结果, 我们需要一个专门输出结果的 printing pass。

由于 printing pass 和 pass manger 注册和之前类似, 本文不再描述。

struct StaticCallCounter : public llvm::AnalysisInfoMixin<StaticCallCounter> 
 

因为要统计各个函数之间的相互调用, 这次选用了 moudle 粒度的 pass

runOnModule

主要逻辑是一步步地从 Module 遍历到每一条指令, 再检查每条指令是否是函数调用,统计函数调用的信息。

在判断一个指令是否是 call 指令时, 使用了动态分派的技巧。

如果分派后的结果为 nullptr 则说明该指令不是 call 类指令。


StaticCallCounter::Result StaticCallCounter::runOnModule(llvm::Module &M) {
  llvm::MapVector<const llvm::Function *, unsigned> Res;
  for (auto &Func : M) {
    for (auto &BB : Func) {
      for (auto &Ins : BB) {
        auto *CB = dyn_cast<CallBase>(&Ins);
        if (nullptr == CB) {
          continue;
        }

        auto DirectInvoc = CB->getCalledFunction();
        if (nullptr == DirectInvoc) {
          continue;
        }

        auto CallCount = Res.find(DirectInvoc);
        if (Res.end() == CallCount) {
          CallCount = Res.insert(std::make_pair(DirectInvoc, 0)).first;
        }
        ++CallCount->second;
      }
    }
  }
  return Res;
}

总结

一个 analysis pass (假设名为 foo)

  1. 要继承 AnalysisInfoMixin<foo>。 
  2. 它的分析结果的类型总是 foo::Result。 
  3. 它的分析方法的入口函数总是 run
  4. run 的第一个参数是对应粒度的 IR, 第二个参数是对应粒度的 analysis manger。 
  5. 总有一个类型为 llvm::AnalysisKey 的私有变量 Key 用于 analysis manger 对 analysis 的定位和管理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值