我是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
我有一些问题:
答案 0 :(得分:1)
实际上,您的代码是正确的。截至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。