工具
opt:这是一个旨在IR级对程序进行优化的工具。输入必须是LLVM位码文件(编码的LLVM IR),并且生成的输出文件必须具有相同类型。
llc:这是一个通过特定后端将LLVM位码转换成目标机器汇编语言文件或者目标文件的工具。你可以通过传送参来选择优化级别、打开调试选项以及启用或禁用特定于目标的优化。
llvm-mc:这个工具能狗汇编指令并生成诸如ELF、Macho和PE等对象格式的目标文件。它也可以反汇编相同的对象,从而转储这些指令的相应的汇编信息和内部LLVM机器指令数据结构。
lli:这个工具是LLVM IP的解释器和JIT编译器
llvm-link:这个工具将几个LLVM位码链接在一起,以产生一个包含所有输入的LLVM位码。
llvm-as:该工具将人工可读的LLVM IR 文件(称为LLVM汇编码)转换位LLVM位码
llvm-dis:这个工具将LLVM码解码成LLVM汇编码
JIT 编译器(Just-In-Time Compiler)是一种在程序运行时将字节码编译为机器码的编译器。它结合了解释器和静态编译器的优点,可以提高程序的性能。
JIT 编译器的工作原理是:
- 程序启动时,JIT 编译器会将字节码加载到内存中。
- 程序执行时,JIT 编译器会监控程序的执行情况。
- 如果发现某个代码块被执行了多次,JIT 编译器会将该代码块编译为机器码。
- 下次程序执行该代码块时,JIT 编译器会直接执行机器码,而不需要解释字节码。
JIT 编译器的优点包括:
- 可以提高程序的性能。
- 可以支持动态语言。
- 可以支持多平台。
JIT 编译器的缺点包括:
- 增加了程序的启动时间。
- 增加了程序的内存使用。
JIT 编译器在许多语言中都有应用,包括 Java、C#、JavaScript 等。
以下是一些具体的例子:
- Java 语言的 JVM 使用 JIT 编译器。
- C# 语言的 CLR 使用 JIT 编译器。
- JavaScript 语言的 V8 引擎使用 JIT 编译器。
JIT 编译器是现代编译器技术的重要组成部分,在提高程序性能方面发挥着重要作用。
例子
我们编写两个C文件
main.c
#include<stdio.h>
int sum (int x,int y);
int main()
{
int r=sum(3,4);
printf("r=%d\n",r);
return 0;
}
sum.c
int sum(int x,int y)
{
return x+y;
}
当我们直接使用
clang main.c sum.c -o sum
这条命令会直接帮我们生成可执行文件
我们使用独立的工具也可以达到相同的结果
clang -emit-llvm -c main.c -o main.bc
clang -emit-llvm -c sum.c -o sum.bc
我们来理解这个命令
-emit-llvm标志告诉clang根据是否存在-c或-S标志生成LLVM 位码或LLVM汇编码文件
-emit-llvm和-c标志一起使用,告诉clang以LLVM位码格式生成一个目标文件。
使用-flto -c标志组合可以得到相同的结果。
使用如下命令就可以生成人们可阅读的LLVM汇编码
clang -emit-llvm -S main.c -o main.ll
clang -emit-llvm -S sum.c -o sum.ll
.bc文件就是生成的二进制文件
.ll文件是LLVM IR语言,在我的另一篇博客中也有写
https://blog.csdn.net/m0_72827793/article/details/135374432
请注意:如果没有-emit-llvm或-ftlo标志,则-c标志生成一个包含目标机器语言的目标文件,而将-S生成目标汇编语言文件。这种行为与GCC兼容
两种生成运行文件方式
第一种:
llc -filetype=obj main.bc -o main.o
llc -filetype=obj sum.bc -o sum.o
clang main.o sum.o -sum
第二种:
llvm-link main.bc sum.bc -o sum.linked.bc
llc -filetype=obj sum.linked.bc -o sum.linked.o
clang sum.linked.o -o sum
-filetype=obj参数指定输出一个目标文件,而不是目标汇编文件!!