我的第一個語言前端與 LLVM 教學

需求: 本教學假設您具備 C++ 知識,但不需要任何編譯器經驗。

歡迎來到「我的第一個語言前端與 LLVM」教學。在這裡,我們將逐步實作一個簡單的語言,展示它有多有趣和容易。本教學將讓您快速上手並展示一個使用 LLVM 生成程式碼的具體範例。

本教學介紹了簡單的「Kaleidoscope」語言,並在幾個章節中迭代建構它,展示它是如何隨著時間推移而建立的。這讓我們可以涵蓋一系列語言設計和 LLVM 特有的概念,沿途展示和解釋程式碼,並減少前期令人難以承受的細節量。我們強烈建議您使用此程式碼 - 複製一份並修改和實驗。

警告:為了專注於教授編譯器技術和 LLVM 本身,本教學並未展示軟體工程原則中的最佳實務。例如,程式碼廣泛地使用全域變數,沒有使用訪問者模式等等…而是保持簡單並專注於手邊的主題。

本教學分為涵蓋個別主題的章節,讓您可以隨意跳過。

  • 第 1 章:Kaleidoscope 語言和詞法分析器 - 這章展示了我們的目標以及我們想要建構的基本功能。詞法分析器也是為語言建構剖析器的第一部分,我們使用一個簡單易懂的 C++ 詞法分析器。

  • 第 2 章:實作剖析器和 AST - 有了詞法分析器,我們可以討論剖析技術和基本的 AST 建構。本教學描述了遞迴下降剖析和運算符優先級剖析。

  • 第 3 章:程式碼生成到 LLVM IR - 準備好 AST 後,我們將展示生成 LLVM IR 有多麼容易,並展示將 LLVM 併入您專案的簡單方法。

  • 第 4 章:新增 JIT 和最佳化器支援 - LLVM 最棒的功能之一是它對 JIT 編譯的支援,因此我們將深入研究它,並向您展示新增 JIT 支援所需的 3 行程式碼。後面的章節將展示如何生成 .o 檔案。

  • 第 5 章:擴展語言:控制流程 - 在基本語言啟動並執行後,我們將展示如何使用控制流程操作(‘if’ 語句和 ‘for’ 迴圈)來擴展它。這讓我們有機會討論 SSA 建構和控制流程。

  • 第 6 章:擴展語言:使用者定義的運算符 - 本章擴展了語言,讓使用者可以定義任意的一元和二元運算符 - 具有可分配的優先順序!這讓我們可以將「語言」的重要部分建構為函式庫常式。

  • 第 7 章:擴展語言:可變變數 - 本章討論新增使用者定義的區域變數以及賦值運算符。這展示了在 LLVM 中建構 SSA 形式有多麼容易:LLVM 要求您的前端建構 SSA 形式才能使用它!

  • 第 8 章:編譯為目標檔案 - 本章解釋了如何取得 LLVM IR 並將其編譯為目標檔案,就像靜態編譯器一樣。

  • 第 9 章:除錯資訊 - 一個真正的語言需要支援除錯器,因此我們新增了除錯資訊,允許在 Kaleidoscope 函式中設定中斷點、印出引數變數和呼叫函式!

  • 第 10 章:結論和其他小技巧 - 本章總結了本系列,討論了擴展語言的方法,並包含指向「特殊主題」資訊的指標,例如新增垃圾回收支援、例外、除錯、支援「義大利麵堆疊」等等。

在本教學結束時,我們將編寫不到 1000 行(非註解、非空白)程式碼。透過這麼少量的程式碼,我們將為一種重要的語言建立一個不錯的小型編譯器,包括手寫的詞法分析器、剖析器、AST,以及程式碼生成支援 - 包括靜態和 JIT!這廣泛性是對 LLVM 強大功能的絕佳證明,並展示了為什麼它是語言設計者和其他需要高效能程式碼生成的人如此受歡迎的目標。