iOS之LLVM架构

编译器架构

传统编译器架构(Three-Phase)

Three-Phase.png

上图是最简单的三段式编译器架构。

  • Frontend:前端
    词法分析、语法分析、语义分析、生成中间代码

  • Optimizer:优化器
    中间代码优化

  • Backend:后端
    生成机器码

    首先,我们看到source是我们的源代码,进入编译器的前端Frontend;在前端完成之后,就进入优化器这一模块;优化完成之后进入后端模块;在这全部完成之后,根据你的架构是x86,armv7等产生机器码。
    这样就会有一个问题,有M种语言,N种架构,那就会有M*N种编译方式需要处理,显然架构不合理。

Apple支持的语言

C
C++
Objective-C
Swift
...

iPhone CPU架构

指令集对应的机型:
2019 A13芯片arm64e : iphone11、iphone11 Pro
2018 A12芯片arm64e : iphone XS、iphone XS Max、iphoneXR
2017 A11芯片arm64: iPhone 8、iPhone 8 Plus、and iPhone X
2016 A10芯片arm64:iPhone 7、7 Plus、iPad (2018)
2015 A9芯片arm64: iPhone 6S、6S Plus 
2014 A8芯片arm64: iPhone 6、iPhone 6 Plus
2013 A7芯片arm64: iPhone 5S
armv7s:iPhone5、iPhone5C、iPad4(iPad with Retina Display)
armv7:iPhone4、iPhone4S、iPad、iPad2、iPad3(The New iPad)、iPad mini、iPod Touch 3G、iPod Touch4

模拟器32位处理器测试需要i386架构
模拟器64位处理器测试需要x86_64架构
真机32位处理器需要armv7,或者armv7s架构
真机64位处理器需要arm64架构

LLVM:

  • 官网:https://llvm.org/

  • The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.

  • LLVM项目是模块化、可重用的编译器以及工具链技术的集合

  • 美国计算机协会(ACM)将其2012年软件系统奖项颁给了LLVM,之前曾经得此奖项的软件和技术包括Mosaic、the World Wide Web、Smalltalk、UNIX、Eclipse等等

  • 创始人Chris Lattner ,亦是swift之父

  • 有些文章把LLVM当做Low Level Virtual Machine(低级虚拟机)的缩写简称,官方描述如下

The name "LLVM" itself is not an acronym; it is the full name of the project
"LLVM"这个名称本身不是首字母缩略词;它是项目的全名

LLVM.png

LLVM百度百科

LLVM架构:

LLVM架构.png
  1. 不同的前后端使用统一的中间代码 LLVM Intermediate Representation(LLVM IR)
  2. 如果需要支持一种新的编程语言,那么只需要实现一个新的前端就可以
  3. 如果需要支持一种新的硬件设备,那么只需要实现一个新的后端就可以
  4. 优化阶段是一个通用的阶段,它针对的是统一的LLVM IR,不论是支持新的编程语言,还是支持新的硬件设备,都不需要对优化阶段做修改
  5. 相比之下,GCC的前端和后端没分的太开,前端后端耦合在了一起,所以GCC为了支持一门新语言,或者支持一个新的平台,就会变得特别困难
  6. LLVM现在被作为实现各种静态和运行时编译语言的通用基础结构(GCC家族、Java、.NET、Python、Ruby、Scheme、Haskell、D等)
  • 广义的LLVM是整个LLVM架构
  • 狭义的LLVM是指LLVM后端


    LLVM架构2.png

    由上图可知,需要支持Swift这个新的语言,只需要实现一个新的前端swiftc就可以实现

GCC:

GCC架构.jpeg

GCC百度百科.png

GCC百度百科

GCC的消亡与Clang的崛起

Apple一直使用GCC作为官方的编译器。GCC作为开源世界的编译器标准一直做得不错,但Apple对编译工具会提出更高的要求。
一方面,是Apple对Objective-C语言新增很多特性,但GCC开发者并不买Apple的账--不给实现,因此索性后来两者分成两条分支分别开发,这也造成Apple的编译器版本远落后于GCC的官方版本。另一方面,GCC的代码耦合度太高,不好独立,而且越是后期的版本,代码质量越差,但Apple想做的很多功能(比如更好的IDE支持)需要模块化的方式来调用GCC,但GCC一直不给做。所以,这种不和让Apple一直在寻找一个高效的、模块化的、协议更放松的开源替代品。GCC系统庞大而笨重,而Apple大量使用的Objective-C在GCC中优先级很低。此外GCC作为一个纯粹的编译系统,与IDE配合得很差。加之许可证方面的要求,Apple无法使用LLVM 继续改进GCC的代码质量。于是,Apple决定从零开始写 C、C++、Objective-C语言的前端 Clang,完全替代掉GCC。

