OC底層原理三十一:LLVM入門(mén)

OC底層原理 學(xué)習(xí)大綱

本節(jié)孵淘,我們給大家介紹一個(gè)偉大的架構(gòu)編譯器LLVM

  1. 什么是編譯器
  2. LLVM概述
  3. LLVM案例體驗(yàn)

1 什么是編譯器锡宋?

1.1 Python案例

  • 創(chuàng)建python文件夾,新建helloDemo.py文件特恬,內(nèi)容如下:
print("hello")
  • 調(diào)用python helloDemo.py執(zhí)行文件执俩,打印出python
    image.png

1.2 C 案例

  • vim創(chuàng)建helloDemo.c文件:
#include <stdio.h>
int main(int a, char * argv[]) {
        printf("hello \n");
        return 0;
}
  • clang helloDemo.c編譯,生成a.out文件癌刽。file a.out查看文件:
    image.png

發(fā)現(xiàn).out文件是:64位的Mach-O可執(zhí)行文件役首,當(dāng)前clang出來(lái)的是x86_64架構(gòu), mac電腦可讀显拜。 所以可以./a.out直接執(zhí)行:

image.png

Q:解釋型語(yǔ)言與編譯型語(yǔ)言

  • python解釋型語(yǔ)言衡奥,一邊翻譯一邊執(zhí)行。和js一樣远荠,機(jī)器可直接執(zhí)行矮固。
  • C語(yǔ)言是編譯型語(yǔ)言,不能直接執(zhí)行矮台,需要編譯器將其轉(zhuǎn)換機(jī)器識(shí)別語(yǔ)言乏屯。

編譯型語(yǔ)言編譯后輸出的是指令(0根时、1組合),cpu可直接執(zhí)行指令
解釋性語(yǔ)言:生成的是數(shù)據(jù)辰晕,不是0蛤迎、1組合,機(jī)器也能直接識(shí)別

編譯器的作用含友,就是將高級(jí)語(yǔ)言轉(zhuǎn)化為機(jī)器能夠識(shí)別語(yǔ)言(可執(zhí)行文件)替裆。

Q:匯編有指令嗎?

  • 早期科學(xué)家窘问,使用0辆童、1編碼。 比如 00001111 對(duì)應(yīng) call惠赫, 00000111 對(duì)應(yīng)bl把鉴。有了對(duì)應(yīng)關(guān)系后。 再手敲0和1就有點(diǎn)難受了儿咱。于是寫(xiě)個(gè)中間解釋器庭砍,我們只用輸入callbl這樣的標(biāo)記指令混埠,經(jīng)過(guò)解釋器怠缸,變成0和1的組合,再交給機(jī)器去執(zhí)行钳宪。 這就是匯編的由來(lái)揭北。

  • 而基于匯編往上,再映射封裝相關(guān)對(duì)應(yīng)關(guān)系吏颖。就跨時(shí)代性c語(yǔ)言搔体,再往上層封裝,就出現(xiàn)了高級(jí)語(yǔ)言oc侦高、swift等語(yǔ)言嫉柴。所以匯編執(zhí)行快,因?yàn)樗?code>直接轉(zhuǎn)換為機(jī)器語(yǔ)言的奉呛。

  • 匯編指令集计螺,是針對(duì)同一操作系統(tǒng)而言,它支持跨平臺(tái)瞧壮。機(jī)器指令cpu的在識(shí)別登馒。早期的計(jì)算機(jī)廠家非常,雖然都用01組合咆槽,但相同組合背后卻是相應(yīng)不同指令陈轿。所以匯編無(wú)法跨平臺(tái)不同操作系統(tǒng)下,匯編指令不同的麦射。

