我的第一個 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 支援所需的三行程式碼。後面的章節將展示如何產生 .o 檔案。
第 5 章:擴展語言:控制流程 - 在基本語言啟動並執行後,我們將展示如何使用控制流程操作('if' 語句和 'for' 迴圈)來擴展它。這讓我們有機會討論 SSA 建構和控制流程。
第 6 章:擴展語言:使用者定義的運算子 - 本章擴展了語言,允許使用者定義任意的單元和二元運算子 - 並具有可分配的優先順序!這使我們能夠將「語言」的很大一部分建構為函式庫常式。
第七章:擴展語言:可變變數 - 本章討論添加用戶自定義的局部變數以及賦值運算符。這顯示了在 LLVM 中構建 SSA 形式是多麼容易:LLVM 並*不需要*您的前端構建 SSA 形式才能使用它!
第八章:編譯成目標文件 - 本章說明如何將 LLVM IR 編譯成目標文件,就像靜態編譯器所做的那樣。
第九章:調試信息 - 一個真正的語言需要支持調試器,因此我們添加了調試信息,允許在 Kaleidoscope 函數中設置斷點,打印參數變數以及調用函數!
第十章:結論和其他花絮 - 本章通過討論擴展語言的方法來總結本系列,並包括指向“特殊主題”信息的指針,例如添加垃圾回收支持、異常、調試、對“意大利麵條堆棧”的支持等。
在本教程結束時,我們將編寫不到 1000 行(非註釋、非空白)的代碼。憑藉這少量的代碼,我們將為一種重要的語言構建一個漂亮的小型編譯器,包括手寫的詞法分析器、解析器、AST 以及代碼生成支持 - 包括靜態和 JIT!其廣度很好地證明了 LLVM 的優勢,並顯示了為什麼它是語言設計者和其他需要高性能代碼生成的人的熱門目標。