如何从给定 LLVM IR 的源代码中获取变量的所有行号?

Posted

技术标签:

【中文标题】如何从给定 LLVM IR 的源代码中获取变量的所有行号?【英文标题】:How to get all the line number of a variable from source code given LLVM IR? 【发布时间】:2019-09-25 10:21:03 【问题描述】:

我完全是 LLVM 的新手。我想知道如何从给定 LLVM IR 的源代码中获取特定变量的所有行号?

例如(显示 LLVM IR 的 sn-p)

store i32 0, i32* %i, align 4, !dbg !12
!12 = !DILocation(line: 2, column: 6, scope: !7)
%4 = load i32*, i32** %ip, align 8, !dbg !30
!30 = !DILocation(line: 7, column: 4, scope: !25)

我相信,通过检查 LLVM IR,获取任何变量的行号详细信息与在指令结束时访问 !dbg 有关。但我不知道如何访问这些信息。

另一个疑问是,如果使用指针存储变量的地址,我们如何知道它存储的是哪个变量的地址?

【问题讨论】:

【参考方案1】:

我相信,通过检查 LLVM IR,获取行号详细信息 对于任何变量都与在末尾访问 !dbg 有关 操作说明。但我不知道如何访问这些信息。

我相信你的假设是正确的。据我所知,所有信息都在那里:

第一条指令以!dbg !12 (store i32 0, i32* %i, align 4, !dbg !12) 结尾。

然后你应该找到以!12 开头的行。提示,调试信息通常位于模块的 LLVM IR 的底部。

在您的情况下是:!12 = !DILocation(line: 2, column: 6, scope: !7) !12 的指令来自生成此 LLVM IR 的源文件中的第 2 行第 6 列。源文件的名称也应该可用(通常位于 LLVM IR 的顶部)。

另一个疑问是指针是否用于存储变量的地址, 我们怎么知道它存储的是哪个变量的地址?

您需要自己推断该信息,例如通过数据流分析。不过,它在概念上相当简单,因为 LLVM IR is in SSA form 已经存在。

【讨论】:

答案是正确的,但可能会提到Instruction::getDebugLoc()。顺便说一句,以 !7 开头的行将具有文件名。或者可以从 DebugLoc 对象中获取它,这就是 IR 打印机所做的。 感谢 Morten 和 arnt 的回答,我看到通过 I->getDebugLoc() 我们可以获得有关变量行号的详细信息,但我关心的是如何获取所有行访问了吗?【参考方案2】:

LLVM 中的所有内容都是一个值,其中一些值会跟踪其用户。 42(一个常量 int)不会,但您感兴趣的 Values 会跟踪他们的用户。我有一些代码可以处理使用特定值的 phi 节点;以下是找到这些 phi 节点的三行代码:

for(auto u : someValue->users()) 
  PHINode * phi = dyn_cast<PHINode>(u);
  if(phi)
    …

请注意,这仅适用于模块内。如果您有一个全局值(例如许多函数),则不会跟踪模块外部的使用(例如大多数函数调用)。

【讨论】:

以上是关于如何从给定 LLVM IR 的源代码中获取变量的所有行号?的主要内容,如果未能解决你的问题,请参考以下文章

从 LLVM IR 获取精确的行/列调试信息

如何使 clang 编译为 llvm IR

解析和修改 LLVM IR 代码

如何从 LLVM IR 的指令元数据中提取操作数?

如何从 LLVM IR 打印浮点数?

LLVM极简教程: 第三章 LLVM IR代码生成