0
点赞
收藏
分享

微信扫一扫

第四十节—iOS用到的LLVM(一)

本文为L_Ares个人写作,以任何形式转载请表明原文出处。

先不说LLVM是什么,概念性的资料其实去某度百科(如果可以的话,建议还是去看维基百科或者LLVM官网)都可以找到这四个英文字母组合起来是意思,先说一下为什么要探索这个东西。

对于从事C++iOS开发的童鞋们一定听说过这个东西,哪怕你不了解,但是听总归是听过的,抛开C++不说,为什么从事iOS开发的童鞋要知道这东西?

什么是编译器,在扩展6特意摘出来写了一下,如果还不知道计算机语言的简要分类和编译器的概念的童鞋,可以看一下。

一、简述什么是LLVM

前言

概念

这里的概念全部引自LLVM官网

所谓工具链技术,举个栗子 :

概述

LLVM现在是一个项目体系是一套框架系统,在之前,它曾是Low Level Virtual Machine的缩写。

LLVM项目包括了非常多的子项目,包括iOS开发者常见的ClangLLDBlibc++libc++ ABI,这都是LLVM的主要子项目。

LLVM虽然包含了这么多编译器作为子项目,但是它本身并不是编译器,也不是编译器后端。

对于LLVM核心(LLVM Core)来说,它是一个编译器基础设施框架。

它提供的是编写编译器所需的一系列的库,例如程序分析、代码优化、机器代码生成等。并且提供了调用这些库的相关工具。也为这些库提供了方便简单的、具备类型的、与平台无关的统一中间代码语言——LLVM IR

LLVMC++编写而成,用于优化以任意程序语言编写的 :

  • 编译时间 (compile-time)

  • 链接时间 (link-time)

  • 运行时间 (run-time)

  • 空闲时间 (idle-time)

LLVM对开发者保持开放,并且兼容现有的脚本。

二、编译器的设计

在探索LLVM的设计之前,先看一下传统的编译器设计,来比较两者的区别,以及探索LLVM的优势。

1. 传统编译器的设计

如图2.1.0所示

传统的编译器整体流程是 :

1.1 编译器前端(Frontend)

1.2 优化器(Optimizer)

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

2. iOS的编译器架构

所谓iOS的编译器架构其实就是LLVM编译器架构中的一部分。包括Objective-CCC++在内,它们使用的编译器前端都是Clang。而Swift编译器前端就是Swift。它们的编译器后端则全部都是LLVM Code Generator

Clang也只是整个LLVM架构中的一个子项目,属于编译器前端,这个在上面说过。

来看iOS的编译器架构图 :

很明显,iOS的编译器是通过Clang或者Swift来完成词法分析、语法分析、语义分析的步骤,来完成对源代码的错误排查,然后生成抽象语法树(AST)

这里利用的就是LLVM的前端,和传统编译器的不同点是,Clang不止做完了上述的排查,还会生成一个非常重要的东西——IR

什么是IR?

那么用语言来描述iOS的编译器架构设计流程就是 :

3. LLVM的设计

LLVM的设计重点和优势 : 面对多种源语言(编译器前端来做),或者多种硬件架构(编译器后端来做)的情况时,对比传统的编译器例如GCC,优势就是LLVMIR设计。

由于GCC是以一个整体应用程序设计的,也就是说,如果你的前端源语言或者后端硬件架构,任一一个发生了变化的话,你需要重新设计一整套前端--优化器--后端的编译器。

LLVM的设计图 :

优势 :

  • 如果前端出现了新的源语言类型,LLVM只需要针对新语言适配一个IR转换器即可,优化器和后端都不需要进行大的改变,甚至不用改变。

  • 如果后端出现了新的硬件架构,LLVM只需要针对新的硬件架构适配一个IR转换器即可,优化器和前端则不需要进行大的改变,甚至不用改变。

三、关于Clang

1. 什么是Clang

内容引自LLVM官网,个人翻译,如有不准确的地方,还请不吝赐教。

2. Clang的概述

3. 一些LLVM或Clang中的名词解释

3.1 词法分析

3.2 语法分析

3.3 语义分析

3.4 抽象语法树

4. iOS中可能遇到的Clang常用指令

这里只说一些iOS中可能常用的Clang指令,如果想要全部的Clang指令集,可以在terminal终端中输入clang --help查看。

如果认为上面的命令查看不方便的,这里还有github版本,内容就是copy的clang --help

或者可以直接在LLVM官网的Clang Document查询。

Clang命令 释义
-ccc-print-phases 打印源码的编译阶段,得到的打印结果就是整个源码到机器代码的整体流程步骤。
-rewrite-objc 将OC源码编译成C++源码
-E 查看预处理阶段详细步骤(在terminal中查看,也可以生成一个新文件 : clang -E main.m >> new_main.m) 。>>就是文件重定向。
-c 必须在-E之后才可以使用,例如clang -E main.m -c。只进行预处理,编译,汇编步骤,不进行链接步骤。执行完成后生成的是.o链接文件。
-S 只进行预处理和编译步骤,不进行汇编,链接等后续步骤。执行完成后,生成的是.s汇编代码文件。
-o <file> 完成预编译-->编译-->汇编-->链接后,生成可执行文件到<file>文件。
-g 在生成的可执行文件中,包含标准的调试信息。
-i <路径>(应该是大写i最标准) 在头文件中的搜索路径中添加<路径>
-fmodules 启用模块化语言特性。
-fsyntax-only 编译器并不生成代码,后续的操作只是语法级别的修改。
-Xclang <arg> clang编译器传递参数<arg>
-dump-tokens 运行预处理器,将源码内部拆分成各种单词(Token)。
-ast-dump 构建抽象语法树AST,然后对其进行拆解和调试。
-fobjc-arc 生成Objective-C指针的retainrelease的调用。
-emit-llvm 对汇编文件和目标文件生成LLVM IR代码。
举报

相关推荐

0 条评论