我是 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
我有一些问题:
最佳答案
实际上,您的代码是正确的。截止到llvm镜像最新的commit,call指令的opcode已经不是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 框架也在一些函数中使用它来处理一些极端情况。您永远无法读取或写入 'UserOp1'(或 UserOp2)指令到 IR。你不需要关心这种类型。另见此处:How to use UserOp1/UserOp2 instruction?
3) 您可能正在使用最新版本的框架,这就是为什么您会得到 56 的调用指令输出。您可能会感到困惑,因为您将此输出与稍微过时的 Instructions.def 文件进行了比较,该文件将调用指令映射到操作码 54。
关于llvm-ir - 如何判断LLVM IR中的指令是否为调用指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55437876/