解析和修改LLVM IR代码

15

我希望能够读取(解析)保存在文本文件中的LLVM IR代码,并向其中添加一些自己的代码。我需要一些例子来展示如何使用LLVM提供的库来完成这个目的。所以,基本上我想要做的是从文本文件中将IR代码读入内存(也许LLVM库会将其表示为AST形式,我不知道),进行修改,例如在AST中添加一些节点,最后将AST写回IR文本文件。

虽然我需要读取和修改IR代码,但如果有人能够提供或引用一些仅读取(解析)它的示例,我将不胜感激。

5个回答

31

首先澄清一个明显的误解: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 并将其写回。


(*) LLVM 中没有 AST 表示 IR,因为它是一种类似汇编的简单语言。如果你往上走一步,到达 C 或 C++,你可以使用 Clang 将其解析为 AST,并在 AST 级别进行操作。然后,Clang 知道如何从其 AST 生成 LLVM IR。但是,你必须从 C/C++ 开始,而不是 LLVM IR。如果你只关心 LLVM IR,那就忘记 AST 吧。


谢谢Eli。你的回答非常有帮助。 - MetallicPriest
提醒一下,我认为应该使用小写字母p来书写"parseIRFile"。请参考http://llvm.org/docs/doxygen/html/IRReader_2IRReader_8h_source.html。 - user2027722
@user2027722:没错,LLVM的API经常变化,使得保持示例最新非常具有挑战性。我有一个Github仓库来解决这个问题:https://github.com/eliben/llvm-clang-samples,我尽可能地保持同步,它比随机的SO答案更具有参考价值。 - Eli Bendersky
错误:在此作用域中未声明“LLVMContext”。 - Carlo Wood

3
通常情况下,这需要通过实现一个LLVM pass/transform来完成。这样你就不必自己解析IR,因为LLVM会为你完成此项工作,并且你将在IR的面向对象内存表示上操作。这个链接是编写LLVM pass的入口点。然后,你可以查看任何已经与LLVM捆绑在一起的标准pass的实现(请查阅lib/Transforms)。

那最终是我要做的事情。但此时此刻,由于我处于学习阶段,我希望能够在文本文件中看到IR。 - MetallicPriest
3
我看不出问题所在。大多数LLVM工具都可以读写IR的文本表示。特别地,若要生成文本表示,请在命令行中添加“-S”开关。(同时请注意,二进制和文本表示完全等效。) - CAFxX

2

Opt工具接收LLVM IR代码,对其运行一个Pass,然后在另一端输出转换后的LLVM IR。

最容易开始编写的是lib\Transforms\Hello\Hello.cpp。修改它,使用源文件作为输入通过opt运行,检查输出。

除此之外,编写Pass的文档非常好。


1
最简单的方法是查看现有工具并从中窃取代码。在这种情况下,您可能需要查看llc的源代码。它可以将位码或.ll文件作为输入。您可以按照自己的方式修改输入文件,然后使用类似于llvm-dis中的代码编写文件,如果您想要一个文本文件。

1
如上所述,最好的方法是编写一个Pass。但是如果您只想迭代指令并对LLVM提供的内容执行某些操作,则可以使用InstVisitor类。它是一个为指令实现访问者模式的类。它非常直观易用,因此如果您想避免学习如何实现Pass,可以采用这种方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接