第四十一節(jié)—iOS用到的LLVM(二)

本文為L_Ares個人寫作祖秒,以任何形式轉(zhuǎn)載請表明原文出處。

本文接上一節(jié)——iOS用到的LLVM(一)舟奠。請對LLVMClang不熟悉的同學(xué)們移步上一節(jié)竭缝,了解了基礎(chǔ)的信息之后再閱讀本節(jié)。

一沼瘫、準(zhǔn)備工作

步驟1 : 使用xcode新建一個空的macOS下的commond Line Tool命令行工具抬纸,下面稱之為工程1
圖1.0.0

注意 :

  1. 這里因?yàn)橛玫氖敲钚?commond Line Tool)耿戚,所以初創(chuàng)的情況下沒有對其他的框架造成依賴湿故。
  2. 因?yàn)闆]有依賴昂芜,所以以下的命令都是不引入其他iOS框架的(包括也沒有引入Foundation框架)秩贰。
  3. 如果想要引入其他的框架,那么就在clang命令上添加框架的地址肩祥。下面是舉例的一個命令飞几,引入內(nèi)容按照自己要使用的框架的情況進(jìn)行修改即可砚哆。

clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.2.sdk(自己的SDK路徑) -fmodules -fsyntax-only -Xclang -ast-dump main.m

步驟2 : 打開terminal終端,進(jìn)入到剛創(chuàng)建的這個項(xiàng)目中main.m所在的文件夾下。
步驟3 : 在terminal終端中輸入clang查看詳細(xì)編譯步驟的指令躁锁。
 clang -ccc-print-phases main.m

圖片未必看的清楚纷铣,我把內(nèi)容拷貝下來了,下面稱之為內(nèi)容1战转。

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

解釋

  1. input搜立、preprocessorcompiler槐秧、backend啄踊、assemblerlinker刁标、bind-arch颠通,這些東西表示的是編譯中的操作名稱。
  2. main.m膀懈、{0}.....{5}顿锰,這些東西表示的是這一步操作中要讀取的文件,也就是上一步操作的結(jié)果文件启搂。
  3. objective-c硼控、objective-c-cpp-outputir胳赌、assembler牢撼、objectimage等這些東西就是本步操作完成后疑苫,生成的文件浪默,也就是上面2中說的上一步操作的結(jié)果文件

對于這個工程缀匕,一共有0~6一共7個階段纳决。這就是main.m這個文件從源碼到機(jī)器語言的總的流程。下面開始按照流程來說乡小。

二阔加、源碼的編譯流程

2.1 編譯總流程

命令 :

 clang -ccc-print-phases main.m

編譯總流程就是上面的內(nèi)容1

先闡述總流程0~6中都是什么 :

0: 輸入文件   : "找到源文件"满钟。
1: 預(yù)處理階段  : 這個階段處理了"宏的替換"和"頭文件的導(dǎo)入"胜榔。
2: 編譯階段   : 進(jìn)行"詞法分析"、"語法分析"湃番,"語義分析"夭织。最重要的是要"
生成中間代碼IR"。
3: 后端       : LLVM在這里會"通過一個一個的Pass去優(yōu)化傳入的IR"吠撮,每個Pass做一些事情尊惰,最終生成匯編代碼。
4: 生成匯編代碼。
5: 鏈接       : "鏈接需要的動態(tài)庫和靜態(tài)庫弄屡,生成可執(zhí)行文件"题禀。
6: 最后一步,"通過不同的架構(gòu)膀捷,生成對應(yīng)的可執(zhí)行文件"迈嘹。

這個步驟與之前經(jīng)常提及的編譯流程,0~6步分別對應(yīng)著 :

源文件(0)-->預(yù)編譯(1)-->編譯(2)-->匯編(3,4)-->鏈接(5)-->生成可執(zhí)行文件(6)

2.2 預(yù)處理階段

在2.1的總流程中說過全庸,預(yù)處理階段要做的事情有兩件 :

  • 宏的替換
  • 頭文件的導(dǎo)入

