解析和修改 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 代码的主要内容,如果未能解决你的问题,请参考以下文章

使用 LLVM c++ API 创建“类”定义

LLVM的IR指令及代码生成技术应用详解

将 LLVM-IR 转换为类似 C 的语言

LLVM 之 IR 篇:如何扩展 LLVM IR 优化器

LLVM 之 IR 篇:如何基于传统 Pass 框架扩展 LLVM IR 优化器

如何使 clang 编译为 llvm IR