Skip to content

Latest commit

 

History

History
422 lines (348 loc) · 20.6 KB

README.md

File metadata and controls

422 lines (348 loc) · 20.6 KB

4.万花筒:添加JIT和优化器支持

  • 第4章介绍
  • 琐碎常数折叠
  • LLVM优化通过
  • 添加JIT编译器
  • 完整的代码清单

4.1 第4章介绍

欢迎阅读“ 使用LLVM实现语言 ”教程的第4章。第1-3章描述了简单语言的实现,并增加了对生成LLVM IR的支持。本章介绍两种新技术:为您的语言添加优化器支持,以及添加JIT编译器支持。这些新增内容将演示如何为Kaleidoscope语言提供优质,高效的代码。

4.2 琐碎常数折叠

我们对第3章的演示优雅且易于扩展。不幸的是,它不会产生很棒的代码。但是,在编译简单代码时,IRBuilder确实给了我们明显的优化:

ready> def test(x) 1+2+x;
Read function definition:
define double @test(double %x) {
entry:
        %addtmp = fadd double 3.000000e+00, %x
        ret double %addtmp
}

此代码不是通过解析输入构建的AST的文字转录。那将是:

ready> def test(x) 1+2+x;
Read function definition:
define double @test(double %x) {
entry:
        %addtmp = fadd double 2.000000e+00, 1.000000e+00
        %addtmp1 = fadd double %addtmp, %x
        ret double %addtmp1
}

如上所述,常量折叠是一种非常常见且非常重要的优化:以至于许多语言实现者在其AST表示中实现常量折叠支持。

使用LLVM,您不需要AST中的此支持。由于构建LLVM IR的所有调用都通过LLVM IR构建器,因此构建器本身会在调用它时检查是否存在常量折叠机会。如果是这样,它只是执行常量折叠并返回常量而不是创建指令。

嗯,这很容易:)。实际上,我们建议IRBuilder在生成这样的代码时始终使用 。它的使用没有“语法开销”(你不必在任何地方使用常量检查来编译你的编译器)并且它可以大大减少在某些情况下生成的LLVM IR的数量(特别是对于具有宏预处理器的语言或使用很多常量)。

另一方面,IRBuilder它受到以下事实的限制:它在构建时与代码内联进行所有分析。如果你采取一个稍微复杂的例子:

ready> def test(x) (1+2+x)*(x+(1+2));
ready> Read function definition:
define double @test(double %x) {
entry:
        %addtmp =