编译器之LLVM

计算机发展到今天,有两个非常著名的编译器是我们经常用到的-GCC和Clang。GCC是古老的编译器,来自于贝尔实验室,可以说是上个世纪的产物,但是并没有因为古老而放弃使用,GCC仍然在更新,目前已经更新到gcc-12(截止2022-10-30)。而Clang是新出来的编译器,新事物有它的先进性,Clang也是如此。Clang来源于llvm项目,他是 Chris Lattner在大学期间搞的一个兴趣项目,后来入职Apple以后,Apple支持他开发一个全新的编译器来支持当初的Object-c,后来在llvm基础上产生了很多比较流行的语言,包括Rust、Swift等等。有人问那我们用llvm不就好了吗? 答案是否定的。因为有些语言如fortran,Clang还没有完全支持,这是一个非常古老的用于科学计算的语言,GCC是默认支持的,同时各个发行版本linux都默认支持gcc,可以说gcc是目前使用最广泛的编译器。而Clang则不是,它需要自己下载安装(Mac OS默认使用Clang作作为编译器,)

同时通过llvm提供的组件,我们很快可以搭建出不同语言的前端,进行语法树分析,而不需要自己动手写ast等操作,可以复用llvm提供的各种核心库来操作。llvm提供了各种数据结构以及方法,让我们快速分析。

1
2
cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTS="mlir;clang" -DLLVM_BUILD_EXAMPLES=ON -DLLVM_TARGETS_TO_BUILD="X86;NVPTX" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON -DMLIR_ENABLE_BINDINGS_PYTHON=ON -DLLVM_CCACHE_BUILD=ON
cmake --build . --target all

LLVM的结构

上文提到的Clang是llvm的一个子项目。它是一个编译器前端,官方给的定义是Clang is an “LLVM native” C/C++/Objective-C compiler, which aims to deliver amazingly fast compiles, extremely useful error and warning messages and to provide a platform for building great source level tools.,除了Clang,llvm还有一些其他的组件,具体参考llvm.

这里我想说的是,编写好了高级语言之后,我们可以将高级语言接入到llvm生态,一旦接入,我们可以产生很多很多种后端二进制代码,包括arm、x86、riscv等等,原因就是llvm作为一个中间表达,我们将高级语言lowing到llvmir,然后通过各种pass对llvmir进行优化,再然后对llvmir进行selectionDAG指令选择,对一些指令进行合法化替换,再产生对应target的二进制代码。

同时llvm近两年出现了mlir项目,这是一个多阶段的编译器结构。目前看主要是应用在深度神经网络中,虽然它并不是只是给深度学习用的,主要的思想是将一些深度学习框架的高级表示嵌入到mlir中,然后通过mlir的官方项目lowing到llvmir,然后再到不同的平台上去运行。

因此,我认为我们未来的方向是

  1. 将自己的模型嵌入到mlir生态。
  2. 将llvmir产生自己后端的ISA指令以及bytecode去运行。

Reference