You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LLVM技术问询:如何获取Alloca指令的使用者(变量使用者)

追踪LLVM中Alloca指令的使用者(栈变量引用)

嘿,我来帮你把这个需求落地得更顺畅——在LLVM里追踪Alloca指令的使用者,本质就是找对应栈变量的所有引用嘛。你现有的遍历模块、函数、基本块的框架是对的,但可以优化得更精准,还能处理一些细节问题。

先给你一套可直接用的代码实现:

#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"

using namespace llvm;

namespace {
struct AllocaUserTracker : public ModulePass {
  static char ID;
  AllocaUserTracker() : ModulePass(ID) {}

  bool runOnModule(Module &M) override {
    // 遍历模块内的每个函数
    for (Function &F : M) {
      // 跳过没有函数体的声明函数,避免无意义遍历
      if (F.isDeclaration()) continue;
      
      // 遍历函数里的每个基本块
      for (BasicBlock &BB : F) {
        // 遍历基本块里的每一条指令
        for (Instruction &I : BB) {
          // 尝试把当前指令转成AllocaInst,判断是不是栈分配指令
          if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
            errs() << "找到Alloca指令: " << *AI << "\n";
            errs() << "它的使用者列表:\n";
            
            // 遍历Alloca的所有直接使用者
            for (User *U : AI->users()) {
              Instruction *UserInst = cast<Instruction>(U);
              errs() << "  直接使用者: " << *UserInst << "\n";
              
              // 如果直接使用者是Load指令,那Load的使用者才是真正用到变量值的地方
              if (LoadInst *LI = dyn_cast<LoadInst>(UserInst)) {
                errs() << "    该Load指令的使用者(实际使用变量值的位置):\n";
                for (User *LoadUser : LI->users()) {
                  errs() << "      " << *cast<Instruction>(LoadUser) << "\n";
                }
              }
            }
            errs() << "-------------------------\n";
          }
        }
      }
    }
    // 我们只是分析IR,没有修改它,所以返回false
    return false;
  }
};
} // 匿名命名空间

char AllocaUserTracker::ID = 0;
// 注册这个Pass,方便用opt工具调用
static RegisterPass<AllocaUserTracker> X("track-alloca-users", "追踪Alloca指令的使用者");

关键细节说明

  1. 更简洁的遍历写法:用C++范围for循环替代老式的迭代器写法,代码可读性更高,LLVM 3.5及以上版本都支持这种写法。
  2. 安全的类型转换:用dyn_cast<AllocaInst>判断指令类型,比强制转换更安全,避免类型不匹配导致的崩溃。
  3. 区分直接使用者和实际变量使用者:Alloca的直接使用者通常是LoadInst、StoreInst或者GetElementPtrInst这类内存操作指令。如果你要找的是真正使用变量值的地方,就得进一步追踪LoadInst的使用者——这部分我已经在代码里做了示例。
  4. 跳过空函数:判断F.isDeclaration()跳过没有函数体的外部函数,避免做无用功。
  5. LLVM标准输出:用errs()输出结果,这是LLVM Pass中推荐的输出方式,和LLVM工具的输出流保持一致。

额外提示

  • 如果你的LLVM版本比较老(比如低于3.5),可以把范围for循环改成老式的迭代器写法,比如for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)。
  • 如果你需要过滤某些使用者(比如忽略StoreInst),可以在遍历AI->users()的时候加额外的类型判断。
  • 要是你需要修改这些使用者的行为(比如替换指令),记得把return false改成return true,告诉LLVM IR已经被修改过了。

内容的提问来源于stack exchange,提问作者mikasa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:51:41