OC学习31:编译器Clang和LLVM探索

张建 lol

编译器

  1. 大家都知道,我们的计算机CPU只能读懂机器码(machine code,也就是一堆0和1组成的编码)。

  2. 但是我们在编写的代码并不是机器码,而是高级编程语言(Object-C、Swift、…等等),最终也可以被计算机所执行,这就需要编译器了,编译器把我们的高级编程语言通过一系列的操作转化成可被计算机执行的机器语言。

  3. 编译器是如何设计的?为什么要这么设计?优势在哪?

  1. 经典的三段式设计(three phase design):

前端(Frontend)-优化器(Optimizer)-后端(Backend)

  • 前端:负责分析源代码,检查语法错误,并构建针对该语言的抽象语法树(AST);也就是词法分析,语法分析,语义分析和生成中间码。

  • 优化器:负责各种转换,尝试改进代码的运行时间。release包比debug包体积小运行快,其中一个原因就是优化器的作用。

  • 后端:生成实际的机器码。

  1. 首先解决了一个很大的问题:
  • 假如有N种语言(C、OC、C++、Swift…)的前端,同时也有M个架构(模拟器、arm64、x86…)的Target,是否就需要 N × M 个编译器?。

  • 三段式架构的价值就体现出来了,通过共享优化器的中转,很好的解决了这个问题。

  • 假如你需要增加一种语言,只需要增加一种前端;假如你需要增加一种处理器架构,也只需要增加一种后端,而其他的地方都不需要改动。这复用思想很牛逼吧。(如下图):

XCode编译器发展史

  1. 发展史

Xcode3 以前:GCC;
Xcode3:增加LLVM,GCC(前端) + LLVM(后端);
Xcode4.2:出现Clang - LLVM 3.0成为默认编译器;
Xcode4.6:LLVM 升级到4.2版本;
Xcode5: GCC被废弃,新的编译器是LLVM 5.0,从GCC过渡到Clang-LLVM的时代正式完成

  1. 为什么苹果的Xcode会使用Clang+LLVM取代GCC?
  • 这里面有些历史原因。毕竟GCC是第三方开源的,不属于苹果维护也不能完全掌控其开发进程,Apple为Objective-C增加许多新特性,但GCC开发者对这些支持却不友好;Apple需要做模块化,GCC开发者却拖着迟迟不实现。这能忍?
  • 随着Apple对其IDE(也就是Xcode)性能的要求越来越高,最终还是从零开发了一个Clang前端加LLVM后端的编译器,这个编译器的作者是大名鼎鼎的Swift之父Chris Lattner。
  1. Clang比GCC优秀在哪些方面?
  • 编译速度快,Debug模式下,编译OC的速度是GCC的三倍
  • 占用内存小,Clang的生成的AST语法树占用内存是GCC的五分之一
  • 模块化设计,Clang基于库的模块化设计,易于IDE集成和重用
  • 诊断性可读性强,在编译过程中,Clang创建并保留了大量的详细元素,有利于调试
  • 设计清晰简单,容易理解,易于扩展增强

OC-Clang和LLVM

  1. Clang 就是基于 LLVM 架构的 C/C++/Objective-C 编译器前端

  2. LLVM现在被用作实现各种静态和运行时编译语言的通用基础结构(C,C++,Objecttive-C,Java,.Net,Python,Ruby,D等)。

  3. Clang 主要处理一些和具体机器无关的针对语言的分析操作.编译器的优化器部分和后端部分是LLVM后端,也可以直接叫 LLVM(狭义的LLVM),广义上LLVM 就是整个LLVM架构。

  1. 命令行查看一下OC源文件的编译过程:

mac@192 NSObject对象的本质 % clang -ccc-print-phases main.m

0: input, “main.m”, objective-c
1: preprocessor, {0}, objective-c-cpp-output
2: compiler, {1}, ir
3: backend, {2}, assembler
4: assembler, {3}, object
5: linker, {4}, image
6: bind-arch, “x86_64”, {5}, image

一共是7个阶段:

  • 第0个阶段找到源代码,读入文件。
  • 第1个阶段 preprocessor,预处理器,就是把头导入,宏定义给展开,包  括 #define、 #include、 #import、 #indef、 #pragma。
  • 第2阶段就是 compiler,编译器 编译ir 中间代码。
  • 第3阶段就是交给后端,来生成 汇编 代码(assembler)。
  • 第4阶段是将汇编代码转换为 目标对象文件
  • 第5阶段是 链接器,将多个目标对象文件合并为一个可执行文件 (或者一个动态库) 。
  • 最后一阶段 生成可执行文件 :Mach-O
  • Post title:OC学习31:编译器Clang和LLVM探索
  • Post author:张建
  • Create time:2020-07-11 22:17:35
  • Post link:https://redefine.ohevan.com/2020/07/11/OC/OC学习31:编译器Clang和LLVM探索/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
On this page
OC学习31:编译器Clang和LLVM探索