了解-clang编译过程

clang编译过程

clang是一个 CC++Objective-C的编译器, 包含了预处理语法解析代码生成优化汇编链接阶段, 尽管clang是高度集成的, 但是理解编译的各个阶段, 仍然很有必要.
过程:

预处理 -> 语法解析 -> 代码生成&优化 -> 汇编 -> 链接
.c -> AST -> .s -> .o -> .out

编译过程

驱动

clang可执行文件实际上是一个小的驱动程序, 控制其他工具(如编译器、汇编器和链接器)的总体执行. 通常你不需要直接和驱动程序交互, 就可以使用clang来运行其他工具.

预处理

这个阶段会对输入的源文件进行标记化处理、宏扩展、#include扩展和其他预处理器指令的处理. 对C输出.i, 对C++输出 .ii, 对 OC 输出 .mi, 对Objective-C++ 输出 .mii, 分别对应如下:

输入: .c.cpp.m.mm
输出: .i.ii.mi.mii

语法分析和语义分析

这个阶段会解析输入文件, 将预处理标记转换为解析树. 一旦以解析树的形式出现, 它也会用语义分析来计算表达式的类型, 确认代码格式是否正确.
该阶段负责生成大多数的编译警告错误, 输出为 AST(抽象语法树, Abstract Syntax Tree)

输出: AST

代码生成和优化

这个阶段会将AST转换为底层的中间代码(称为 LLVM IR), 再最终转换为机器码.该阶段负责优化生成的代码, 并处理特定目标的代码生成. 输出通常称为 .s 文件或者 汇编文件.

输出: .s汇编文件

汇编

这个阶段将编译器的输出转换为目标文件, 输出为 .o 文件 或者 object 文件

输出: .oobject文件

链接

这个阶段会将多个目标文件合并为一个可执行文件或动态库.输出为 a.out 或者 .so 文件

输出: .out.so

示例

下面用一个简单的hello world来演示一下:

第1步: 创建源码文件hello.c如下:

//
//  hello.c
//

#include <stdio.h>

#define ADD(x,y) (x+y)
#define ADD10(x, y) ADD(x+10, y)


int main() {
#if A
    printf("hello world A"); // A
#else
    printf("hello world B"); // B
#endif
    printf("result:%d", ADD10(1, 2));
}


第2步: 对其进行预编译, 得到.i输出文件, 使用命令:

$ clang -E hello.c -o hello.i

-E 选项为进行预编译 (更多的编译选项可以在查看这里)
hello.i 文件内容如下:

# 1 "hello.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 362 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "hello.c" 2
.
.
.
# 10 "hello.c" 2



int main() {



    printf("hello world B");

    printf("result:%d", (1 +10 +2));
}

从中可以看到预处理做的一些工作

  • include 扩展: # 10 "hello.c 2"上边的均为stdio.h中的内容
  • 标记化处理: .i 文件中行首行末的数字
  • 去除注释: hello.c 的注释都没有了
  • 条件编译: 未定义宏A, 故删除#if A分支下的代码块,并保留该空行
  • 宏删除: ADD10ADD 宏被删除; 条件编译的宏指令也被删除
  • 宏替换: ADD10ADD宏直接替换为(1+10+2), 并删除宏定义,保留该空行

第3步:编译,得到.s文件, 使用命令

$ clang -S hello.i -o hello.s

-S 选项为进行汇编之前的所有阶段(代码生成优化指定目标的代码生成), 产生一个汇编文件 (更多的编译选项可以在查看这里)
hello.s文件内容如下:

    .section    __TEXT,__text,regular,pure_instructions
    .build_version macos, 10, 15    sdk_version 10, 15
    .globl  _main                   ## -- Begin function main
    .p2align    4, 0x90
_main:                                  ## @main
    .cfi_startproc
## %bb.0:
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    leaq    L_.str(%rip), %rdi
    movb    $0, %al
    callq   _printf
    leaq    L_.str.1(%rip), %rdi
    movl    $13, %esi
    movl    %eax, -4(%rbp)          ## 4-byte Spill
    movb    $0, %al
    callq   _printf
    xorl    %esi, %esi
    movl    %eax, -8(%rbp)          ## 4-byte Spill
    movl    %esi, %eax
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc
                                        ## -- End function
    .section    __TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
    .asciz  "hello world B"

L_.str.1:                               ## @.str.1
    .asciz  "result:%d"


.subsections_via_symbols

第4步: 汇编,得到.o文件, 使用命令

$ clang -c hello.s -o hello.o

-c 选项为执行汇编及之前的所有阶段, 生成机器码0101, 产生一个目标文件 (更多的编译选项可以在查看这里)
hello.o文件内容如下:

cffa edfe 0700 0001 0300 0000 0100 0000
0400 0000 0802 0000 0020 0000 0000 0000
1900 0000 8801 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
b800 0000 0000 0000 2802 0000 0000 0000
.
.
.
68ff ffff ffff ffff 3900 0000 0000 0000
0041 0e10 8602 430d 0600 0000 0000 0000
2800 0000 0100 002d 1900 0000 0200 0015
1200 0000 0100 002d 0b00 0000 0200 0015
0000 0000 0100 0006 0100 0000 0f01 0000
0000 0000 0000 0000 0700 0000 0100 0000
0000 0000 0000 0000 005f 6d61 696e 005f
7072 696e 7466 0000 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335