编译器llvm
㈠ LLVM相比于GCC,有哪些技术上的优势
首先简要介绍一下LLVM。LLVM是一个针对LLVM Intermediate Representation(IR,中间语言)的跨平台优化编译器,它的模块化设计很好,使得这个编译器中的很多功能可以被单独实现或者改进,这与其C++实现无法分开。由此,LLVM可以被设计成很多语言编译器实现的后端,负责处理程序优化和跨平台,而前端只需将程序转换成LLVM IR即可。比如说,Clang就是基于LLVM实现的C/C++编译器,它的主要功能就是将C/C++程序转换成LLVM IR,然后由LLVM负责后续的工作。
LLVM技术上的(最大)优势就在于它的模块化设计。在LLVM中,IR的解析,优化,汇编码的生成,寄存器分配,汇编码优化以及机器码生成,各种类型的二进制文件生成全部都是接口定义清晰的模块完成的,很容易分别改进或者添加定制功能。而且由于LLVM的C++实现,很多模块理解和使用比较容易。这些特性使得LLVM可以很容易地被用在科研和生产实践当中。反观GCC,模块化做得不如LLVM好,这使得它定制或者改进比较不方便。
㈡ Go语言编译器TinyGo,基于LLVM,在微控制器和小系统上编译和运行
TinyGo是一个为微控制器、WebAssembly(Wasm)和命令行工具等小型场景设计的Go语言编译器。TinyGo重用了Go语言工具和LLVM使用的库,以编译用Go语言编写的程序。目前,该项目在GitHub上已经积累了10.1k的Star。
如下为一个示例程序,当运行在任何支持的带板载LED的主板上时,则会点亮内置LED。
上述程序可以在单片机、Adafruit ItsyBitsy M0微控制器或任何支持的带内置LED的板上进行编译和不需要修改的运行,只要设置正确的TinyGo编译器目标即可。例如,设置如下目标可以编译和点亮 单片机。
项目概述
TinyGo项目旨在将Go语言引入到具有单进程或核心的微控制器和小系统。TinyGo类似于emgo,但主要的区别在于作者想要保留Go内存模型。另一个区别在于TinyGo在内部使用LLVM,因而可以获得更小更高效的代码以及更高的灵活性。
创建TinyGo项目的初衷是,如果Python可以在微控制器上运行,Go语言当然也应该能够在更低级微设备上运行。
支持设备
你可以为微控制器、WebAssembly和Linux编译TinyGo程序。目前,TinyGo支持以下85种微处理器板。
更多技术细节请参阅原项目。
㈢ LLVM - 工具
LLVM工具通过调用LLVM的一部分库,实现库的功能,通常使用编译器或者开发编译器的人会用到这些工具。
这是一个在LLVM IR级别做程序优化的工具,输入和输出都是LLVM IR。编译器,或者基于LLVM做优化的开发者通常会使用这一标准工具来查看优化的效果。它也提供了很多option, 可以执行某一特定的pass。
这是微观意义上的LLVM编译器,不同于gcc的编译器,它的输入是LLVM IR,输出是汇编文件或者是目标文件。通过-filetype=asm或者-filetype=obj来指定输出是汇编文件还是目标文件,若生成是目标文件,llc会调用LLVM中的汇编输出的代码库来工作(注意这个汇编器和gcc的汇编器也不同,它输入的是MI,是一种后端的中间表示)。除此之外,还可以用-On来指定优化级别(llc默认优化级别是-O2),或者其他一些参数。
(.bc文件换成.ll文件也可以)
这是LLVM汇编器,它输入汇编文件,输出目标文件, 类似于gnu中的as命令。同时,它也可以反汇编,指定特殊参数(–disassemble)就行。可以发现,llc和llvm-mc都会调用到输出目标文件的库,也就是MCObjectStreamer。
这个工具是LLVM IR的解释器,也是一个JIT编译器。LLVM可以把C语言翻译成LLVM IR,然后解释执行,与Java的那一套类似,这也是最初LLVM编写时的实现(一个虚拟机运行IR)。
最早看到这个工具,以为是链接器,其实它是IR级别的链接器,链接的是IR文件。谈到这里,可以说一下LLVM针对多个源文件编译时的两种目标码输出方式。
第一种是LLVM先通过前端把每个源文件单独翻译成IR级别,然后用llvm-link链接成一个IR,然后再经过优化、后端等步骤生成目标文件,使用llvm-link的同时,可以使用链接时优化。不过需要注意,这种方式同样需要最终调用链接器,将这个目标文件链接成可执行文件。
第二种是LLVM通过前端把每个源文件单独翻译后,再单独经过优化、后端等工作,将每个源文件生成目标文件,之后再调用链接器,将所有目标文件链接成可执行文件。
这是针对LLVM IR的汇编器,其实名字里带as,实际上不是gcc那个as,它的功能是将.ll文件翻译为.bc文件,LLVM项目里,.ll称为LLVM汇编码,所以llvm-as也就是IR的汇编器了。
与llvm-as刚好相反,IR的反汇编器,用来将.bc文件翻译为.ll文件。
最后也提一下clang,它也是现在LLVM项目中一个很重要的前端工具。clang能够调用整个编译器的流程,也就是上边其他工具调用的库,它很多都同样会调用。clang通过指定-emit-llvm参数,可以配合-S或-c生成.ll或.bc文件,这样我们就能把Clang的部分和LLVM的后端分离开来独立运行,对于观察编译器流程来说,很实用。
还有一些其他工具,就不举例了,可以查看LLVM项目路径下/src/tools/中查看。
㈣ 如何更好的掌握编译器的设计与实现
1. 阅读相关书籍:编译原理、编译器设计、编译器实现等;
2. 自学相关编程语言:C、C++、Java等;
3. 实践:可以使用开源的编译器框架,例如ANTLR,搭建自己的编译器;
4. 了解编译器的各个组成部分,并学习它们的工作原理;
5. 阅读技术文章,了解编译器的设计和实现的最新进展;
6. 加入开源项目,编写和维护编译器;
7. 在论坛上交流,和更多的编译器开发者分享心得体会;
8. 参加学术会议,接触到最新的研究成果;
9. 尝试着自己设计一个编译器,用实践来加深理解。