解析和修改 LLVM IR 代码
Posted
技术标签:
【中文标题】解析和修改 LLVM IR 代码【英文标题】:Parsing and Modifying LLVM IR code 【发布时间】:2012-02-06 21:13:46 【问题描述】:我想读取(解析)LLVM IR 代码(保存在文本文件中)并向其中添加一些我自己的代码。我需要一些这样做的例子,也就是说,这是如何通过使用 LLVM 提供的库来完成的。所以基本上我想要的是将IR代码从文本文件读入内存(也许LLVM库以AST形式表示它,我不知道),进行修改,比如在AST中添加更多节点,然后最后写在 IR 文本文件中返回 AST。
虽然我需要阅读和修改 IR 代码,但如果有人能提供或参考一些刚刚阅读(解析)它的示例,我将不胜感激。
【问题讨论】:
【参考方案1】:首先,纠正一个明显的误解:LLVM 是一个用于操作 IR 格式代码的框架。看不到 AST (*) - 您读取 IR,转换/操作/分析它,然后将 IR 写回。
阅读 IR 真的很简单:
int main(int argc, char** argv)
if (argc < 2)
errs() << "Expected an argument - IR file name\n";
exit(1);
LLVMContext &Context = getGlobalContext();
SMDiagnostic Err;
Module *Mod = ParseIRFile(argv[1], Err, Context);
if (!Mod)
Err.print(argv[0], errs());
return 1;
[...]
此代码接受文件名。这应该是一个 LLVM IR 文件(文本)。然后它继续将其解析为Module
,它表示 LLVM 内部内存格式的 IR 模块。然后可以使用 LLVM 拥有的各种通行证进行操作,或者您自己添加。查看 LLVM 代码库中的一些示例(例如 lib/Transforms/Hello/Hello.cpp
)并阅读此内容 - http://llvm.org/docs/WritingAnLLVMPass.html。
将 IR 吐回到文件中更加容易。 Module
类只是将自身写入流:
some_stream << *Mod;
就是这样。
现在,如果您对想要对 IR 代码进行的具体修改有任何具体问题,那么您真的应该问一些更集中的问题。我希望这个答案能告诉你如何解析 IR 并将其写回。
(*) IR 在 LLVM 中没有 AST 表示,因为它是一种简单的类汇编语言。如果您更上一层楼,使用 C 或 C++,您可以使用 Clang 将其解析为 AST,然后在 AST 级别进行操作。然后,Clang 知道如何从其 AST 生成 LLVM IR。但是,您必须从这里开始使用 C/C++,而不是 LLVM IR。如果你只关心 LLVM IR,那就别管 AST。
【讨论】:
谢谢伊莱。你的回答很有帮助。 请注意,我认为它应该是带有小写 p 的“parseIRFile”。 llvm.org/docs/doxygen/html/IRReader_2IRReader_8h_source.html @user2027722:是的,LLVM API 变化如此频繁,以至于很难让样本保持最新。我有一个 Github 存储库:github.com/eliben/llvm-clang-samples,我尽可能保持同步,它比随机 SO 答案更像是一个事实来源 错误:“LLVMContext”未在此范围内声明【参考方案2】:这通常通过实现 LLVM 传递/转换来完成。这样,您根本不必解析 IR,因为 LLVM 会为您完成它,并且您将在 IR 的面向对象的内存表示中进行操作。
This 是编写 LLVM pass 的入口点。然后,您可以查看与 LLVM 捆绑在一起的任何已实现的标准通行证(查看 lib/Transforms)。
【讨论】:
这就是我最终要做的。但此时,由于我处于学习阶段,我希望能够在文本文件中看到 IR。 我没有看到问题。大多数 LLVM 工具可以读/写 IR 的文本表示。特别是,要发出文本表示,请将 -S 开关添加到命令行。 (另外,永远记住二进制和文本表示是绝对等价的)。【参考方案3】:Opt 工具获取 llvm IR 代码,对其运行一次传递,然后在另一侧输出转换后的 llvm IR。
最容易开始黑客攻击的是 lib\Transforms\Hello\Hello.cpp。破解它,使用您的源文件作为输入运行 opt,检查输出。
除此之外,写pass的文档真的很不错。
【讨论】:
【参考方案4】:最简单的方法是查看现有工具之一并从中窃取代码。在这种情况下,您可能需要查看 llc 的源代码。它可以采用位码或 .ll 文件作为输入。你可以以任何你想要的方式修改输入文件,然后如果你想要一个文本文件,则使用类似于 llvm-dis 中的代码的东西写出文件。
【讨论】:
【参考方案5】:如上所述最好的方法就是写一个pass。但是,如果您想简单地遍历指令并使用 LLVM 提供的 InstVisitor 类做一些事情。它是一个实现访问者模式以获取指令的类。这对用户来说非常直接,所以如果你想避免学习如何实现通行证,你可以求助于它。
【讨论】:
以上是关于解析和修改 LLVM IR 代码的主要内容,如果未能解决你的问题,请参考以下文章