舉例

  1. 打開工程1秀仲,定義一個宏#define JD_NUM 10
  2. 因?yàn)?code>Xcode自帶的頭文件引入#import <Foundation/Foundation.h>是導(dǎo)入Foundation框架壶笼,Foundation框架太大了而且現(xiàn)在我們不需要用神僵,所以頭文件引用就換成#import <stdio.h>
  3. commond + s保存一下拌消。
  4. 打開terminal終端挑豌,進(jìn)入main.m所在的文件夾下安券。
  5. 鍵入clang指令查看預(yù)處理階段的詳細(xì)步驟墩崩。命令如下 (詳細(xì)的Clang命令解釋可以看上一節(jié)中的Clang常用指令)。
  6. 操作圖如下圖2.2.0
圖2.2.0
Clang命令 :
clang -E main.m >> main2.m

解釋 :

現(xiàn)在main.m的文件夾下就會出現(xiàn)main2.m文件侯勉,它就是經(jīng)過預(yù)處理階段操作之后的結(jié)果鹦筹。如下圖2.2.1。

圖2.2.1
  1. 打開main2.m文件址貌,拉到文件的最后铐拐,找到main函數(shù)入口。結(jié)果如下圖2.2.2
圖2.2.2
問 : typedef是不是預(yù)處理階段進(jìn)行的處理练对?

其實(shí)這里通過對#definetypedef本身的概念了解就知道是不一樣的遍蟋,typedef本身是存儲類關(guān)鍵字,本質(zhì)上并不屬于宏或頭文件螟凭。預(yù)處理階段并不會對關(guān)鍵字做解釋虚青。

簡單驗(yàn)證一下 :

  1. 工程1中加入typedef int JD_USE_INT,將int類型創(chuàng)建別名為JD_USE_INT螺男。以后工程1改叫工程2棒厘。
  2. commons + s保存工程2的代碼。
  3. 依然使用clang -E main.m >> main2.m指令下隧,得到main2.m奢人。
  4. 打開main2.m直接找到文本最后的main函數(shù)入口
  5. 操作圖如下圖2.2.3
  6. 結(jié)果圖如下圖2.2.4淆院。
圖2.2.3
圖2.2.4

2.3 編譯階段

編譯階段的主要任務(wù)有3個 :

  • 詞法分析 : 將預(yù)處理階段傳過來的源碼的字符序列一個一個的讀入源程序何乎,然后根據(jù)構(gòu)詞規(guī)則轉(zhuǎn)換成單詞序列(Token)。
  • 語法分析 : 在詞法分析的基礎(chǔ)上,將單詞序列組合成各類語法短句宪赶。例如 : 程序宗弯、語句、表達(dá)式等搂妻。然后將所有的語句節(jié)點(diǎn)抽象出來蒙保,生成抽象語法樹(AST),再檢查源程序的結(jié)構(gòu)是否符合語法規(guī)則欲主。
  • 生成中間代碼IR : 完成上述步驟以后邓厕,代碼生成器會將抽象語法樹(AST)自上而下的遍歷,逐步將其轉(zhuǎn)換成LLVM IR扁瓢。

舉例

1. 詞法分析

  1. terminal終端cd進(jìn)入新的工程2main.m所在文件夾下详恼。
  2. 輸入以下clang指令,查看詞法分析引几。
  3. 源代碼圖為上圖2.2.3昧互,clang結(jié)果圖為下圖2.3.0
  4. 這里注意,空格也算一個位置伟桅。
clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m
圖2.3.0.png

2. 語法分析

  1. terminal終端cd進(jìn)入工程2main.m所在文件夾下敞掘。
  2. 輸入以下clang指令,查看語法分析楣铁。
  3. 結(jié)果如下圖2.3.1
clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
圖2.3.1
  1. FunctionDecl : 方法節(jié)點(diǎn)

    • <line:7:1, line:13:1> :
      方法節(jié)點(diǎn)的代碼范圍是第7行第1個字符第13行第1個字符玖雁。
    • line:7:5 main 'int (int, const char **)' :
      第7行第5個字符的位置開始,是main方法的位置盖腕,第一個int表示main方法的返回值類型赫冬,(int, const char **)表示main方法的參數(shù)類型。
  2. ParmVarDecl : 參數(shù)節(jié)點(diǎn)

    • <col:10, col:14> :
      參數(shù)節(jié)點(diǎn)因?yàn)榕cmain方法在同一行溃列,所以不再說明是第7行劲厌。
      直接說明第一個參數(shù)的位置是第10個字符開始,到第14個字符為止听隐。
    • argc 'int' :
      參數(shù)名稱是argc补鼻,參數(shù)類型是int
    • 上述是第一個參數(shù)的解釋遵绰,下面的第二個參數(shù)相同辽幌,不再贅述。
  3. CompoundStmt : 圍欄椿访,也可以說是范圍乌企,代表的就是main方法的{ }函數(shù)塊區(qū)域。

  4. ObjCAutoreleasePoolStmt : 自動釋放池成玫。

  5. VarDecl : 變量節(jié)點(diǎn)加酵。內(nèi)容比較簡單拳喻,可以自行理解一下。

  6. CallExpr : 調(diào)用函數(shù)猪腕,這一行后面的int代表這個函數(shù)的返回值的類型是int冗澈。這里借助一下圖片,如下圖2.3.2陋葡。

圖2.3.2
  1. BinaryOperator : 函數(shù)的第二個參數(shù)亚亲,這叫字節(jié)運(yùn)算符。這一行表示這個字節(jié)運(yùn)算符是加法運(yùn)算腐缤。表明函數(shù)的第二個參數(shù)是一個加法運(yùn)算的結(jié)果捌归。再看下圖2.3.3
圖2.3.3
  1. ReturnStmt : 返回節(jié)點(diǎn)。
  2. IntegerLiteral : 整型岭粤。
  3. 語法分析階段會對代碼中的錯誤進(jìn)行提示惜索。例如將工程1的代碼去掉一個;,重新運(yùn)行語法分析的clang指令剃浇,結(jié)果如下圖2.3.4巾兆,明顯提示少了一個;,在第10行的第42個字符處虎囚。
圖2.3.4

3. 生成中間代碼LLVM IR

IR的基本語法
語法 釋義
; 注釋
@ 全局標(biāo)識
% 局部標(biāo)識
alloca 開辟空間
align 內(nèi)存對齊
i32 32bit角塑,4字節(jié)
store 寫入內(nèi)存
load 載入內(nèi)存
call 調(diào)用函數(shù)
ret 返回
操作
  1. 修改工程2的代碼,多添加一個函數(shù)溜宽,方便把所有的IR代碼的語法都了解一遍吉拳。新的工程命名為工程3质帅。工程3代碼如下 :
#import <stdio.h>

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

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

  1. commond + S保存工程3的代碼适揉。
  2. terminal終端cd進(jìn)入工程3所在文件夾下。
  3. 輸入以下clang指令煤惩,生成IR文件嫉嘀。
  4. clang指令執(zhí)行完成后,會在main.m文件所在的文件夾下生成main.ll文件魄揉。
  5. 生成main.ll的結(jié)果如下圖2.3.5剪侮。
clang -S -fobjc-arc -emit-llvm main.m
圖2.3.5.png
  1. 可以利用Sublime Text打開main.ll文件,并將Sunlime Text軟件右下角的Plain Text改成Objective-C的格式洛退。結(jié)果如下圖2.3.6瓣俯。
圖2.3.6.png

2.4 優(yōu)化器

我們知道了ClangLLVM的前端,Clang做了2.2預(yù)處理階段2.3編譯階段的事情兵怯,那么從哪里開始算是LLVM的后端彩匕?

