CompilerRT 项目用于为硬件不支持的低级功能提供特定雨目标的支持。
例如,32位目标通常缺少支持64位除法的指令,CompilerRT通过提供特定于目标并经过优化的功能来解决这个问题,该功能在使用32位指令的同时实现了64位除法,提供相同的功能,因此是LLVM项目中libgcc的替代品,此外,还具有对地址内存清洗工具的运行时支持,你可以从http://llvm.org/release/download.html 上查找更多的版本。
基于LLVM的编译工具链中室一个关键组件,因此上一章已经介绍了如何安装CompilerRT。如果你仍然没有这个组件,记住将其源代码放入LLVM源代码树中的projects 文件夹内,如下命令序列所示。
wget http://llvm.org/release/3.4/compiler-rt-3.4.src.tar.gz
tar xzf compiler-rt-3.4.src.tar.gz
如果你愿意,可以使用它的SVN存储库
cd llvm/projects
svn checkout http://llvm.org/svn/llvm-project/compiler-rt/trunk
除了SVN存储库,可以通过GIT镜像下载
2.1.3 实验Compiler_RT
要查看编译器运行时库启动时的典型情况,可以编写一个执行64位除法的C程序来做一个简单的实验。
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main()
{
uint64_t a = 0ULL, b = 0ULL;
scanf("%lld %lld", &a, &b);
printf("64-bit devision is %lld\n", a/b);
return EXIT_SUCCESS;
}
-m32 标志指示编译器生成32位x86程序,而-S 标志将用于在test-32bit.S中为此程序生成x86汇编语言文件。 如果查看这个文件,就回看到每当程序需要执行除法时都会有一个有趣的调用
call __udivdi3
该函数由Compiler-RT定义,并演示了将在何处使用该库,但是,如果省略-m32标志并使用64位x86编译器,即生成test-64bit.S汇编文件的第二个编译器命令一样,则不会再看到需要CompilerRT协助的程序,因为可以通过单个指令完成除法运算。
divq -24(%rbp)
2.2 使用DragonEgg插件
如前所述,LLVM项目初期依赖于GCC,没有自己的C/C++前端。在那时,你需要下载一个名为llvm-gcc 的GCC源代码树并将其完整编译,才能使用LLVM。由于编译涉及完整的GCC软件包,需要知道自己重建GCC所需的所有必要GNU知识,因此这是一项非常耗时且棘手的任务。DragonEgg项目利用GCC插件系统提出了一个聪明的解决方案,它将LLVM逻辑分离到它自己的一个更小的代码树中。这样,用户不再需要重建整个GCC包,而只需要构建一个插件,然后将其加载到GCC中即可,DragonEgg也是LLVM项目下唯一获得GPL授权的项目。
即使Clang已经兴起,DragonEgg至今仍然存在,因为Clang只处理C和C++语言,而GCC能够解析更多类型的语言,通过使用DragonEgg插件,可以使用GCC作为LLVM编译器的前端,从而能够编译GCC支持的大多数语言,包括Ada,C,C++和Fortrain 并且支持部分Go Java,ObjectiveC,Objective C++。
该插件用LLVM的相应部分替代GCC的中间和后端,并自动执行所有编译步骤,能满足你对一流的编译器驱动程序的期望。图2-1是这种场景的编译流程。
如果你愿意,可以使用-fplugin-arg-dragonegg-emit-ir -S标志将编译过程序停止在LLVM IR生成阶段,并使用LLVM工具分析和调查前端的结果,或者手动使用LLVM工具完成编译过程,我们将很快看一个例子。
由于DragonEgg是一个LLVM分支项目,维护人员无法以维护LLVM主项目那样的频率更新该项目。在编写本书时,DragonEgg最新的稳定版本时3.3版本,并且被绑定到LLVM 3.3的工具集中。因此,如果你生成LLVM代码则不能使用3.3以外版本的LLVM工具分析此文件,也不能进行优化或继续编译。你可以在http://dragonegg.llvm.org 上找到DragonEgg官方网站。
2.2.1 构建DragonEgg
要编译并安装DragonEgg,请首先从http://llvm.org/release/3.3/dragonegg=3.3.src.tar.gz 获取源代码,对于ubuntu,请使用以下命令。
wget http://llvm.org/release/3.3/dragonegg-3.3.src.tar.gz
tar xvzf dragonegg-3.3.src.tar.gz
cd dragonegg.src
如果你希望从SVN库中获取最新但不稳定的源代码,请使用以下命令
svn checkout http://llvm.org/svn/llvm-project/deagonegg/trunk dragonegg
对于GIT镜像,请使用以下命令。
git clone http://llvm.org/git/dragonegg.git
要执行编译和安装,需要提供LLVM安装路径。LLVM版本必须与正在安装的DragonEgg版本相匹配。假设使用与弟1章中相同的安装前缀/usr/local/llvm ,并假设GCC 4.6已经安装并存在于你的shell PATH变量中,则应使用以下命令
GCC-gcc-4.6 LLVM_CONFIG=/usr/local/llvm/bin/llvm-config make
cp -a dragonegg.so /usr/local/llvm/lib
请注意,该项目缺少自动工具或CMake项目文件,你应该使用make命令直接构建。如果你的gcc命令已经提供了你需要的正确GCC版本。则可以在运行make时省略GCC = gcc4.6前缀。构建后将生成名为dragonegg.so并且格式为共享库的插件,可以使用GCC命令行调用该插件。