美文网首页
iOS之LLVM架构

iOS之LLVM架构

作者: 好_好先生 | 来源:发表于2020-01-03 14:42 被阅读0次

    编译器架构

    传统编译器架构(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

    相关文章

      网友评论

          本文标题:iOS之LLVM架构

          本文链接:https://www.haomeiwen.com/subject/cgpzoctx.html