iOS八股文(十六)LLVM概述

在iOS开发过程中,不管你是使用swift还是OC,在编译的过程中都会使用到LLVM,在之前的文章中也在探究原理的过程中,使用过clang -rewrite -objc命令重写过OC代码,那么今天就系统的认识一下LLVM。

LLVM简介

LLVM(Low Level Virtual Machine)是构架编译器(compiler)的框架系统,以C++编写而成,用于优化以任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(idle-time),对开发者保持开放,并兼容已有脚本。

LLVM计划启动于2000年,最初由美国UIUC大学的Chris Lattner博士主持开展。2006年Chris Lattner加盟Apple Inc.并致力于LLVM在Apple开发体系中的应用。Apple也是LLVM计划的主要资助者。

LLVM已经被Apple、Microsoft、Google、Facebook等各大公司采用

Chris Lattner 这个老表非常牛逼,我们搞iOS开发的应该认识一下,除了LLVM他还是Swift的创始人。

Chris Lattner(生于 1978 年)是一位美国软件工程师,以LLVM和相关项目(如Clang 编译器Swift 编程语言)的主要作者而闻名。截至 2022 年 1 月 21 日,他是他共同创立的人工智能公司 Modular AI 的首席执行官。在创立 Modular AI 之前,他在SiFive担任平台工程高级副总裁,在Google Brain工作了两年后。[4]在此之前,他曾短暂担任自动驾驶软件副总裁[5]Tesla, Inc.曾在Apple Inc.担任开发工具部门的高级总监,领导XcodeInstruments和编译器团队 -- 来自维基百科

Clang

Clang是一个C语言C++Objective-C语言的轻量级编译器

Clang是LLVM的一个子项目。Clang可以用来编译

LLVM的优势

LLVM的结构如下面两个图所示:

src=http---static.oschina.net-uploads-space-2018-0308-161727_pcVc_2621781.png&refer=http---static.oschina.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto.webp

src=http---upload-images.jianshu.io-upload_images-4044896-5739dd179d436fc6.png&refer=http---upload-images.jianshu.io&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto.webp

可以将编译的过程分为3部分:前端、优化器、后端。

  • 编译器前端:经过词法分析、语法分析、语义分析,最后生成IR中间代码
  • 优化器:对中间代码进行优化
  • 编译器后端:生成指定架构模式的二进制文件。

以Objcet-C为例,其编译的过程:
通过clang编译器生成IR代码 -> 优化器 -> llvm后端生成二进制文件
同理swift,其编译的过程:
通过swiftc编译器生成IR代码 -> 优化器 -> llvm后端生成二进制文件

通过这个实例,我们发现LLVM编译器,最明显的优势 - 解藕。无论是前端的编程语言,还是后端的架构,都不依赖整个LLVM。假设苹果后期需要适配一种新的架构模式,只要重新开发一套对应的后端编译器,就可以将此架构模式纳入大家庭了。同样,如果有一天苹果想用Java来作为开发语言,只要再编写一套能将Java编译成IR代码的前端编译器。

编译过程

我们可以借助中断命令,来查看iOS项目的编译过程。

编译阶段

打印编译阶段

clang -ccc-print-phases main.m
复制代码

image.png

  • 读取源码文件
  • 预处理阶段
  • 编译阶段,生成ir代码
  • 后端, 生成汇编代码
  • 通过汇编代码生成目标文件
  • 目标文件通过链接,生成镜像
  • 通过不同的架构模式,生成该架构模式下的可执行文件

预处理

预处理也叫 预编译 ,处理代码里面#开头的代码,替代宏,删除注释,展开头文件。

clang -E main.m
复制代码

编译阶段

词法分析

预处理阶段完成后,就会进行词法分析,把代码切割成一个一个Token。

clang -fmodules -fsyntax-only -Xclang -dump-tokens main.mm
复制代码

image.png

语法分析

进行完词法分析,就会进行语法分析,主要目的是为了检查代码语法正确,然后会生成抽象语法树(AST)。 page4image18037424

clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
复制代码

image.png

生成中间代码

进行完上面步骤就开始生成IR代码了,有的时候我们可以通过IR代码来分析语言的底层原理。

clang -S -fobjc-arc -emit-llvm main.m
复制代码

优化

llvm的有化为多个等级,可以在Xcode上面选择。

image.png

clang -Os -S -fobjc-arc -emit-llvm main.m -o main.ll
复制代码

除了这种优化,还有bitCode优化。同样可以在Xcode中配置。

image.png 通过bitCode优化后,会生成.bc文件,但由于很多第三方库没有支持bitCode,所以目前大部分工程的bitCode都是关闭的。

clang -emit-llvm -c main.ll -o main.bc
复制代码

汇编

我们通过之前步骤生成的.ll 文件或者 .bc文件生成汇编代码:

  clang -S -fobjc-arc main.bc -o main.s
  clang -S -fobjc-arc main.ll -o main.s
复制代码

生成的汇编代码同样可以优化:

clang -Os -S -fobjc-arc main.m -o main.s
复制代码

之后,我们通过汇编代码,就可以生成了目标文件

clang -fmodules -c main.s -o main.o
复制代码

链接

链接器把编译产生的目标文件和库文件(.dylib,.a)生成Mach-O文件:

clang main.o -o main
复制代码

以上就是我们程序在编译的时候所做的所有工作。

参考链接

猜你喜欢

转载自juejin.im/post/7108314824555102215