每個函數能夠制定一個垃圾回收期的名稱,這個名稱是一個簡單的字符串:html
define void @f() gc "name" { ... }
編譯器聲明瞭這個名字的可能值。指定一個收集器將會致使編譯器會爲了支持這個垃圾回收算法修改它的輸出。前端
前置數據是一種與函數相關的數據,在函數主體以前代碼生成器會立刻發散這種數據。這個特性的目的是爲了讓容許在前端分配語言指定的在指定函數中運行期元數據,而且能夠經過函數指針來得到這個數據的同時這個函數指針仍然是可調用的。對一個給定的函數來訪問這個數據,程序能夠經過bitcast轉換這個函數指針到一個常量類型的指針。這是意味着這個IR符號指向這個前置數據的開始。算法
爲了維持普通函數調用的語義,這個前置數據必須有一個實際格式。具體來講,這必須開始於一段bytes序列,且能夠從中解碼到一段用於該模塊目標的機器指令序列,這個點的傳送控制緊隨這個前綴數據,而不執行任何其餘的可見動做。這就容許內聯器和其餘pass來推論這是一個函數定義語義而不是須要一個前置數據。顯而易見地,這使前置數據的格式高度依賴於目標平臺。後端
前置數據的定義,相似於一個前綴數據類型的全局變量的初始化式。在前置數據和函數主體之間沒有自動填充的數據。若是有填充要求,那麼它必須是前置數據的一部分。數組
這是一個很小的有效前置數據,其對於X86體系結構的值爲144,類型爲i8,則會被編碼爲 nop 指令。安全
define void @f() prefix i8 144 { ... }
通常來講,前置數據能夠跳過元數據經過編碼一個相關的branch指令,就像下面這個例子中的對於X86_64體系有效的前置數據,它的前兩個byte將被編碼jmp.+10dom
%0 = type <{ i8, i8, i8* }>
define void @f() prefix %0 <{ i8 235, i8 8, i8* @md}> { ... }
函數可能只擁有前置數據但沒有主體。這與 available_externally 連接標識有着相同的語義,即數據可能會被優化器使用的不會被髮散到對象文件中。函數
屬性組是在IR中的對象引用的屬性的集合。他們對於保持 .ll 可讀有着重要意義,由於許都函數會使用相同的屬性集。在退化的狀況下一個 .ll 文件對應着單一的 .c 文件,這個單一的屬性組講捕獲那些用於構建這個文件的重要命令行標識。佈局
一個屬性組是一個模塊層次的對象。要使用一個屬性組,一個對象能夠引用這個屬性組的ID(例如 #37)。一個對象可能引用超過一個屬性組。在這種狀況下來自於不一樣屬性組的屬性會被合併。性能
這裏有一個規定一個函數應該內聯的屬性組的例子,並擁有一個堆棧對齊屬性值爲4,且不使用SSE指令
; Target-independent attributes:
attributes #0 = { alwaysinline alignstack=4 }
; Target-dependent attributes:
attributes #1 = { "no-sse" }
; Function @f has attributes: alwaysinline, alignstack=4, and "no-sse".
define void @f() #0 #1 { ... }
函數屬性用於函數交流額外信息的。函數屬性被認爲是函數的一部分,而不是函數類型的一部分,因此擁有不一樣函數屬性的函數能夠對應着同一個函數類型。
函數屬性是緊跟在指定的函數類型後的簡單的關鍵字。若是之後須要指定多個函數屬性,那麼使用空格符分隔它們。例如:
define void @f() noinline { ... }
define void @f() alwaysinline { ... }
define void @f() alwaysinline optsize { ... }
define void @f() optsize { ... }
該屬性代表,函數的調用不能被複制。一個 noduplicate 函數的調用可能被移動到父函數,但不能被複制到父函數。
一個包含 noduplicate 函數仍然可能被內聯,條件是該調用沒有被重複內聯。這意味着,該函數具備 internal 連接標識,並只有一個調用點,因此內聯後,原始調用被刪除。
此此屬性代表,該函數不能被除了過程間優化 pass 外的任何優化或代碼生成器 pass 優化。這個屬性不能與一塊兒 alwaysinline 屬性使用;這個屬性也與 minsize 屬性和 optsize 屬性不兼容。( minsize 與 optsize 要求優化)
此屬性要求在函數中同時指定該屬性和 noinline 屬性,因此該函數從不內聯到任何調用者。只有具有alwaysinline 屬性的函數才能內聯到這個函數。
對於一個函數,這個屬性代表該函數嚴格基於它的參數計算其結果(或決定展開異常),而不經過解引用任何指針參數或以其餘方式訪問任何調用者可見的可變狀態(如內存,控制寄存器等)。它不經過任何指針參數(包括 byval 參數)寫入和從不改變調用者可見的任何狀態。這意味着它沒法經過調用C + +的異常throw的方法展開異常。
對於一個參數,這個屬性代表,該函數不能解引用指針參數,儘管若是經過其餘指針它能夠讀取或寫入指針參數指向內存(由於調用者可見的是指針的值而不是指針指向的值)。
對於一個函數,這個屬性代表該函數不經過任何指針參數(包括 byval 參數)或寫其餘方式修改任何調用者函數可見的狀態(如內存,控制寄存器等)。它可能會解引用指針參數和讀取在調用者中設置的狀態。在使用相同的函數集和全局狀態時,一個只讀函數老是返回相同的值(或展開相同的異常)。它沒法經過調用C + +的異常throw的方法展開異常。
上一個參數,這個屬性表示該函數不經過這個指針參數寫的,即便它可能寫入內存的指針指向。
該屬性代表,該函數應該發散一個堆棧溢出保護功能。它有一個「canary」形式 —( a random value placed on the stack before the local variables that’s checked upon return from the function to see if it has been overwritten.)。一個啓發式用來肯定一個函數須要的堆棧保護與否。在如下狀況,這個被使用了啓發式將啓用函數保護器:
字符數組比 ssp-buffer-size 大(默認值爲8)。
字符數組的集合比 ssp-buffer-size 大。
調用alloca()的變量長度或常量長度(alloca的參數)大於 ssp-buffer-size 。
被識別爲須要保護的變量將被安排在堆棧,使得對於堆棧保護器它們是連續的。
若是一個函數,它有一個SSP屬性被內聯到一個不具備SSP屬性的函數,而後將獲得的函數將具備一個SSP屬性。
該屬性代表,該函數應該發散一個堆棧溢出保護功能。這將覆蓋 ssp 函數屬性。
被識別爲須要保護的變量將被安排在堆棧,使得對於堆棧保護器它們是連續的。具體佈局規則是:
一、大數組和含大數組的結構體(>= sp-buffer-size)是最接近堆棧保護器的。
二、小數組和含小數組的結構體(< sp-buffer-size)是第二接近堆棧保護器的。
三、採起了它們的地址的變量是第三接近堆棧保護器的。
若是一個函數,它有一個 sspreq 屬性被內聯到一個不具備 sspreq 屬性或具備 ssp 或 sspstrong 屬性的函數,那麼獲得的結果函數將具備 sspreq 屬性。
該屬性代表,該函數應該發散一個堆棧溢出保護功能。在肯定函數是否須要的堆棧保護器時,此屬性會使用一個強有力的試探法。強大的啓發式將爲函數啓用保護器:
任何長度和類型的數組
任何長度和類型的數組的集合。
調用了alloca( ) 。
採起了它們的地址的局部變量。
被識別爲須要保護的變量將被安排在堆棧,使得對於堆棧保護器它們是連續的。具體佈局規則是:
一、大數組和含大數組的結構體(>= sp-buffer-size)是最接近堆棧保護器的。
二、小數組和含小數組的結構體(< sp-buffer-size)是第二接近堆棧保護器的。
三、採起了它們的地址的變量是第三接近堆棧保護器的。
這將覆蓋 ssp 功能屬性。
若是一個函數,它有一個 sspstrong 屬性被內聯到一個不具備 sspstrong 屬性的函數,那麼最後獲得的函數將具備 sspstrong 屬性。