首页 > 解决方案 > 如何判断 LLVM IR 中的指令是否为调用指令?

问题描述

我是 llvm 的新手,我正在尝试在 IR 中查找所有函数调用指令。我的代码如下所示:

  for (BasicBlock &BB : F) {
    for (Instruction &inst : BB) {

      errs() << "\n => " << inst << "\n";

      // if (dyn_cast<CallInst>(&inst) || dyn_cast<InvokeInst>(&inst)) {
      if(inst.getOpcode() == Instruction::Call || inst.getOpcode() == Instruction::Invoke) { 
        errs() << "\n callinst => " << inst << "\n";
      }
    }
  }

但这并不能找到函数调用指令。例如,对于这个指令:

call void @func2(i32* %num)

代码找不到它。

我为这个指令做了一些实验:

inst.getOpcodeName() == "call"
inst.getOpcode() == 56

但:

Instruction::Call == 54
Instruction::UserOp1 == 56

我有一些问题:

  1. 如何在 llvm IR 中找到函数调用?
  2. 指令::UserOp1 的用途是什么?
  3. 为什么上面的例子如此混乱?

标签: llvm-ir

解决方案


实际上,您的代码是正确的。截至 llvm 镜像中的最新提交,调用指令的操作码不再是 54,而是 56。2018 年 11 月 13 日更改为 55,2019 年 2 月 8 日更改为 56。

https://github.com/llvm-mirror/llvm/commit/ca8cb6852b59f4cbfc311415aab0d5a7ce0616b4#diff-3ac5806b20ed80b3be17bac3cdb4f799

https://github.com/llvm-mirror/llvm/commit/e3696113b639c8bf0b72d6c27dd76d6fdd8ebf61#diff-3ac5806b20ed80b3be17bac3cdb4f799

UserOp1 的操作码现在是 58。

对于您的问题:

1)识别调用指令以及任何其他类型指令的正确方法是使用isa<>()函数。模板参数是您要识别的类型,函数参数是您的指令指针。在您的示例中,您可以将 if 条件更改为:

if(isa<CallInst>(&inst) || isa<InvokeInst>(&inst)) {

为什么你宁愿这样做而不是比较操作码的原因是很明显的。如您所见,可以添加新指令并更改操作码。因此,比较操作码很快就会变得不兼容。如果类型匹配,无论操作码如何,使用“isa”函数将始终返回 true。在此处检查此功能的文档:http: //llvm.org/docs/ProgrammersManual.html#the-isa-cast-and-dyn-cast-templates

2) UserOp1 是一种只在内部使用的指令。据我所知,llvm 框架在一些功能中也使用它来处理一些极端情况。您永远无法向 IR 读取或写入“UserOp1”(或 UserOp2)指令。你不需要关心这种类型。另请参阅:如何使用 UserOp1/UserOp2 指令?

3) 您可能正在使用最新版本的框架,这就是为什么您会得到 56 的调用指令输出。您可能会感到困惑,因为您将此输出与稍微过时的 Instructions.def 文件进行了比较,该文件将调用指令映射到操作码 54。


推荐阅读