llvm-ir - 如何判断 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
我有一些问题:
- 如何在 llvm IR 中找到函数调用?
- 指令::UserOp1 的用途是什么?
- 为什么上面的例子如此混乱?
解决方案
实际上,您的代码是正确的。截至 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)指令。你不需要关心这种类型。另请参阅:如何使用 UserOp1/UserOp2 指令?
3) 您可能正在使用最新版本的框架,这就是为什么您会得到 56 的调用指令输出。您可能会感到困惑,因为您将此输出与稍微过时的 Instructions.def 文件进行了比较,该文件将调用指令映射到操作码 54。
推荐阅读
- haskell - 如何在 Haskell 中导入 Math.X?
- python - 熊猫:asfreq 时间序列的奇怪行为
- string - Why commas and underscore is using in Golang. Explain the line 12 in the below code?
- rust - 如何配置 actix-web 以接受来自任何来源的 CORS 请求?
- python - what is the best way to save the memory and save large numpy array to the h5py file?
- microsoft-graph-api - Microsoft Delta Query not returing openextension defined while creating event
- javascript - Is there a method to check if a container needs scrollbars?
- jmeter - Jmeter action based on assertion result
- javascript - 如何从开发人员工具的检查元素中隐藏 html 内容?
- android - DJI MSDK 的哪些功能受“库防失真”模块的影响?