iOS LLVM及编译过程

LLVM概述

  • LLVM 是以 C++ 编写的架构编译器(compiler)的框架系统
  • 从如下方面优化任意语言编写的的程序
    • 编译时间 compile time
    • 连接时间 link time
    • 运行时间 run time
    • 空闲时间 idle time

传统编译器设计

编译器前端 Frontend

编译器前端的任务是 解析源代码前端

  • 检查代码正确性
    • 词法分析
    • 语法分析
    • 语义分析
  • 构建抽象语法树
  • LLVM的前端还会生成 中间代码intermediate representationIR

优化器 Optimizer

优化器端的任务是改善代码的运行时间,例如消除冗余运算等。c++

编译器后端 Backend / 代码生成器CodeGenerator

  • 将代码映射到目标指令集
  • 生成机器语言
  • 机器相关的代码优化

iOS的编译器架构

OCcc++ 使用的编译器前端是clangSwift使用的是Swift;后端都是LLVM后端

LLVM的设计

传统的编译器设计把前端、优化器、后端集成在一块儿,须要支持新语言或新硬件结构时就必须从新开发一套编译器。LLVM的设计模式很好的解决了这种不便。设计模式

  • LLVM的编译器前端会生成通用的中间代码intermediate respresentation IR
  • 优化器对中间代码处理不须要改变
  • 须要支持新语言时只须要单独开发前端
  • 须要支持新架构时只须要单独编写后端

Clang

  • LLVM中的一个子项目
  • 基于LLVM的轻量级编译器
  • 替代GCC,提供更快的编译速度
  • 负责编译OCCC++
  • LLVM架构的编译器前端

编译流程

打印编译流程

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

  • 0、输入文件:找到源文件
  • 一、预处理:包括替换宏和导入头文件
  • 二、编译阶段:词法分析、语法分析、语义分析,最终生成IR
  • 三、后端:经过一个个Pass去优化,每一个Pass完成一部分功能,最终生成汇编代码
  • 四、生成目标文件
  • 五、连接:连接须要的动态库和静态库,生成目标文件
  • 六、经过不一样架构,生成对应的可执行文件

预处理

clang -E main.m
复制代码

执行后能够看到头文件导入以及宏被替换。xcode

词法分析

预处理后会进行词法分析,词法分析会把代码切片成一个个tokenbash

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

执行后能够看到每一个词(token)所在的位置架构

语法分析

语法分析会验证语法是否正确,在词法分析的基础上把单词组合成各类语法短语,而后把节点组成抽象的语法树(Abstract Syntax Tree,AST)框架

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

若是找不到头文件,能够手动导入SDK函数

clang -isysroot SDK路径 -fmodules -fsyntax-only	-Xclang	-ast-dump main.m
复制代码

生成中间代码IR(intermediate representation)

处理完上述步骤,代码生成器(Core Generator)会根据语法树自顶向下生成LLVM IR。OC会在这里进行runtime的桥接:property的合成、ARC处理等。优化

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

LLVM的优化级别有 -O0 -O1 -O2 -O3 -Os

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

执行指令能够获得.ll文件

  • IR基本语法
@       全局标示
%       局部标示
alloca  开辟空间
align   字节对齐
i32     32位,4字节
store   写入内存
load    读取数据
call    调用函数
ret     return
复制代码

查看未优化的main.ll

优化后的main.ll

bitCode

xcode7之后开启了bitCode,苹果对代码作了进一步优化并生成.bc文件。经过.ll文件生成.bc文件。

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

生成汇编代码

能够经过.bc.ll文件生成汇编代码

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

生成汇编代码的时候也能够进行优化

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

生成目标文件

输入汇编代码,转化成机器代码,最后输出目标文件。

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

查看main.o中的符号

xcrun nm -nm main.o
复制代码

能够看到print函数、test函数、main函数

  • _printf 能够看到 undefined extranal 标示
  • undefined 表明它在当前文件找不到
  • extranal 表明它能够外部访问

生成能够执行文件

把编译的.o文件和dylib.a文件链接,生成mach-o文件

clang	main.o	-o	main
复制代码

执行可执行文件,能够看见输出了正确结果

相关文章
相关标签/搜索