2. LLVM概述

  • LLVM架構(gòu)編譯器compiler)的框架系統(tǒng)蛾娶,以c++編寫(xiě)而成,用于優(yōu)化任意程序語(yǔ)言編寫(xiě)的程序的編譯時(shí)間compile-time)潜秋、鏈接時(shí)間(link-time)蛔琅、運(yùn)行時(shí)間run-time)以及空閑時(shí)間idle-time),對(duì)開(kāi)發(fā)者保持開(kāi)放峻呛,并兼任已有腳本罗售。
  • 2006年Chris Lattner加盟Apple Inc.并致力于LLVMApple開(kāi)發(fā)體系中的應(yīng)用。Apple也是LLVM計(jì)劃主要資助者钩述。
    目前LLVM已經(jīng)被蘋(píng)果iOS開(kāi)發(fā)工具寨躁、Xilinx VivadoFacebook牙勘、Google等各大公司采用职恳。

2.1 傳統(tǒng)編譯器的設(shè)計(jì)

傳統(tǒng)編譯器的設(shè)計(jì)
- 編譯器前端(Frontend):

編譯器的前端任務(wù)解析源代碼。 會(huì)進(jìn)行詞法分析谜悟、語(yǔ)法分析话肖、語(yǔ)義分析北秽。檢查源代碼是否存在錯(cuò)誤葡幸,然后構(gòu)建抽象語(yǔ)法樹(shù)(Abstract Syntax Tree AST),LLVM前端還會(huì)生成中間代碼(intermediate representation, IR)

- 優(yōu)化器(Optimizer)

優(yōu)化器負(fù)責(zé)各種優(yōu)化贺氓。改善代碼的運(yùn)行時(shí)間蔚叨,如消除冗余計(jì)算

- 后端(Backkend)/ 代碼生成器(CodeGenerator)

將代碼映射目標(biāo)指令集,生成機(jī)器語(yǔ)言辙培,并進(jìn)行機(jī)器相關(guān)代碼優(yōu)化 (目標(biāo)指不同操作系統(tǒng)

iOS的編譯器架構(gòu):

Objective C / C / C++ 使用的編譯器前端Clang蔑水,Swiftswift,后端都是LLVM扬蕊。

image.png

2.2 LLVM的設(shè)計(jì)

  • GCC是一個(gè)非常成功編譯器搀别,但由于它作為整體應(yīng)用程序設(shè)計(jì)的,用途受到了限制尾抑。

  • LLVM最重要的地方:支持多種語(yǔ)言多種硬件架構(gòu)歇父。使用通用代碼表示形式:IR(用來(lái)在編譯器中表示代碼的形式)

  • LLVM可以為任何編程語(yǔ)言獨(dú)立編寫(xiě)前端,也可以為任何硬件架構(gòu)獨(dú)立編寫(xiě)后端.

  • 所以LLVM不是一個(gè)簡(jiǎn)單的編譯器再愈,而是架構(gòu)編譯器榜苫,可以兼容所有前端后端

LLVM的設(shè)計(jì)

2.3 Clang

ClangLLVM項(xiàng)目的一個(gè)子項(xiàng)目翎冲〈共牵基于LLVM架構(gòu)輕量級(jí)編輯器誕生之初就是為了替代GCC,提供更快編譯速度驹饺。 他是負(fù)責(zé)編譯C钳枕、C++Objecte-C語(yǔ)言的編譯器赏壹,它屬于整個(gè)LLVM架構(gòu)中的編譯器前端么伯。

  • 對(duì)于開(kāi)發(fā)者而言,研究Clang可以給我們帶來(lái)很多好處卡儒。

3. LLVM案例體驗(yàn)

  • 新建一個(gè)Mac OS命令行工程:
    image.png
  • 沒(méi)有改動(dòng)代碼


    image.png

3.1 編譯流程

  • cd到main.m的文件夾田柔。使用下面命令查看main.m的編譯步驟:
clang -ccc-print-phases main.m

image.png

編譯流程分為以下7步

  • 0: input, "main.m", objective-c
    輸入文件:找到源文件
  • 1: preprocessor, {0}, objective-c-cpp-output
    預(yù)處理:宏的展開(kāi),頭文件的導(dǎo)入
  • 2: compiler, {1}, ir
    編譯:詞法骨望、語(yǔ)法硬爆、語(yǔ)義分析,最終生成IR
  • 3: backend, {2}, assembler ()
    匯編: LLVM通過(guò)一個(gè)個(gè)的Pass去優(yōu)化擎鸠,每個(gè)Pass做一些事缀磕,最后生成匯編代碼
  • 4: assembler, {3}, object
    目標(biāo)文件
  • 5: linker, {4}, image
    鏈接: 鏈接需要的動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù),生成可執(zhí)行文件
  • 6: bind-arch, "x86_64", {5}, image
    架構(gòu)可執(zhí)行文件:通過(guò)不同架構(gòu)劣光,生成對(duì)應(yīng)的可執(zhí)行文件