Clang

  • Clang是LLVM项目的一个子项目

  • 基于LLVM架构的C/C++/Objective-C编译器前端

  • 官网:http://clang.llvm.org/

相比GCC,Clang具有如下优点:

  • 编译速度快:在某些平台上,Clang的编译速度显著的快过GCC(Debug模式下编译OC速度比GCC)快3倍
  • 占用内存小:Clang生成的AST所占用的内存是GCC的五分之一左右
  • 模块化设计:Clang采用基于库的模块化设计,易于IDE集成及其他用途的重用
  • 诊断信息可读性强:在编译过程中,Clang创建并保留了大量详细的元数据(metadata),有利于调试
  • 设计清晰简单,容易理解,易于扩展增强
    LLVM架构3.png

    clang.png

    clang百度百科

OC源代码的前端编译过程

源代码:

#include 

#define AGE 40

int main(int argc, const char * argv[]) {
    int a = 10;
    int b = 20;
    int c = a + b + AGE;
    
    return 0;
}
  • 命令行查看编译的过程:$ clang -ccc-print-phases main.m(打印编译阶段)
0: input, "main.m", objective-c //找到源代码:main.m 文件
1: preprocessor, {0}, objective-c-cpp-output //预处理器,include,import 宏定义换掉
2: compiler, {1}, ir // 编译成ir 中间代码
3: backend, {2}, assembler // 后端 交给后端
4: assembler, {3}, object // 目标代码 
5: linker, {4}, image // 链接 其他一些静态库动态库
6: bind-arch, "x86_64", {5}, image // 适合某个架构的代码

预处理(preprocessor)

  • 查看预处理结果:$ clang -E main.m


    预处理.png

词法分析

  • 词法分析,生成Token:$clang -fmodules -E -Xclang -dump-tokens main.m
annot_module_include '#include 

#define AGE 40

int main(int argc, const char * argv[]) {
    int a = 10;
    int b = 20;
    int c = a + b '     Loc=
int 'int'    [StartOfLine]  Loc=
identifier 'main'    [LeadingSpace] Loc=
l_paren '('     Loc=
int 'int'       Loc=
identifier 'argc'    [LeadingSpace] Loc=
comma ','       Loc=
const 'const'    [LeadingSpace] Loc=
char 'char'  [LeadingSpace] Loc=
star '*'     [LeadingSpace] Loc=
identifier 'argv'    [LeadingSpace] Loc=
l_square '['        Loc=
r_square ']'        Loc=
r_paren ')'     Loc=
l_brace '{'  [LeadingSpace] Loc=
int 'int'    [StartOfLine] [LeadingSpace]   Loc=
identifier 'a'   [LeadingSpace] Loc=
equal '='    [LeadingSpace] Loc=
numeric_constant '10'    [LeadingSpace] Loc=
semi ';'        Loc=
int 'int'    [StartOfLine] [LeadingSpace]   Loc=
identifier 'b'   [LeadingSpace] Loc=
equal '='    [LeadingSpace] Loc=
numeric_constant '20'    [LeadingSpace] Loc=
semi ';'        Loc=
int 'int'    [StartOfLine] [LeadingSpace]   Loc=
identifier 'c'   [LeadingSpace] Loc=
equal '='    [LeadingSpace] Loc=
identifier 'a'   [LeadingSpace] Loc=
plus '+'     [LeadingSpace] Loc=
identifier 'b'   [LeadingSpace] Loc=
plus '+'     [LeadingSpace] Loc=
numeric_constant '40'    [LeadingSpace] Loc=>
semi ';'        Loc=
return 'return'  [StartOfLine] [LeadingSpace]   Loc=
numeric_constant '0'     [LeadingSpace] Loc=
semi ';'        Loc=
r_brace '}'  [StartOfLine]  Loc=
eof ''      Loc=

语法分析

  • 生成语法树(AST,Abstract Syntax Tree):clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
    新增方法:
void test(int a, int b) {
    int c = a + b -3;
}
语法分析.png

语法分析2.png

swift生成语法树:swiftc -dump-ast main.swift
swfit生成SIL代码:swiftc -emit-sil main.swift

生成中间代码(LLVM IR)

  • LLVM有3种表示形式(但本质是等价的)
    1,text:便于阅读的文本格式,类似于汇编语言,扩展名为.ll,clang -S -emit-llvm main.m
    2,memory:内存格式
    3,bitcode:二进制格式,扩展名为.bc,clang -c -emit-llvm main.m
  • swift生成IR代码:swiftc -emit-ir main.swift -o main.ll

官方语法参考:
https://llvm.org/docs/LangRef.html

LLVM-IR.jpeg

文章参考:
https://www.jianshu.com/p/9dbb5930f0ea
https://blog.csdn.net/xhhjin/article/details/81164076
https://ke.qq.com/course/322016

你可能感兴趣的:(iOS之LLVM架构)