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 <stdio.h>

#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 <stdio.h>

#define AGE 40

int main(int argc, const char * argv[]) {
    int a = 10;
    int b = 20;
    int c = a + b '     Loc=<main.m:9:1>
int 'int'    [StartOfLine]  Loc=<main.m:13:1>
identifier 'main'    [LeadingSpace] Loc=<main.m:13:5>
l_paren '('     Loc=<main.m:13:9>
int 'int'       Loc=<main.m:13:10>
identifier 'argc'    [LeadingSpace] Loc=<main.m:13:14>
comma ','       Loc=<main.m:13:18>
const 'const'    [LeadingSpace] Loc=<main.m:13:20>
char 'char'  [LeadingSpace] Loc=<main.m:13:26>
star '*'     [LeadingSpace] Loc=<main.m:13:31>
identifier 'argv'    [LeadingSpace] Loc=<main.m:13:33>
l_square '['        Loc=<main.m:13:37>
r_square ']'        Loc=<main.m:13:38>
r_paren ')'     Loc=<main.m:13:39>
l_brace '{'  [LeadingSpace] Loc=<main.m:13:41>
int 'int'    [StartOfLine] [LeadingSpace]   Loc=<main.m:14:5>
identifier 'a'   [LeadingSpace] Loc=<main.m:14:9>
equal '='    [LeadingSpace] Loc=<main.m:14:11>
numeric_constant '10'    [LeadingSpace] Loc=<main.m:14:13>
semi ';'        Loc=<main.m:14:15>
int 'int'    [StartOfLine] [LeadingSpace]   Loc=<main.m:15:5>
identifier 'b'   [LeadingSpace] Loc=<main.m:15:9>
equal '='    [LeadingSpace] Loc=<main.m:15:11>
numeric_constant '20'    [LeadingSpace] Loc=<main.m:15:13>
semi ';'        Loc=<main.m:15:15>
int 'int'    [StartOfLine] [LeadingSpace]   Loc=<main.m:16:5>
identifier 'c'   [LeadingSpace] Loc=<main.m:16:9>
equal '='    [LeadingSpace] Loc=<main.m:16:11>
identifier 'a'   [LeadingSpace] Loc=<main.m:16:13>
plus '+'     [LeadingSpace] Loc=<main.m:16:15>
identifier 'b'   [LeadingSpace] Loc=<main.m:16:17>
plus '+'     [LeadingSpace] Loc=<main.m:16:19>
numeric_constant '40'    [LeadingSpace] Loc=<main.m:16:21 <Spelling=main.m:11:13>>
semi ';'        Loc=<main.m:16:24>
return 'return'  [StartOfLine] [LeadingSpace]   Loc=<main.m:18:5>
numeric_constant '0'     [LeadingSpace] Loc=<main.m:18:12>
semi ';'        Loc=<main.m:18:13>
r_brace '}'  [StartOfLine]  Loc=<main.m:19:1>
eof ''      Loc=<main.m:19:2>

语法分析

  • 生成语法树(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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351