optimizer優(yōu)化沒(méi)有作為一個(gè)獨(dú)立階段袜蚕,在編譯階段內(nèi)部完成

3.2 預(yù)處理階段

  • main.m中準(zhǔn)備測(cè)試代碼:
#import <stdio.h>
#define C 30

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int a = 10;
        int b = 20;
        printf("%d", a + b + C);
    }
    return 0;
}
  • clang預(yù)編譯輸出main2.m文件:
clang -E main.m >> main2.m
  • 打開(kāi)main2.m,有575行绢涡。其中大部分是stdio庫(kù)的代碼:

    image.png

  • 我們發(fā)現(xiàn)測(cè)試代碼中的宏C牲剃,在預(yù)編譯階段完成了替換,變成了30

預(yù)編譯階段: 1. 導(dǎo)入頭文件 2.替換宏

  • 修改測(cè)試代碼雄可,給int類(lèi)型取個(gè)別名HT_INT_64凿傅,再次預(yù)編譯處理
#define C 30

typedef int HT_INT_64;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        HT_INT_64 a = 10;
        HT_INT_64 b = 20;
        printf("%d", a + b + C);
    }
    return 0;
}
  • 發(fā)現(xiàn)typedef不會(huì)被替換
    image.png

安全拓展:

  1. 使用define重要方法名稱(chēng)進(jìn)行替換。比如#define Pay XXXTest這樣開(kāi)發(fā)者使用宏P(guān)ay開(kāi)發(fā)舒服数苫,但是被hank時(shí)聪舒,實(shí)際代碼是XXXTest,不容易被察覺(jué)虐急。
    #define真實(shí)內(nèi)容箱残,不應(yīng)該寫(xiě)成亂碼,會(huì)讓人有此地?zé)o銀三百兩的感覺(jué)止吁,最好弄成系統(tǒng)類(lèi)似名稱(chēng)或其他不經(jīng)意名稱(chēng)被辑。這樣才容易忽視安全級(jí)別更高 ??)
    typedef沒(méi)有這個(gè)偷梁換柱的效果赏殃。define只影響預(yù)處理期敷待。

3.3 編譯階段

3.3.1 詞法分析
  • 編譯main.m文件:
clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m

-詞法分析,就是根據(jù)空格括號(hào)這些將代碼拆分成一個(gè)個(gè)Token仁热。標(biāo)注了位置第幾行第幾個(gè)字符開(kāi)始的榜揖。

image.png

3.3.2 語(yǔ)法分析
  • 語(yǔ)法分析是驗(yàn)證語(yǔ)法是否正確勾哩。
    在詞法分析的基礎(chǔ)上,將單詞序列組合成各類(lèi)語(yǔ)法短語(yǔ)举哟,如“程序”思劳,“語(yǔ)句”,“表達(dá)式”等妨猩,然后將所有節(jié)點(diǎn)組成抽象語(yǔ)法樹(shù)(Abstract Syntax Tree潜叛,AST)。 語(yǔ)法分析程序判斷源程序結(jié)構(gòu)上是否正確壶硅。
clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
  • 作用域威兜、類(lèi)型運(yùn)算方式十分清晰庐椒。( 語(yǔ)法樹(shù)一次只能處理一次計(jì)算椒舵。兩次運(yùn)算,就得多分一層級(jí)约谈。)

    image.png

  • 語(yǔ)法分析笔宿,就是在生成語(yǔ)法樹(shù)時(shí)完成檢測(cè)的。

  • 頭文件找不到時(shí)棱诱,可以指定SDK:
clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.2.sdk(自己SDK路徑) -fmodules -fsyntax-only -Xclang -ast-dump main.m

3.4 生成中間代碼IR(Intermediate representation)

3.4.1 生成中間代碼
  • 完成以上步驟后泼橘,就開(kāi)始生成中間代碼IR,代碼生成器(Code Generation)會(huì)將語(yǔ)法樹(shù)自頂向下遍歷逐步翻譯成LLVMIR迈勋。

  • 便于理解炬灭,我們簡(jiǎn)化代碼:

#import <stdio.h>

int test(int a, int b) {
    return a + b + 3;
}

int main(int argc, const char * argv[]) {
    int a = test(1,2);
    printf("%d",a);
    return 0;
}

通過(guò)下面命令生成.ll文本文件,查看IR代碼:

clang -S -fobjc-arc -emit-llvm main.m
  • IR基本語(yǔ)法
    @ 全局標(biāo)識(shí)
    % 局部標(biāo)識(shí)
    alloca 開(kāi)辟空間
    align 內(nèi)存對(duì)齊
    i32 32個(gè)bit粪躬,4個(gè)字節(jié)
    store 寫(xiě)入內(nèi)存
    load 讀取數(shù)據(jù)
    call 調(diào)用數(shù)據(jù)
    ret 返回
  • 使用VSCodeSublime Text可以打開(kāi)代碼:(可以指定文件語(yǔ)言担败,讓代碼高亮色
image.png
  • Q:圖中為何多創(chuàng)建那么多局部變量?(如test函數(shù)內(nèi)的a5镰官、a6)
  • 因?yàn)樵谏弦浑A段(編譯階段),我們將代碼編譯成了語(yǔ)法樹(shù)結(jié)構(gòu)吗货。而此時(shí)泳唠,我們只是沿語(yǔ)法樹(shù)進(jìn)行讀取。 語(yǔ)法樹(shù)每一個(gè)層級(jí)宙搬,都需要一個(gè)臨時(shí)變量來(lái)承接笨腥。再返回上一層級(jí)處理
  • 所以會(huì)產(chǎn)生那么多局部變量勇垛。
3.4.2 IR優(yōu)化
  • 我們可以在XcodeBuild Settings中搜索Optimization,可以看到優(yōu)化級(jí)別脖母。
    (Debug模式默認(rèn)None [O0]無(wú)優(yōu)化,Release模式默認(rèn)Fastest,Smallest [Os]最快最小)
image.png
  • LLVM的優(yōu)化級(jí)別分為 -O0闲孤、 -O1谆级、 -O2-O3-Os(第一個(gè)字母是Optimization的O)肥照。

  • 分別選擇O0Os兩個(gè)優(yōu)化等級(jí)進(jìn)行中間代碼的生成比較:

clang -S -fobjc-arc -emit-llvm main.m -o mainO0.ll      //  O0  無(wú)優(yōu)化
clang -Os -S -fobjc-arc -emit-llvm main.m -o mainOs.ll  //  Os 最快最小
image.png

image.png
  • 優(yōu)化后的代碼脚仔,舒服多了。之前那些冗余臨時(shí)局部變量舆绎,也都被優(yōu)化鲤脏,代碼量減少很多。
3.4.3 bitCode再優(yōu)化
  • Xcode7之后吕朵,開(kāi)啟bitCode蘋(píng)果會(huì)再進(jìn)一步優(yōu)化猎醇,生成.bc中間代碼

