Go編譯器簡介【譯】

趁着元旦休假+春節,嘗試把2018年期間讓我受益的一些文章、問答,翻譯一下。
歡迎指正、討論,但願對你也有所幫助。
原文連接:https://github.com/golang/go/...前端

構成Go編譯器的關鍵package都包含在cmd/compile目錄。咱們從邏輯上把編譯器編譯過程分紅四個階段,下文將簡要介紹這四個階段的package列表。
談到編譯器,你可能據說過相似「前端」、「後端」這樣的字眼。粗略地講,咱們也將編譯器的四個階段工做劃分紅了前兩個階段和後兩個階段,也就是前端和後端。還有一個詞——」中端「,一般包含在第二個階段中(譯者注:有的編譯器在前端和後端之間引入了一個代碼優化階段,稱爲middle-end,中端。感興趣的讀者能夠提早深刻了解下通常編譯器架構)。
須要注意的是,go/目錄的package和編譯器無關,好比go/types等。因爲最初的編譯器是用C語言編寫而成,go/中包含了一些用Go代碼編寫的工具,如gofmt和vet。
還有一點須要澄清,」gc「表明」Go compiler「,和咱們經常使用來表示垃圾回收的GC沒啥關係。git

1.詞法分析和語法分析

cmd/compile/internal/syntax目錄包含了詞法分析、語法分析和語法樹構造部分。編譯器第一階段工做中,對每一個源文件進行詞法、語法分析,並生成AST(抽象語法樹)。
每一個語法樹都精確表達了相應的源代碼文件。樹的節點對應着各個源文件的元素,例如表達式、聲明語句。語法樹還包含了代碼位置信息,爲錯誤報告和調試信息提供支持。github

2.類型檢查和AST轉換

cmd/compile/internal/gc目錄包含了編譯器AST建立、類型檢查、AST轉換部分。這個package中包含了一個從C繼承的AST定義。這個package的第一要事就是把syntax包的語法樹轉換成編譯器支持的AST來表示。這個步驟看起來略顯多餘,在未來的版本中可能會被重構。
接下來要作的是類型檢查。第一步作名字解析和類型推斷,肯定對象屬於哪一個標識符以及表達式的類型。類型檢查還包括一些額外操做,例如判斷」聲明但未使用「的變量、肯定函數是否會終止。
某些節點類型的細化也會在這部分完成。例如從算術加節點中拆分出字符串加、無用代碼消除、函數調用內聯化和逃逸分析。golang

3.通用SSA

這裏有官方給出的SSA背景介紹。
cmd/compile/internal/gc(SSA轉換)
cmd/compile/internal/ssa(SSA pass和規則)
這個階段,AST將轉換爲靜態單賦值(SSA)形式。這是一種具備特定屬性的低級中間表示法,更容易優化和生成機器碼。
轉換期間還要處理內置函數。現代編譯器通過多代進化已經很智能,會用大量優化代碼替代內置函數,得到更高性能。
在AST到SSA轉換期間,爲了方便複用,一些節點也降級爲更簡單的組件。例如,內置拷貝(譯者猜:copy?)替換內存移動(譯者猜:memmove?)並將range重寫爲for。因爲歷史緣由,其中一些在轉換爲SSA以前完成,將來計劃所有移至這裏。
而後,一系列與機器無關的pass和規則被應用。這些不涉及任何單一計算機體系結構。
這些環節包括消除無用代碼、刪除非必需的空值檢查以及刪除未使用的分支。通用重寫規則主要涉及表達式,例如用常量替換、乘法和浮點運算的優化。後端

4.生成機器代碼

cmd/compile/internal/ssa(SSA低級化和特定架構處理)
cmd/internal/obj(機器碼生成)
機器依賴相關的階段以比較「較低」的操做開始,這些操做將通用變量重寫成其特定於機器的變體。例如,amd64架構中,能夠合併許多加載存儲操做。
要注意」低級「的操做運行全部機器特定的重寫規則,它也應用了大量優化。
一旦SSA被「低級」處理而且更具體地針對目標體系架構,就要運行最終代碼優化的處理步驟了。其中包含了另外一個無用代碼消除的步驟。該步驟會將變量移動到更靠近它們被使用的位置、刪除從未被讀取的局部變量以及寄存器分配。
此步驟完成的其餘重要工做包括堆棧佈局和指針分析。堆棧佈局將堆棧偏移分配給局部變量,指針分析計算每一個GC安全點上的堆棧指針是否仍然是活動的。安全

在SSA生成階段結束時,Go函數已轉換爲sequence。這些sequence最終被轉換成機器碼。架構

相關文章
相關標籤/搜索