我是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";
}
}
}
但这不能找到函数调用指令。例如:
for this instruction: call void @func2(i32* %num)
the code can not find it.
And I did some experiment for this instucion:
inst.getOpcodeName() == "call"
inst.getOpcode() == 56
but:
Instruction::Call == 54
Instruction::UserOp1 == 56
我有一些问题:
实际上,你的代码是正确的。对于llvm镜像中的最新提交,调用指令的操作码不再是54,而是56.在2018年11月13日,它被改为55,而在2019年2月8日,它被改为56。
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)指令。你不必关心这种类型。另见:How to use UserOp1/UserOp2 instruction?
3)您可能正在使用最新版本的框架,这就是为什么您的呼叫指令输出为56的原因。您可能会感到困惑,因为您将此输出与稍微过时的Instructions.def文件进行了比较,该文件将调用指令映射到54的操作码。