優(yōu)化器(Optimizer)和代碼生成器(CodeGenerator)都可以算作LLVM后端

  • 后端的作用 :
    (1). 優(yōu)化媒区。
    2.3編譯階段最后生成的LLVM IR代碼傳入一個一個的Pass進(jìn)行IR優(yōu)化驼仪,每個Pass都會對傳入的IR進(jìn)行本Pass要做的優(yōu)化掸犬。
    (2). 生成匯編代碼。
    完成所有所需Pass優(yōu)化的IR將會變成匯編代碼绪爸。
  • 什么是Pass?
    (1). 首先湾碎,Pass是節(jié)點(diǎn)。是LLVM優(yōu)化過程中的優(yōu)化邏輯所在之處奠货。
    (2). 其次介褥,Pass是屬于LLVM的后端(Backend)的。
    (3). 最后递惋,LLVM的優(yōu)化是以節(jié)點(diǎn)(Pass)來完成的呻顽,是一個節(jié)點(diǎn)一個節(jié)點(diǎn)去完成的,所有節(jié)點(diǎn)一起合作之后丹墨,才完成了LLVM的優(yōu)化的轉(zhuǎn)化廊遍。
    例如 : 有的節(jié)點(diǎn)是負(fù)責(zé)運(yùn)算之后將冗余的代碼減去的,有的節(jié)點(diǎn)則是負(fù)責(zé)跳轉(zhuǎn)之后再減去冗余代碼的贩挣。
  • 什么是bitCode?
    (1). 蘋果在xcode7之后可以開啟bitCode喉前,在iOS中,我們說bitCode是蘋果對LLVM在編譯階段生成的IR的一種特殊形式王财,本質(zhì)上bitCode也是IR卵迂,也是中間代碼,它以二進(jìn)制形式存在绒净,蘋果推出bitCode就是一種官方的優(yōu)化方式。
    (2). 在經(jīng)過bitCode的優(yōu)化之后挂疆,IR代碼文件會轉(zhuǎn)化成.bc文件格式的中間代碼改览。

舉例

很明顯,通過2.3編譯階段生成的IR在閱讀理解上是很冗余的缤言,短短的幾行簡單的代碼都變得很長宝当,所以LLVM中存在對IR代碼進(jìn)行一些適當(dāng)?shù)膬?yōu)化,當(dāng)然這個優(yōu)化在xcode上面是可選擇的胆萧。還是選擇以工程3為基本庆揩,如圖2.4.0。

圖2.4.0.png

xcode是帶有對IR代碼是否進(jìn)行優(yōu)化的可視化界面的跌穗,一般情況下订晌,Debug模式下默認(rèn)都是沒有開啟代碼優(yōu)化,而Release模式下蚌吸,則開啟了優(yōu)化锈拨。

4.1 LLVM的優(yōu)化級別
級別 釋義
O0 None,不進(jìn)行IR優(yōu)化
O1 Fast
O2 Faster
O3 Fastest
Os Fastest , Smallest
Ofast 比Os還要更近一步的優(yōu)化
Oz 讓IR代碼體積最小的優(yōu)化

注釋 : 級別的中的O是英文字母套利,不是數(shù)字0推励。

4.2 利用命令行對IR進(jìn)行優(yōu)化的舉例

還是利用工程3鹤耍,我們就不直接利用xcode的優(yōu)化了,為了看到優(yōu)化的IR代碼验辞,利用終端的命令行對IR代碼進(jìn)行優(yōu)化稿黄。

  1. 利用終端,進(jìn)入到工程3main.m所在文件夾下跌造。
  2. 終端中輸入以下clang命令
clang -Os -S -fobjc-arc -emit-llvm main.m
  1. 依然利用Sublime Text打開main.ll文件杆怕,調(diào)整成OC的語法格式。
  1. 結(jié)果如下圖2.4.1所示壳贪。
圖2.4.1.png
4.3 bitCode的生成

還是利用工程3陵珍。

  1. 利用終端進(jìn)入工程3main.m所在的文件夾下。
  2. 終端中輸入以下clang命令违施,先生成IRmain.ll文件互纯。
clang -S -fobjc-arc -emit-llvm main.m
  1. 再在終端中輸入以下clang命令,利用main.ll文件生成main.bc文件磕蒲。
clang -emit-llvm -c main.ll -o main.bc
  1. 生成的結(jié)果如下圖2.4.2所示留潦。
圖2.4.2.png

2.5 匯編

2.5.1 直接生成匯編

直接利用上面圖2.4.2中的3個文件。

  1. .m格式的源文件轉(zhuǎn)化為匯編代碼辣往,利用下述命令兔院。
clang -S -fobjc-arc main.m -o main.s
  1. .ll格式的IR代碼文件轉(zhuǎn)化為匯編代碼,利用下述命令站削。
clang -S -fobjc-arc main.ll -o main1.s
  1. .bc格式的bitCode優(yōu)化后的文件轉(zhuǎn)化為匯編代碼坊萝,利用下述命令。
clang -S -fobjc-arc main.bc -o main2.s

結(jié)果如下圖2.5.0和2.5.1所示

圖2.5.0.png
圖2.5.1.png

2.5.2 生成匯編可進(jìn)行優(yōu)化

