Clang - ShenYj/ShenYj.github.io GitHub Wiki

Clang

Clang简介

Clang是一个C语言、C++、Objective-C语言的轻量级编译器。源代码发布于BSD协议下。 Clang将支持其普通lambda表达式、返回类型的简化处理以及更好的处理constexpr关键字。

Clang是一个由Apple主导编写,基于LLVM的C/C++/Objective-C编译器 2013年4月,Clang已经全面支持C++11标准,并开始实现C++1y特性(也就是C++14,这是 C++的下一个小更新版本)。Clang将支持其普通lambda表达式、返回类型的简化处理以及更 好的处理constexpr关键字。

Clang是一个C++编写、基于LLVM、发布于LLVM BSD许可证下的C/C++/Objective-C/ Objective-C++编译器。它与GNU C语言规范几乎完全兼容(当然,也有部分不兼容的内容, 包括编译命令选项也会有点差异),并在此基础上增加了额外的语法特性,比如C函数重载 (通过__attribute__((overloadable))来修饰函数),其目标(之一)就是超越GCC

Object-C编译过程

1、预处理(preprocessor)

预处理会替进行头文件引入,宏替换,注释处理,条件编译(#ifdef)等操作

2、词法分析(lexical anaysis)

读入源文件的字符流,将他们组织成有意义的词素(lexeme)序列,对于每个词素,此法分析器产生词法单元(token)作为输出

3、语法分析(semantic analysis)

词法分析的Token流会被解析成一颗抽象语法树(abstract syntax tree - AST)。AST是开发者编写clang插件主要交互的数据结构,clang也提供很多API去读取AST。更多细节:Introduction to the Clang AST。

4、CodeGen

CodeGen遍历语法树,生成LLVM IR代码。LLVM IR是前端的输出,后端的输入。

5、生成汇编代码

LLVM对IR进行优化后,会针对不同架构生成不同的目标代码,最后以汇编代码的格式输出

6、汇编器生成 .o文件

汇编器以汇编代码作为输入,将汇编代码转换为机器代码,最后输出目标文件(object file)

7、连接器

把编译产生的.o文件和(dylib,a,tbd)文件,生成一个mach-o文件

Clang与swiftc对比

Clang常用命令

  • 把目标文件编译成c++文件

    clang -rewrite-objc main.m -o main.cpp

  • 指定SDK路径

    clang -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/ iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk main.m

  • clang编译.o文件、链接等操作可以参考之前整理的静态库相关笔记

  • 查看源码的编译阶段 clang -ccc-print-phases

    ❯ 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
    

    0-> 输出文件:找到源文件
    1-> 预处理阶段:这个过程处理包扩宏的替换,头文件的导入
    2-> 编译阶段:进行此法分析、语法分析、检测语法是否正确,最终生成IR
    3-> 后端:这里LLVM会通过一个个Pass去优化,每个Pass做一些事情,最终生成汇编代码
    4-> 生成目标文件
    5-> 链接:链接需要的动态库和静态库,生成可执行文件
    6-> 通过不同的架构,省测绘功能对应的可执行文件

    • 预处理阶段 clang -E main.m执行完毕后可以看到头文件的导入和宏的替换

    • 编译阶段

      • 词法分析 与处理完成后就会进行词法分析,这里会把代码切成一个个Token,比如大小括号、关键词、等于号和其他字符串等,clang指令为 clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m

      • 语法分析 词法分析完成之后就是语法分析,它的任务是验证语法是否正确。在词法分析的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等,然后将所有节点组成抽象语法书(Abstract Syntax Tree, AST)。语法分析程序判断源程序在接受上是否正确。clang指令为 clang -fmodules -fsyntax-only -Xclang -ast-dump mian.m

      • 生成中间代码IR 完成上述步骤后就开始生成中间代码IR了,代码生成器(Code Generation)会将语法树自顶向下逐步翻译成LLVM IR。通过下面指令可以生成.ll的文本文件,查看IR代码 clang -S -fobjc-arc -emit-llvm main.m
        Object-C代码在这一部会进行runtime的桥接:property合成,ARC处理等

        • IR 的部分基础语法

          @: 全局标识
          %: 局部标识
          alloca:开辟空间
          align: 内存对齐
          i32: 32个bit,4个字节
          store:写入内存
          load:读取数据(从内存读取到cpu)
          call: 调用函数
          ret: 返回

        • IR 的优化 LLVM的优化级别分别是-O0 -O1 -O2 -O3 -Os
          e.g.: clang -Os -S -fobjc-arc -emit-llvm main.m -o main.ll

xcrun

xcode安装的时候顺带安装了xcrun命令,xcrun命令在clang的基础上进行了一些封装,要更好用一些

  • xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp (模拟器)

  • xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main- arm64.cpp (手机)

链接

⚠️ **GitHub.com Fallback** ⚠️