认识 LLVM
简介
LLVM是一套提供编译器基础设施的开源项目,是用 C++ 编写,包含一系列模块化的编译器组件和工具链,用来开发编译器前端和后端。它是为了任意一种编程语言而写成的程序,利用虚拟技术创造出编译时期、链接时期、执行时期以及“闲置时期”的优化。
LLVM的命名源自于底层虚拟机(Low Level Virtual Machine)的首字母缩写,导致不了解它的人以为它是类似于 JVM(Java Virtual Machine) 的虚拟机,实际上这个项目的范围并不局限于创建一个虚拟机,而是包括 LLVM 中介码(LLVM IR)、LLVM调试工具、LLVM C++ 标准库等一系列编译工具及低端工具技术的集合。
传统的静态编译器设计是三阶段设计,其主要组件是前端、优化器和后端。
前端负责词法分析、语法分析、语义分析、生成中间代码等功能。
优化器负责进行各种转换以尝试提高代码的运行时间,例如消除冗余计算,并且通常或多或少独立于语言和目标。
后端(也称为代码生成器)负责将代码映射到目标指令集。除了编写正确的代码外,它还负责生成利用所支持架构的不寻常特性的良好代码。编译器后端的常见部分包括指令选择、寄存器分配和指令调度。
该模型同样适用于解释器和 JIT 编译器。JVM 也是该模型的一个实现,它使用 Java 字节码作为前端和优化器之间的接口。
而 LLVM 被设计为支持多种源语言或目标架构,它提供了一套适合编译器系统的中间语言,如果编译器在其优化器中使用这个中间语言表示,则可以为任何可以编译到它的语言编写前端,并且可以为任何可以从它编译的目标编写后端。
使用这种设计,移植编译器以支持新的源语言只需要实现新的前端,即可以重用现有的优化器和后端;同样想增加支持新的目标架构也只需要实现新的后端。而如果按传统设计,前端和后端实际是耦合在一起,实现新的源语言或支持新的目标架构将需要从头开始,要支持 N 目标和 M 源语言将需要 N*M 个编译器。
LLVM IR
LLVM提供了一套适合编译器系统的中间语言(Intermediate Representation,IR),有大量变换和优化都围绕其实现,经过变换和优化后的中间语言,可以转换为目标平台相关的汇编语言代码。
该中间语言与具体的语言、指令集、类型系统无关,其中每条指令都是静态单赋值形式(SSA), 即每个变量只能被赋值一次。这有助于简化变量之间的依赖分析。
以下是简单的 LLVM IR 代码:
define i32 @add1(i32 %a, i32 %b) {
entry:
%tmp1 = add i32 %a, %b
ret i32 %tmp1
}
define i32 @add2(i32 %a, i32 %b) {
entry:
%tmp1 = icmp eq i32 %a, 0
br i1 %tmp1, label %done, label %recurse
recurse:
%tmp2 = sub i32 %a, 1
%tmp3 = add i32 %b, 1
%tmp4 = call i32 @add2(i32 %tmp2, i32 %tmp3)
ret i32 %tmp4
done:
ret i32 %b
}
上述代码对应的 C 语言代码为:
unsigned add1(unsigned a, unsigned b) {
return a+b;
}
unsigned add2(unsigned a, unsigned b) {
if (a == 0) return b;
return add2(a-1, b+1);
}
从这个例子可以看出,LLVM IR 是一种强类型的精简指令集( RISC )。像真正的 RISC 指令集一样,它支持简单指令的线性序列,如加法、减法、比较和分支。这些指令采用三地址形式,这意味着它们接受一定数量的输入并在不同的寄存器中产生结果。LLVM IR 支持标签,通常看起来像一种奇怪的汇编语言形式。
与大多数 RISC 指令集不同,LLVM 使用简单的类型系统进行强类型化(例如,i32
是一个 32 位整数,i32**
是一个指向 32 位整数的指针),并且机器的一些细节被抽象掉了。例如,调用约定是通过指令和显式参数 call
抽象出来的。ret
与机器代码的另一个显着区别是 LLVM IR 不使用一组固定的命名寄存器,它使用一组无限的以 % 字符命名的临时寄存器。
LLVM IR 支持三种表达形式:人类可读的汇编、在C++中对象形式、序列化后的 bitcode 形式。
编译
LLVM允许代码被静态的编译,包含在传统的GCC系统底下,者通过实时编译(JIT)机制将中间表示转换为机器码(类似 Java)。
LLVM 类型系统包含基本类型(整数或是浮点数)及五个复合类型(指针、数组、向量、结构及函数),在LLVM具体语言的类型建制可以以结合基本类型来表示,举例来说,C++所使用的class可以被表示为结构、函数及函数指针的数组所组成。
LLVM 提供了 Clang 作为官方的编译器前端,同时支持 C、C++、Objective-C 和 Objective-C++ 语言。主要来自 Apple 公司的赞助支持,Clang 的目的用以取代 GCC 系统底下的 C / Objective-C 编译器,在当代的系统,它较为容易与集成开发环境(IDE)集成,而且对于线程有更好的支持。许多 GCC 的前端也已经可以与其运行,LLVM目前支持 Ada、C语言、C++、D语言、Fortran、Haskell、Julia、Objective-C、Rust 及 Swift 等语言的编译。
认识 LLVM的更多相关文章
- LLVM 笔记(五)—— LLVM IR
ilocker:关注 Android 安全(新手) QQ: 2597294287 LLVM 的 IR (Intermediate Representation) 是其设计中的最重要的部分.优化器在进行 ...
- LLVM 笔记(四)—— three-phase 设计的收益
ilocker:关注 Android 安全(新手) QQ: 2597294287 采用 three-phase 的设计方式,便于编译器支持多种语言和多种目标平台. 如果在优化器阶段采用通用的 IR ( ...
- LLVM 笔记(二)—— PHI node
ilocker:关注 Android 安全(新手) QQ: 2597294287 什么是 PHI node? 所有 LLVM 指令都使用 SSA (Static Single Assignment,静 ...
- [ZZ] A Proposal For Compiling Direct3D HLSL With LLVM (Written by Michael Larabel )
http://www.phoronix.com/scan.php?page=news_item&px=OTI2NA Note: Something very instersting to w ...
- LLVM与Clang的概述及关系
LLVM是构架编译器(compiler)的框架系统,以C++编写而成,用于优化以任意程序语言编写的程序的编译时间(compile-time).链接时间(link-time).运行时间(run-time ...
- [llvm] Call the LLVM Jit from c program
stackoverflow: http://stackoverflow.com/questions/1838304/call-the-llvm-jit-from-c-program Another t ...
- install LLVM
version >= 3.8.0 $ cd llvm... $ mv someofClang ./tools $ mkdir build $ cd build $ cmake -DCMAKE_B ...
- LLVM example for main
#include "llvm/IR/CallSite.h" #include "llvm/IR/Instruction.h" #include "ll ...
- clang LLVM 介绍和安装(Ubuntu10 64位)
http://www.csdn.net/article/2013-11-27/2817632 的对Stanley B.Lippman采访提到clang的一些优点,以前程序员杂志也写过,为了提高系统的性 ...
- 转:GCC,LLVM,Clang编译器对比
GCC,LLVM,Clang编译器对比 转自: http://www.cnblogs.com/qoakzmxncb/archive/2013/04/18/3029105.html 在XCode中, ...
随机推荐
- Pod:Kubernetes最小执行单元
Pod基本概念理解 Pod是什么 Pod 是 Kubernetes 应用程序的基本执行单元,它是 Kubernetes 对象模型中创建或部署的最小和最简单的单元. 一个Pod可以包括一个或者多个容器. ...
- 安装MySQL到Ubuntu 20.04
本文的内容主要来自对How To Install MySQL on Ubuntu 20.04的翻译.在根据该文的指导下,我在自己的Ubuntu 20.04.3 LTS版本中安装了MySQL 8. St ...
- 五天学完MySQL打卡挑战 day01
明天继续上传学习笔记和练习的Word文档 晚安~
- Cesium参考资源
Reference resources cesium官网 cesium 下载 cesium官方文档 APIs cesium-workshop github cesium 官方示例 cesium git ...
- 嵌入式硬件之ADC/DAC
嵌入式硬件之ADC/DAC 写在前面 这几天在做一个寒假练项目,其中涉及到了音频的处理,ADC.DAC再次进入到了我的视野,并引起了我新的思考. 1.初次相识 记得去年七月份,本科毕业刚离校,就到研究 ...
- linux中uniq命令全面解析
目录 一 :uniq作用 二:uniq格式 1.参数 2.参数案例解析: linuxuniq简介 Linux uniq 命令用于检查及删除文本文件中重复出现的行列,一般与 sort 命令结合使用. u ...
- python26day
内容回顾 多态: 一个类表现出的多种形态,实际上是通过继承来完成的 今日内容 super,调用父类的同名方法 按照mro顺序来寻找当前类的下一个类 封装 广义上的封装 方法属性名字前加了__,就变 ...
- Redis 源码简洁剖析 04 - Sorted Set 有序集合
Sorted Set 是什么 Sorted Set 命令及实现方法 Sorted Set 数据结构 跳表(skiplist) 跳表节点的结构定义 跳表的定义 跳表节点查询 层数设置 跳表插入节点 zs ...
- RPC调用获取参数值
本文以 RPC 获取百度登录password加密值为例: 涉及的知识点有: 1.js调试,寻找加密代码 2. 浏览器本地代码替换 3. js自执行函数 4. 插桩 5. RPC 远程调用 6. pyt ...
- ApacheCN 深度学习译文集 20201218 更新
新增了四个教程: Python 人工智能中文版 0 前言 1 人工智能简介 2 人工智能的基本用例 3 机器学习管道 4 特征选择和特征工程 5 使用监督学习的分类和回归 6 集成学习的预测分析 7 ...