生成匯編進(jìn)行的優(yōu)化是對機(jī)器語言的優(yōu)化许起。

我們已經(jīng)知道十偶,源碼變成匯編的過程要經(jīng)過 : 源碼 --> IR --> bitcode --> 匯編,其實(shí)除了在源碼 --> IR的時候可以進(jìn)行優(yōu)化街氢,在生成匯編的時候扯键,系統(tǒng)還是會進(jìn)行一步優(yōu)化睦袖,我們在上一節(jié)的傳統(tǒng)優(yōu)化器的設(shè)計(jì)中說過后端/代碼生成器也有優(yōu)化能力珊肃。

還是利用工程3的源碼。并且優(yōu)化的級別統(tǒng)一選定為最高級別Os馅笙,其他的級別自行更換嘗試伦乔。

  1. 源碼直接生成匯編的優(yōu)化
clang -Os -S -fobjc-arc main.m -o main3.s

對比main.m未經(jīng)過優(yōu)化和經(jīng)過優(yōu)化分別生成的匯編main.smain3.s :

圖2.5.2.png
  1. IR生成匯編的優(yōu)化
clang -Os -S -fobjc-arc main.ll -o main4.s
圖2.5.3.png
  1. bc生成匯編的優(yōu)化
clang -Os -S -fobjc-arc main.bc -o main5.s
圖2.5.4.png

因?yàn)槲覀兊脑创a只有最簡單的11行,所以優(yōu)化的效果不會有那么的大董习,但也可以看得出來優(yōu)化的效果還是很好的烈和。

但是!C罅堋招刹!這里我們正常的情況下是不可以手動的進(jìn)行調(diào)節(jié)的恬试。

對比IR的優(yōu)化來看,IR的優(yōu)化我們可以在xcode中就可以進(jìn)行配置疯暑,就是上面的圖2.4.0训柴,而生成匯編的時候進(jìn)行的優(yōu)化,我們沒有辦法人工的干預(yù)妇拯。

2.6 生成目標(biāo)文件和生成可執(zhí)行文件(鏈接)

以下所有的操作都是以工程3為基礎(chǔ)的幻馁。

2.6.1 生成目標(biāo)文件

目標(biāo)文件的生成是匯編器以匯編代碼作為輸入,將匯編代碼轉(zhuǎn)換成機(jī)器代碼越锈,最后輸出目標(biāo)文件(object file)仗嗦。

常用命令是 :

clang -fmodules -c main.s -o main.o

命令結(jié)果 :

圖2.6.0.png

查看目標(biāo)文件main.o的符號的命令 :

xcrun nm -nm main.o

命令結(jié)果 :

圖2.6.1.png
  1. undefined : 表示在當(dāng)前文件,暫時找不到某個符號甘凭,比如在上圖2.6.1中就是說找不到_printf這個符號稀拐,也就是找不到printf這個方法。

  2. external : 表示這個符號是外部可以訪問的丹弱。比如上圖的2.6.1中找不到的_printf這個符號是可以在外部訪問的到的钩蚊,也就是說printf這個方法不是本文件的方法,但是是可以經(jīng)過外部的文件找得到的方法蹈矮。

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

我們知道砰逻,可執(zhí)行文件的生成就是由很多的.o文件來完成的。這些.o文件要集合在一起需要要存在一些的聯(lián)系泛鸟,而這個聯(lián)系就是由鏈接(linker)來做到的蝠咆。

連接器把編譯產(chǎn)生的.o文件和.dylib.a文件生成一個mach-o文件。

用下述命令生成可執(zhí)行文件 :

clang main.o -o main

生成可執(zhí)行文件的結(jié)果 :

圖2.6.2.png

鏈接之后北滥,我們再查看可執(zhí)行文件的符號刚操,對比目標(biāo)文件來看。

查看可執(zhí)行文件的符號的命令 :

xcrun nm -nm main

結(jié)果圖 :

圖2.6.3.png

從圖3.6.3中可以看到再芋,雖然undefined標(biāo)識是依然存在的菊霜,但是后面的括號中已經(jīng)告訴我們_printf符號是來自于libSystem的。

那為什么要有這個from libSystem呢济赎?

