天天看點

SPIR-V 研究:編譯器基本原理(一)SPIR-V 研究:編譯器基本原理(一)

SPIR-V 研究:編譯器基本原理(一)

前面轉過兩篇關于SPIR-V 中間語言的介紹;接下來筆者準備深入學習一下SPIR-V的标準。根據标準,SPIR-V是以一種二進制格式存在的,并且函數還是以控制流圖CFG的形式存在;資料結構也保留了進階語言裡的層級關系。(https://en.wikipedia.org/wiki/Standard_Portable_Intermediate_Representation)

這樣做的目的是為了更好的在目标平台上進行優化;同時Khronos也放出了官方标準的開源編譯器Glslang。 是以,為了更好的了解SPIR-V,我們有必要先溫習一下編譯器的基本原理,特别是前端的詞法分析、文法分析、語義分析和中間語言生成。

編譯器基本結構

下圖是一個一般編譯器的編譯進階語言的過程。

SPIR-V 研究:編譯器基本原理(一)SPIR-V 研究:編譯器基本原理(一)

基本上就是預處理(比如C/C++裡宏彙編),編譯并彙編(每個源碼檔案都生成對應的.o檔案,這時的代碼是relocatable的),連結生成可執行檔案(linker,把許多.o檔案以及用到的庫函數.lib檔案合并并作全局優化),最後OS的加載器會加載可執行檔案并運作之(Windows上是PE格式,Linux上市ELF格式)。具體細節可以參考Linkers and Loaders 這本書。

下面我們重點看編譯器的結構。

SPIR-V 研究:編譯器基本原理(一)SPIR-V 研究:編譯器基本原理(一)

這是一般編譯器的結構,主要分前端和後端,以中間語言生成為界限。前端主要是分析文法語義并生成代碼的中間表示,這主要包括lexer 和 parser,以及語義分析;後端主要是生成目标機器代碼,包括分析并優化,寄存器配置設定等。

下圖是編譯器的主要編譯過程(phase)。

SPIR-V 研究:編譯器基本原理(一)SPIR-V 研究:編譯器基本原理(一)

這裡我們研究的目标SPIR-V就是一種标準化的中間語言表示。是以我們更關心的是前端的研究,這也是編譯器裡比較成熟,相對簡單的部分。以前的OpenGL裡,GLSL寫成的Shader是進階語言(相當于C++),OpenGL的驅動會把它編譯成顯示卡GPU對應的機器碼。是以各家會有不同的中間表示;Vulkan會統一标準用SPIR-V了。

SPIR-V 研究:編譯器基本原理(一)SPIR-V 研究:編譯器基本原理(一)

計算機語言

計算機科學裡的語言可以看作是一個字母表(alphabet )上的某些有限長字元串的集合;這一般可以包含無限多個字元串,也就是無限集合(Infinite Sets)。這裡有限長字元串就是“sentences”;sentences是word(或token)組成,它有一定的結構;token則是letter由一定規則組成;letter個數是有限的,它們全部取自字母表(alphabet )。

這是個有層次的定義。

Layer 分析對象 組成元素
詞法(Lexical structure ) token letter
文法(Syntactic structure) sentences token
語義(Semantics) 文法樹

語言是有一定的文法規則的(grammar)。而grammar是一組有限的規則的集合;計算機語言裡的grammar是不同于一般自然語言的文法,它可以構造出所有可能的sentences。是以這是一個利用有限規則來産生無限的合法語句的問題。

而grammar又可以用正規表達式來定義;比如GLSL的文法glslang.y。