http://blog.csdn.net/banyao2006/article/details/7045216
摘要
該文檔是LLVM匯編語(yǔ)言的參考指南。LLVM是基于表示的靜態(tài)單賦值(SSA),該表示提供類型安全、低層級(jí)操作,靈活性,及簡(jiǎn)潔表示所有高層級(jí)語(yǔ)言的能力。這是貫穿各方面LLVM編譯策略的通用代碼表示。
簡(jiǎn)介
LLVM代碼表示用于三個(gè)不同形式:作為在內(nèi)存(in-memory)編譯器IR、磁盤(pán)比特碼表示(適合即時(shí)編譯器的快速加載),以及人類可讀的匯編語(yǔ)言表示。這讓LLVM為高效編譯器轉(zhuǎn)換和分析提供強(qiáng)大的中間表示的同時(shí),提供調(diào)試和轉(zhuǎn)換可視化的自然手段。LLVM的三種不同形式是等價(jià)的。該文檔描述了人類可讀的表示和注解。
LLVM表示旨在具有易于表達(dá)、類型化和擴(kuò)展性的同時(shí)保持輕量級(jí)和低層級(jí)。它通過(guò)處于可清晰映射高層想法的足夠低的層級(jí)(類似于微處理器允許許多源語(yǔ)言映射其上而成為通用IR),使其成為通用IR。通過(guò)提供類型信息,LLVM可用于優(yōu)化的目的:例如,通過(guò)指針?lè)治觯勺C明C自動(dòng)變量永遠(yuǎn)不會(huì)訪問(wèn)當(dāng)前函數(shù)以外的部分...允許其使用簡(jiǎn)單的SSA以代替內(nèi)存位置。
規(guī)范化
記住,該文檔描述的是規(guī)范化的LLVM匯編語(yǔ)言,這很重要。語(yǔ)法分析器的接受范圍與規(guī)范化之間有所差異。例如,下列指令句法通順,但不夠規(guī)范化:
%x = add i32 1, %x
因?yàn)?span lang="EN-US">%x的定義不能控制自身的所有使用。LLVM基礎(chǔ)架構(gòu)提供驗(yàn)證LLVM模塊是否規(guī)范化的驗(yàn)證pass。在語(yǔ)法分析輸入的匯編后由語(yǔ)法分析器和在其輸出比特碼前由優(yōu)化器自動(dòng)運(yùn)行該pass。驗(yàn)證pass指出的違反行為指名了轉(zhuǎn)換pass或語(yǔ)法分析器輸入的bug。
標(biāo)識(shí)符
LLVM標(biāo)識(shí)符具有兩種基本類型:全局和局部。全局標(biāo)識(shí)符(函數(shù),全局變量)以'@'起始。局部標(biāo)識(shí)符(寄存器名字,類型)以'%'起始。另外,標(biāo)識(shí)符針對(duì)不同目的有三種不同格式:
1 命名值表示為字符串及其前綴。例如,%foo, @DivisionByZero, %a.really.long.identifier。實(shí)際的正則表達(dá)式是'[%@][a-zA-Z$._][a-zA-Z$._0-9]*'。在其名字里需要其它字符的標(biāo)識(shí)符會(huì)被引用環(huán)繞。特殊字符可使用"\xx"表示,其中xx是字符ASCII碼的16進(jìn)制表示。這樣,所有字符可用于命名值,甚至引用自身。
2 未命名值利用無(wú)符號(hào)數(shù)值及其前綴表示。例如,%12, @2, %44。
3 常量,在下面的章節(jié)“常量”中描述。
LLVM需要以前綴起始取值有兩個(gè)原因:編譯器無(wú)需擔(dān)心保留字的命名沖突,而且保留字的集合可在未來(lái)無(wú)懲罰地?cái)U(kuò)展。另外,未命名標(biāo)識(shí)符允許編譯器無(wú)需刻意避免符號(hào)表沖突而快速使用臨時(shí)變量。
LLVM保留字與其它語(yǔ)言非常相似。關(guān)鍵字包括不同操作碼(add, bitcast,ret等),基本類型名(void,i32等)和其它。這些保留字不會(huì)與變量名沖突,因?yàn)榍罢叨疾灰郧熬Y字符('%'或'@')起始。
這是整數(shù)變量'%x'乘以8的LLVM代碼示例。
簡(jiǎn)單方式:
%result = mul i32 %x, 8
簡(jiǎn)化之后:
%result = shl i32 %x, i8 3
復(fù)雜方式:
%0 = add i32 %X, %X ; 生成 {i32}:%0
%1 = add i32 %0, %0 ; 生成 {i32}:%1
%result = add i32 %1, %1
最后一種實(shí)現(xiàn)%x乘以8的方式表明LLVM許多重要詞法特點(diǎn):
1.注釋以';'界定,直到行尾。
2.當(dāng)計(jì)算結(jié)果未賦值給命名變量時(shí),創(chuàng)建未命名臨時(shí)變量。
3.未命名臨時(shí)變量順序編號(hào)。
還表明該文檔中遵循的習(xí)慣。當(dāng)展示指令時(shí),指令之后是定義生成值類型和命名的注釋。注釋以italic文本呈現(xiàn)。
高層結(jié)構(gòu)
模塊結(jié)構(gòu)
LLVM程序是由"模塊"組成的,每個(gè)模塊是輸入程序的一個(gè)轉(zhuǎn)換單元。每個(gè)模塊包括函數(shù)、全局變量和符號(hào)表入口。模塊可由LLVM鏈接器組合在一起,這將合并函數(shù)(全局變量)的定義,解析之后的聲明,并合并符號(hào)表入口。這是"hello world"模塊的示例:
; 聲明string常量作為全局常量
@.LC0 = internal constant [13 x i8] c"hello world\0A\00" ; [13 x i8]*
; puts函數(shù)的外部聲明
declare i32 @puts(i8 *) ; i32(i8 *)*
; main函數(shù)的定義
define i32 @main() { ; i32()*
; Convert [13 x i8]* to i8 *...
%cast210 = getelementptr [13 x i8]* @.LC0, i64 0, i64 0 ; i8 *
; Call puts function to write out the string to stdout...
call i32 @puts(i8 * %cast210) ; i32
ret i32 0
}
本例由全局變量".LC0",puts函數(shù)的外部聲明和main的函數(shù)定義組成。
通常地,模塊由一系列的全局值組成,其中函數(shù)和全局變量都是全局值。全局值以指向內(nèi)存位置的指針(因此,指向字符數(shù)組的指針,指向函數(shù)的指針)表示,并具有下列鏈接類型的一種。
鏈接類型
所有全局變量和函數(shù)具有下列鏈接類型之一:
private 具有私有鏈接的全局值只能被當(dāng)前模塊的對(duì)象直接訪問(wèn)。特別地,具有私有全局值模塊的鏈接代碼可能在必要時(shí)導(dǎo)致對(duì)私有部分重命名,以避免沖突。由于該符號(hào)對(duì)模塊是私有的,所有引用會(huì)被更新。這并不會(huì)在目標(biāo)文件的任何符號(hào)表有所顯示。
linker_private 類似私有鏈接,但該符號(hào)通過(guò)匯編器并由鏈接器在求值后移除。
internal 類似私有鏈接,但其值在目標(biāo)文件中顯示為局部符號(hào)(ELF文件格式的STB_LOCAL)。這對(duì)應(yīng)C語(yǔ)言的static關(guān)鍵字。
available_externally 具有"有效外部"鏈接的全局值不會(huì)引入到LLVM模塊對(duì)應(yīng)的目標(biāo)文件。它們的存在是為進(jìn)行內(nèi)聯(lián)和其它優(yōu)化時(shí)告知位于模塊外的全局值定義具體位置。具有有效外部鏈接的全局值可隨意丟棄,否則與linkconce_odr鏈接類型一樣。該鏈接類型只能定義不能聲明。
linkonce 具有"僅鏈接一次"鏈接的全局值在鏈接發(fā)生時(shí),與同名的其它全局值合并。這典型地用實(shí)現(xiàn)內(nèi)聯(lián)函數(shù),模板或在每個(gè)使用該鏈接的轉(zhuǎn)換單元中生成的其它代碼。未引用的linkonce全局值可丟棄。
weak "弱"鏈接與linkonce鏈接具有相同的合并語(yǔ)法,除未引用的弱鏈接全局值不丟棄外。這用于C源碼中聲明為"weak"的全局值。
common "通用"鏈與"弱"鏈接極其相似,但它們用于C的定義,例如全局作用域的"int X;"。"通用"鏈接的符號(hào)與weak符號(hào)一樣,以同樣的方式合,而且若未引用,該鏈接可能也不會(huì)刪除。通用符號(hào)可沒(méi)有顯式段,但必須零初始化,且可能未標(biāo)記為'constant'。函數(shù)和別名可能沒(méi)有通用鏈接。
appending "附加"鏈接只用于指向數(shù)組類型的全局變量。兩個(gè)具有appending鏈接的全局變量鏈接在一起時(shí),兩個(gè)全局?jǐn)?shù)組附加在一起。這就是在鏈接.o文件時(shí)LLVM系統(tǒng)鏈接器將相同名稱的“段”附加在一起的類型安全和等性。
extern_weak 該鏈接的語(yǔ)法含義遵循ELF目標(biāo)文件模型:該符號(hào)直到進(jìn)行鏈接是才是weak類型,如果未鏈接,該符號(hào)會(huì)用null替代未定義的引用。
linkonce_odr
weak_odr 一些語(yǔ)言允許不同的全局值進(jìn)行合并,例如不同語(yǔ)義的兩個(gè)函數(shù)。其它語(yǔ)言,例如C++,保證只有等價(jià)的全局值才能合并("一次定義規(guī)則"-"ODR")。這樣的語(yǔ)言可使用linkonce_odr和weak_odr鏈接類型以表明只有等價(jià)的全局值才能合并。這些鏈接類型在其它方面與非odr版本具有相同屬性。
externally 若以上標(biāo)識(shí)符都沒(méi)有使用,全局值則是外部可見(jiàn)的,這意味全局值參與鏈接并可用于解析外部符號(hào)引用。
以下兩種鏈接類型僅針對(duì)微軟Windows平臺(tái)。它們?yōu)橹С謴?span lang="EN-US">DLL(Dynamic Link Library)引入符號(hào)(或?qū)С龇?hào)至DLL)而設(shè)計(jì)。
dllimport "dllimport"鏈接導(dǎo)致編譯器通過(guò)由DLL導(dǎo)出符號(hào)建立的指向指針的全局指針,引用函數(shù)或變量。
dllexport "dllexport"鏈接導(dǎo)致編譯器提供DLL中指向指針的全局指針,以使該全局值可利用dllimport屬性引用。在微軟Windows目標(biāo)平臺(tái),指針通過(guò)聯(lián)合_imp_和函數(shù)或變量名的形式命名。
例如,".LC0"變量定義為interal,如果其它模塊定義了".LC0"變量且該變量被鏈接,兩者之一將被重命名以避免沖突。既然"main"和"puts"是external類型(比如缺少鏈接聲明),它們可在當(dāng)前模塊外被訪問(wèn)。
除了"外部可見(jiàn)",dllimport或extern_weak外,函數(shù)聲明的其它鏈接類型都是不合法的。
別名僅有external, internal, weak或weak_odr鏈接。
調(diào)用約定
LLVM的函數(shù),call和invoke都可為指定的調(diào)用設(shè)定可選的調(diào)用約定。動(dòng)態(tài)調(diào)用者/被調(diào)用者配對(duì)的調(diào)用約定必須匹配,否則程序行為未定義。LLVM支持下列調(diào)用約定,且可能在將來(lái)有所增加。
"ccc" - C調(diào)用約定
該調(diào)用約定(如果沒(méi)有指定其它調(diào)用約定,默認(rèn)使用該調(diào)用約定)匹配目標(biāo)平臺(tái)的C調(diào)用約定。它支持可變參數(shù)(varargs)函數(shù)調(diào)用,并容忍函數(shù)原型聲明和聲明實(shí)現(xiàn)的一些誤配(就像正常C行為)。
"fastcc" - 快速調(diào)用約定
該調(diào)用約定試圖使調(diào)用盡可能快(例如通過(guò)寄存器傳值)。它允許目標(biāo)平臺(tái)使用任何小技巧以產(chǎn)生該平臺(tái)的快速代碼,而無(wú)需與外部指定的ABI(Application Binary Interface)保持一致。其實(shí)現(xiàn)支持任意的推后調(diào)用優(yōu)化(tail call optimization)。它不支持可變參數(shù),且要求所有被調(diào)用者的原型與函數(shù)定義的原型完全匹配。
"coldcc" - 生冷的調(diào)用約定
該調(diào)用約定基于調(diào)用不常執(zhí)行這一假定,試圖使調(diào)用者的代碼盡可能有效。因此,這些調(diào)用常保護(hù)所有寄存器,以致調(diào)用不會(huì)破壞調(diào)用者邊界的任何數(shù)據(jù)區(qū)域。它不支持可變參數(shù),且要求所有被調(diào)用者的原型與函數(shù)定義的原型完全匹配。
"cc <n>" - 編號(hào)約定
所有調(diào)用約定可通過(guò)編號(hào)指定,可用于目標(biāo)平臺(tái)相關(guān)的調(diào)用約定。目標(biāo)平臺(tái)相關(guān)的調(diào)用約定從64開(kāi)始編號(hào)。
更多的調(diào)用約定可按需增加/定義,以支持Pascal約定或所有其它熟知的與目標(biāo)平臺(tái)無(wú)關(guān)的約定。
可見(jiàn)性樣式
所有全局變量和函數(shù)具有下列可見(jiàn)性樣式之一:
"default" - 默認(rèn)樣式
在使用ELF目標(biāo)文件格式的目標(biāo)平臺(tái)上,默認(rèn)可見(jiàn)性意味著聲明對(duì)其它模塊可見(jiàn),對(duì)于共享庫(kù)意味著聲明實(shí)體可被覆蓋(override)。對(duì)于Darwin平臺(tái),默認(rèn)可見(jiàn)性意味著聲明可對(duì)其它模塊可見(jiàn)。默認(rèn)可見(jiàn)性對(duì)應(yīng)語(yǔ)言的"外部鏈接"。
"hidden" - 隱藏樣式
如果具有隱藏樣式對(duì)象的兩個(gè)聲明位于同一共享目標(biāo)文件時(shí),它們引用同一目標(biāo)。隱藏可見(jiàn)性通常表明,符號(hào)不會(huì)位于動(dòng)態(tài)符號(hào)表,因此沒(méi)有其它模塊(可執(zhí)行或共享庫(kù))能直接引用該符號(hào)。
"protected" - 保護(hù)樣式
ELF的保護(hù)可見(jiàn)性表明,符號(hào)將會(huì)位于動(dòng)態(tài)符號(hào)表,但在定義模塊內(nèi)的引用會(huì)綁定為局部符號(hào)。也就是說(shuō),該符號(hào)不會(huì)被其它模塊覆蓋。
命名類型
LLVM IR允許對(duì)確定類型指定別名。這可使IR更可讀和更緊湊(condense)(特別是涉及遞歸類型時(shí))。下面是命名規(guī)范的示例:
%mytype = type { %mytype*, i32 }
除"void"外可以給定所有類型命名。類型名字別名可用于任何識(shí)別到"%mytype"語(yǔ)法的地方。
記住,針對(duì)指定結(jié)構(gòu)的類型進(jìn)行類型名字別名,而且你還能對(duì)同一類型指定不同名字。當(dāng)輸出.ll文件時(shí),這常導(dǎo)致混淆的行為。既然LLVM IR使用結(jié)構(gòu)的類型,名字就不是類型的一部分。當(dāng)輸出LLVM IR時(shí),打印器(printer)將挑選一個(gè)名字以返回(render)特有形狀的所有類型。這意味著,如果對(duì)以同一LLVM類型結(jié)尾的不同源類型進(jìn)行編碼,輸出器(dumper)有時(shí)輸出"錯(cuò)誤"或意外的類型。這是重要的設(shè)計(jì)觀點(diǎn),且不會(huì)改變。
全局變量
全局變量定義了在編譯期而非運(yùn)行期的內(nèi)存分配區(qū)域。它可被任意值初始化,可位于顯式段(section),還具有可選的顯式指定對(duì)齊。變量可定義為"thread_local",這意味它不會(huì)被線程共享(每個(gè)線程將具有它的獨(dú)立拷貝)。變量也可定義為全局"常量",這表明它的內(nèi)容永不會(huì)被修改(允許更好的優(yōu)化,可將全局?jǐn)?shù)據(jù)位于執(zhí)行代碼的只讀段等)。記住,需要在運(yùn)行時(shí)初始化的變量不能標(biāo)記為"常量",是因?yàn)樗写鎯?chǔ)空間。
LLVM顯式允許全局變量的聲明標(biāo)記為常量,甚至它的最終定義并非如此。這可用于使程序優(yōu)化效果好一些,但需要語(yǔ)言定義以保證基于'constantness'的優(yōu)化對(duì)并不包含定義的轉(zhuǎn)換單元有效。
如SSA賦值,全局變量定義程序中具有所有基本塊作用域(例如指針指向的)的指針值。它總定義至其"內(nèi)容"類型的指針,是因?yàn)楹笳呙枋隽藘?nèi)存區(qū)域和可通過(guò)指針訪問(wèn)的所有LLVM內(nèi)存目標(biāo)。
全局變量可聲明位于目標(biāo)平臺(tái)相關(guān)的計(jì)數(shù)地址空間。對(duì)于支持以上操作的目標(biāo)平臺(tái),地址空間可能會(huì)影響優(yōu)化器的執(zhí)行和/或可訪問(wèn)該變量的目標(biāo)平臺(tái)指令。默認(rèn)的地址空間是零。地址空間的限制必須處于其它屬性之前。
LLVM允許指定針對(duì)全局值的顯式段。如果目標(biāo)平臺(tái)支持的話,LLVM將發(fā)射全局值至指定段。
還可對(duì)全局值指定顯式的對(duì)齊。如果沒(méi)設(shè)置,或是對(duì)齊設(shè)為零,全局值的對(duì)齊將設(shè)置為目標(biāo)平臺(tái)方便的值。如果指定了顯式對(duì)齊,全局值強(qiáng)制具有至少指定的對(duì)齊值。所有對(duì)齊必須為2的冪。
例如,下列定義了位于計(jì)數(shù)地址空間的全局值,具有初始器,段和對(duì)齊:
@G = addrspace(5) constant float 1.0, section "foo", align 4
函數(shù)
LLVM函數(shù)定義由"define"關(guān)鍵字、可選的鏈接類型、可選的可見(jiàn)樣式、可選的調(diào)用慣例、返回類型、可選的返回類型參數(shù)屬性、函數(shù)名稱、(可能為空的)參數(shù)列表(每一個(gè)參數(shù)都有可選的參數(shù)屬性)、可選的函數(shù)屬性、可選的段、可選的對(duì)齊、可選的垃圾回收器、打開(kāi)的花括號(hào)、基本塊列表和封閉的花括號(hào)組成。
LLVM函數(shù)聲明由"declare"關(guān)鍵字、可選的鏈接類型、可選的可見(jiàn)樣式、可選的調(diào)用慣例、返回類型、可選的返回類型參數(shù)屬性、函數(shù)名稱、可能為空的參數(shù)列表、可選的對(duì)齊和可選的垃圾回收器組成。
函數(shù)定義包含基本塊列表以形成該函數(shù)的CFG(控制流圖)。每個(gè)基本塊可選地以標(biāo)號(hào)(給出基本塊的符號(hào)表入口)起始,包含指令列表,并以終止指令(例如跳轉(zhuǎn)或函數(shù)返回)結(jié)束。
函數(shù)的第一個(gè)基本塊有兩點(diǎn)特殊性:進(jìn)入函數(shù)時(shí)直接執(zhí)行,且不允許具有前趨基本塊(例如,函數(shù)入口的塊不能有任何分支)。因?yàn)樵搲K沒(méi)有前趨,它同樣沒(méi)有任何PHI節(jié)點(diǎn)。
LLVM允許為函數(shù)指定顯式段。如果目標(biāo)平臺(tái)支持的話,LLVM將函數(shù)置于指定的段。
對(duì)函數(shù)可指定顯式的對(duì)齊。如果未設(shè)置,或是對(duì)齊設(shè)置為零,函數(shù)的對(duì)齊會(huì)設(shè)置為目標(biāo)平臺(tái)方便的值。如果指定顯式的對(duì)齊,函數(shù)強(qiáng)制至少具有指定的對(duì)齊。所有對(duì)齊必須是2的冪。
語(yǔ)法:
define [linkage] [visibility]
[cconv] [ret attrs]
<ResultType> @<FunctionName> ([argument list])
[fn Attrs] [section "name"] [align N]
[gc] { ... }
別名
別名作為被別名值(the aliasee value)(可為函數(shù)、全局變量、另一個(gè)別名或全局值的位轉(zhuǎn)換)的"第二名稱"。別名可具有可選的鏈接類型和可選的可見(jiàn)樣式。
語(yǔ)法:
@<Name> = alias [Linkage] [Visibility] <AliaseeTy> @<Aliasee>
參數(shù)屬性
返回類型和函數(shù)類型的每個(gè)參數(shù)可具有與其相關(guān)的參數(shù)屬性集合。參數(shù)屬性用于表達(dá)函數(shù)結(jié)果或參數(shù)的額外信息。參數(shù)屬性被認(rèn)為是函數(shù)而非函數(shù)類型的一部分,因此具有不同參數(shù)屬性的函數(shù)可具有同一函數(shù)類型。
參數(shù)屬性是遵循指定類型的簡(jiǎn)單關(guān)鍵字。如果需要多個(gè)函數(shù)屬性,則以空格分隔。例如:
declare i32 @printf(i8* noalias nocapture, ...)
declare i32 @atoi(i8 zeroext)
declare signext i8 @returns_signed_char()
記住,函數(shù)結(jié)果(nounwind,只讀)的任何屬性直接位于參數(shù)列表后。
當(dāng)前,只定義了下列參數(shù)屬性:
zeroext
這表明,代碼生成器中調(diào)用者或被調(diào)用者分別將參數(shù)或返回值零擴(kuò)展為32位值。
signext
這表明,代碼生成器中調(diào)用者或被調(diào)用者分別將參數(shù)或返回值符號(hào)擴(kuò)展為32位值。
inreg
這表明,在函數(shù)調(diào)用或返回生成代碼期間(通常,將變量置于與內(nèi)存相對(duì)的寄存器中,但是目標(biāo)平臺(tái)使用這種方式以區(qū)別寄存器的兩種不同類型),參數(shù)或返回值被視為處于特殊的目標(biāo)平臺(tái)無(wú)關(guān)方式。該屬性的使用是目標(biāo)平臺(tái)相關(guān)的。
byval
這表明,指針參數(shù)應(yīng)以傳值方式傳至函數(shù)。該屬性指出,調(diào)用者和被調(diào)用者間將導(dǎo)致被指向單元(pointee)的隱形復(fù)制,因此被調(diào)用者不能修改調(diào)用者的值(原文有筆誤:so the callee is unable to modify the value in the callee,應(yīng)為in the caller)。該屬性只對(duì)LLVM指針參數(shù)有效。這通常用于傳值方式傳遞結(jié)構(gòu)和數(shù)組,但對(duì)指向標(biāo)量的指針同樣有效。上述復(fù)制被認(rèn)為是屬于調(diào)用者而非被調(diào)用者(例如,只讀函數(shù)不應(yīng)寫(xiě)具有byval屬性的參數(shù))。這不是返回值的有效屬性。byval屬性也支持由align屬性指定的對(duì)齊。這對(duì)代碼生成器有與目標(biāo)平臺(tái)相關(guān)的影響,這通常表明生成的棧槽(stack slot)需要對(duì)齊。
sret
這表明,指針參數(shù)指定了源程序的函數(shù)返回值結(jié)構(gòu)的地址。該指針必須由調(diào)用者保證有效:加載和存儲(chǔ)該結(jié)構(gòu)假定被調(diào)用者不會(huì)進(jìn)入陷阱(trap)。這只可能應(yīng)用與第一個(gè)參數(shù)。這不是返回值的有效屬性。
noalias
這表明,該指針不能別名一切全局值或其它任何參數(shù)。調(diào)用者有責(zé)任保證符合上述情況。對(duì)于函數(shù)返回值,noalias還表明指針不能別名為其它任何對(duì)調(diào)用者可見(jiàn)的指針。更多的細(xì)節(jié)請(qǐng)參見(jiàn)別名分析中NoAlias回復(fù)的討論。
nocapture
這表明,被調(diào)用者不產(chǎn)生比被調(diào)用者本身生命周期長(zhǎng)的指針的任何復(fù)制。這不是返回值的有效屬性。
nest
這表明,指針參數(shù)可通過(guò)使用trampoline intrinsics引用。這不是返回值的有效屬性。
垃圾回收器名稱
每個(gè)函數(shù)可指定垃圾回收器名稱,該名稱是簡(jiǎn)單的字符串:
define void @f() gc "name" { ... }
編譯器聲明name的支持值。指定將導(dǎo)致編譯器改變其輸出的回收器,是為了支持有名的垃圾回收算法。
函數(shù)屬性
函數(shù)屬性為增加函數(shù)的附加信息而設(shè)置。函數(shù)屬性被視為函數(shù)而非函數(shù)類型的一部分,因此具有不同參數(shù)屬性的函數(shù)可具有同一函數(shù)類型。
函數(shù)屬性是遵循指定類型的簡(jiǎn)單關(guān)鍵字。如果需要多個(gè)函數(shù)屬性,則以空格分隔。例如:
define void @f() noinline { ... }
define void @f() alwaysinline { ... }
define void @f() alwaysinline optsize { ... }
define void @f() optsize
alwaysinline
該屬性表明,內(nèi)聯(lián)器試圖盡可能將函數(shù)內(nèi)聯(lián)至調(diào)用者,而忽略該調(diào)用者的任何活躍的內(nèi)聯(lián)大小閾值。
noinline
該屬性表明,內(nèi)聯(lián)器任何情況都不會(huì)將函數(shù)內(nèi)聯(lián)。該屬性可能不能與alwaysinline屬性一起使用。
optsize
該屬性建議,優(yōu)化pass和代碼生成器pass在保持函數(shù)少代碼量還是執(zhí)行特定優(yōu)化以減少代碼大小間做決定。
noreturn