因?yàn)楫?dāng)這個可執(zhí)行文件main要被執(zhí)行的時候鉴逞,main內(nèi)部有一個符號_printf是來自于外部,當(dāng)要調(diào)用這個_printf的時候司训,dyld會在加載的時候進(jìn)行綁定构捡,而如何綁定呢?就會根據(jù)符號提供的位置壳猜,也就是(from libSystem)來確定_printf符號是來自于libSystem的勾徽,這時iOS的操作系統(tǒng)中的libSystem動態(tài)庫就會把_printf的地址告訴dyld,然后進(jìn)行符號的綁定统扳。

所以說喘帚,這個符號是在運(yùn)行的時候動態(tài)綁定的畅姊。這也是為什么fishhook可以去hook一些外部函數(shù)的原因。

當(dāng)main這個可執(zhí)行文件生成之后吹由,我們就可以直接執(zhí)行這個main涡匀,命令行如下 :

./main

結(jié)果如下圖 :

圖2.6.4.png

也可以查看一下main的基本信息,比如它的格式溉知、版本信息陨瘩、運(yùn)行所需的系統(tǒng)要求等,命令行 :

file main

結(jié)果如下圖 :

圖2.6.5.png

可以看到main的文件格式是Mach-O级乍,是64位的x86架構(gòu)下可運(yùn)行的舌劳,也就是說main是一個單一架構(gòu)的文件不是胖二進(jìn)制文件。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末玫荣,一起剝皮案震驚了整個濱河市甚淡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捅厂,老刑警劉巖贯卦,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異焙贷,居然都是意外死亡撵割,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門辙芍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來啡彬,“玉大人,你說我怎么就攤上這事故硅∈樱” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵吃衅,是天一觀的道長往踢。 經(jīng)常有香客問我,道長徘层,這世上最難降的妖魔是什么峻呕? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮惑灵,結(jié)果婚禮上山上,老公的妹妹穿的比我還像新娘。我一直安慰自己英支,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布哮伟。 她就那樣靜靜地躺著干花,像睡著了一般妄帘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上池凄,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天抡驼,我揣著相機(jī)與錄音,去河邊找鬼肿仑。 笑死致盟,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的尤慰。 我是一名探鬼主播馏锡,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼伟端!你這毒婦竟也來了杯道?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤责蝠,失蹤者是張志新(化名)和其女友劉穎党巾,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霜医,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡齿拂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了肴敛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片创肥。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖值朋,靈堂內(nèi)的尸體忽然破棺而出叹侄,到底是詐尸還是另有隱情,我是刑警寧澤昨登,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布趾代,位于F島的核電站,受9級特大地震影響丰辣,放射性物質(zhì)發(fā)生泄漏撒强。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一笙什、第九天 我趴在偏房一處隱蔽的房頂上張望飘哨。 院中可真熱鬧,春花似錦琐凭、人聲如沸芽隆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胚吁。三九已至牙躺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腕扶,已是汗流浹背孽拷。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留半抱,地道東北人脓恕。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像窿侈,于是被迫代替她去往敵國和親炼幔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

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

  • 本文為L_Ares個人寫作棉磨,以任何形式轉(zhuǎn)載請表明原文出處江掩。 內(nèi)容較多,本文盡量不廢話乘瓤,看起來會有點(diǎn)刻板环形,但都是干貨...
    L_Ares閱讀 877評論 0 3
  • 1.概念 1.LLVM LLVM是架構(gòu)編譯器(compiler)的框架系統(tǒng),以c++編寫而成衙傀,用于優(yōu)化以任意程序語...
    MonKey_Money閱讀 1,157評論 0 3
  • LLVM的概念 日常開發(fā)過程我們的開發(fā)工具或多或少都跟LLVM扯得上一點(diǎn)關(guān)系抬吟,那么什么是LLVM呢?它有什么作用呢...
    沉淀紛飛閱讀 532評論 0 3
  • 1. 寫在前面 現(xiàn)在出去面試统抬,啟動優(yōu)化是繞不開的胎食,到底我們的 APP 該如何去進(jìn)行優(yōu)化呢 吓著?在優(yōu)化之前我們必須要先...
    俊而不遜閱讀 1,358評論 0 5
  • iOS之武功秘籍 文章匯總[http://www.reibang.com/p/07991e5b1c30] 寫在前...
    長茳閱讀 582評論 0 3