優(yōu)化體現(xiàn):上傳APPstore的包努溃,針對(duì)不同型號(hào)手機(jī)做了區(qū)分姑食,不同型號(hào)手機(jī)下載時(shí),大小不同茅坛。

clang -emit-llvm -c main.ll -o main.bc

3.5 生成匯編代碼

  • 完成中間代碼的生成后音半,可以將代碼轉(zhuǎn)變匯編代碼了。

  • 此刻我們有4種不同程度的代碼(源代碼->無(wú)優(yōu)化IR代碼->Os優(yōu)化IR代碼 -> bitcode優(yōu)化代碼):

    image.png

  • 分別對(duì)4種程度的代碼輸出匯編文件:

clang -S -fobjc-arc main.m -o main.s
clang -S -fobjc-arc main.ll -o mainO0.s
clang -S -fobjc-arc mainOs.ll -o mainOs.s
clang -S -fobjc-arc main.bc -o mainbc.s
image.png

可以看到在生成匯編代碼時(shí)贡蓖,只有選擇優(yōu)化等級(jí)曹鸠,才能減少匯編代碼量

【拓展】在生成中間代碼前后斥铺,都可以進(jìn)行優(yōu)化彻桃。

  • [嘗試一] 將main.m直接選擇Os級(jí)別優(yōu)化生成.s匯編文件
clang -Os -S -fobjc-arc main.m -o mainOs.s
  • [嘗試二] 將main.m生成無(wú)優(yōu)化main.s,再main.s選擇Os級(jí)別優(yōu)化生成.s匯編文件
clang -S -fobjc-arc -emit-llvm main.m -o mainO0.ll
clang -Os -S -fobjc-arc mainO0.ll -o mainOoOs.s
  • [嘗試三] 將main.m選擇Os級(jí)別優(yōu)化生成main.s晾蜘,再main.s選擇無(wú)優(yōu)化級(jí)別生成.s匯編文件
clang -Os -S -fobjc-arc -emit-llvm main.m -o mainOs.ll
clang -S -fobjc-arc mainOs.ll -o mainOsOo.s
  • [嘗試四] 將main.m選擇Os級(jí)別優(yōu)化生成main.s邻眷,再main.s選擇Os級(jí)別優(yōu)化生成.s匯編文件
clang -Os -S -fobjc-arc -emit-llvm main.m -o mainOs.ll
clang -Os -S -fobjc-arc mainOs.ll -o mainOsOs.s
  • 內(nèi)容比較:
image.png

3.6 生成目標(biāo)文件(機(jī)器代碼)

  • 生成匯編文件后,匯編器匯編代碼作為輸入剔交,將匯編代碼轉(zhuǎn)換機(jī)器代碼肆饶,輸出目標(biāo)文件(object file)
clang -fmodules -c main.s -o main.o
  • file對(duì)比一下main.s匯編代碼和main.o機(jī)器代碼:
file main3.m
file main.o
image.png
  • xcrun執(zhí)行nm命令查看main.o文件中的符號(hào):
xcrun nm -nm main.o
image.png
  • 此時(shí)只是把當(dāng)前文件編譯為了機(jī)器碼外部符號(hào)(如printf)無(wú)法識(shí)別岖常。

undefined: 表示當(dāng)前文件暫時(shí)找不到符號(hào)驯镊。
external:表示這個(gè)符號(hào)外部可以訪問(wèn)的。(實(shí)現(xiàn)不在我這竭鞍,在外部某個(gè)地方

所以當(dāng)前雖轉(zhuǎn)換成了機(jī)器代碼板惑。但是只是目標(biāo)文件,并不能直接執(zhí)行偎快,需要所有資源鏈接起來(lái)冯乘,才可以執(zhí)行

3.7 生成可執(zhí)行文件(鏈接)

  • 通過(guò)鏈接器把編譯產(chǎn)生的.o文件和.dylib晒夹、.a文件鏈接關(guān)聯(lián)起來(lái)裆馒,生成真正的mach-o可執(zhí)行文件
clang main.o -o main // 將目標(biāo)文件轉(zhuǎn)成可執(zhí)行文件
file main            // 查看文件
xcrun nm -nm main    // 查看main的符號(hào)
image.png
  • 對(duì)比main.o目標(biāo)文件姊氓,此時(shí)生成的main文件:
  1. object文件變成了executable可執(zhí)行文件
  2. 雖然都有undefined,但是可執(zhí)行文件中指定了該符號(hào)來(lái)源庫(kù)领追。機(jī)器在運(yùn)行時(shí)他膳,會(huì)從相應(yīng)的庫(kù)中取讀取符號(hào)(printf)

至此,我們已完整分析:源代碼可執(zhí)行文件整個(gè)流程

image.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市订雾,隨后出現(xiàn)的幾起案子肢预,更是在濱河造成了極大的恐慌,老刑警劉巖洼哎,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烫映,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡噩峦,警方通過(guò)查閱死者的電腦和手機(jī)锭沟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)识补,“玉大人族淮,你說(shuō)我怎么就攤上這事∑就浚” “怎么了祝辣?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)切油。 經(jīng)常有香客問(wèn)我蝙斜,道長(zhǎng),這世上最難降的妖魔是什么白翻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任乍炉,我火速辦了婚禮,結(jié)果婚禮上滤馍,老公的妹妹穿的比我還像新娘。我一直安慰自己底循,他們只是感情好巢株,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著熙涤,像睡著了一般阁苞。 火紅的嫁衣襯著肌膚如雪困檩。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,246評(píng)論 1 308
  • 那天那槽,我揣著相機(jī)與錄音悼沿,去河邊找鬼。 笑死骚灸,一個(gè)胖子當(dāng)著我的面吹牛糟趾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播甚牲,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼义郑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了丈钙?” 一聲冷哼從身側(cè)響起非驮,我...
    開(kāi)封第一講書(shū)人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雏赦,沒(méi)想到半個(gè)月后劫笙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡星岗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年填大,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伍茄。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡栋盹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出敷矫,到底是詐尸還是另有隱情例获,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布曹仗,位于F島的核電站榨汤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏怎茫。R本人自食惡果不足惜收壕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望轨蛤。 院中可真熱鬧蜜宪,春花似錦、人聲如沸祥山。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)缝呕。三九已至澳窑,卻和暖如春斧散,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背摊聋。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工鸡捐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人麻裁。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓箍镜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親悲立。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鹿寨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 什么是LLVM LLVM項(xiàng)目是模塊化、可重用的編譯器以及工具鏈技術(shù)的集合 The LLVM Project is ...
    那位小姐閱讀 2,660評(píng)論 0 10
  • OC底層原理 學(xué)習(xí)大綱[http://www.reibang.com/p/9e19354c0266] 對(duì)象的本質(zhì)...
    markhetao閱讀 1,198評(píng)論 11 1
  • 解釋性語(yǔ)言和編譯性語(yǔ)言的區(qū)別薪夕?解釋性語(yǔ)言可以通過(guò)解釋器直接執(zhí)行相應(yīng)的代碼脚草,比如python語(yǔ)言;而編譯性語(yǔ)言要經(jīng)過(guò)...
    半邊楓葉閱讀 866評(píng)論 0 1
  • 目錄 傳統(tǒng)編譯器設(shè)計(jì) 輸入源代碼(Obj-C, Swift, ...) → 編譯器處理 → 輸出機(jī)器碼(01010...
    小瞎_MarkDash閱讀 1,258評(píng)論 0 2
  • 什么是LLVM LLVM項(xiàng)目是模塊化原献、可重用的編譯器以及工具鏈技術(shù)的集合馏慨。 美國(guó)計(jì)算機(jī)協(xié)會(huì) (ACM) 將其201...
    Coder_LRT閱讀 2,386評(píng)論 0 1