LLVM筆記(1) - TableGen


1. 什么是tablegen
  tablegen是llvm用於開發和維護編譯器中公共特性的條目(e.g. 指令描述, 寄存器描述)的代碼, 使之靈活的描述與構造的自動化工具. 其本質是一個parser, 將輸入的td文件轉化為特定的數據結構后再輸出為易於閱讀的cpp代碼. 更多介紹可見http://llvm.org/docs/TableGen/index.html或參見docs/TableGen/下文件說明.

2. tablegen的使用方式
  首次成功編譯后, 在[llvm install path]/bin/下會生成可執行文件llvm-tblgen. 通常使用方法(在llvm的cmake工程中)它讀入一個td文件, 並將結果輸出至一個inc文件中. 以高通的Hexagon架構為例(具體使用命令可以llvm-tblgen --help查詢)生成指令信息代碼:

1 [12:32:11] hansy@hansy:~/llvm/llvm (master)$ ../llvm_build/bin/llvm-tblgen -gen-instr-info -I ./lib/Target/Hexagon/ -I ./include/ -I ./lib/Target/ ./lib/Target/Hexagon/Hexagon.td -o ~/test.inc

  生成的inc文件實質為cpp代碼, llvm工程中會包含這些文件. 當前tablegen生成的代碼主要分為前端clang(target independent code, 在[llvm build path]/tools/clang/include/clang/下)以及后端llvm(target dependent code, 在[llvm build path]/lib/Target/[arch]下).
  tablegen代碼包含兩塊: 對td文件的處理, 在lib/TableGen/目錄下, 包含lexer與parser, 負責解析tablegen的語法並轉換為內部數據結構; 輸出cpp代碼, 在utils/TableGen/目錄下, 用於生成我們需要的cpp代碼, 這塊與llvm代碼邏輯強相關, 基本上一個cpp文件對應一類信息.

3. td文件的語法
  tablegen的輸入來源於td文件, 如要了解tablegen就先要了解td文件. 與生成的inc文件類似, td文件也包含兩塊內容(在[llvm source path]/對應的目錄下), 后端還包含部分llvm target independent code(主要為IR相關), 暫不贅述.
  仍以Hexagon架構為例, lib/Target/Hexagon/Hexagon.td是Hexagon架構td的入口(每個架構對應目錄下都有一個以架構命令的td文件). 在該文件中定義了一些基礎數據結構, 並包含了構建該架構后端所需的所有信息的文件.
  先來看看該文件定義的數據結構. 在td中使用兩個關鍵字定義數據結構(llvm中稱為records, 其實質對應的是tablegen中的一個類/類實例), class與def. 其中classes類似於模板, 用於描述一類抽象的records(e.g. Register, RegisterClass, Instruction). 而definitions用於表達一個具體的records(可以理解為一個特定的類). 每個records包含若干數據成員, 這些成員的類型有bit(布爾量), int(整型), string(字符串), code(代碼段, 包含一行或多行的字符串), bits<n>(位段)等類型. 數據成員使用let關鍵字進行賦值, 對於tablegen中解析的成員必須都初始化(為定義的值可以使用?初始化為'未初始化值'), 否則會導致編譯失敗. 若一個definition record包含一個未初始化成員, 其值將從該definition的superclass中獲取. 若tablegen中未解析該成員則不賦值也不會報錯. 以Asmparser為例(defined in include/llvm/Target/Target.td):

 1 class AsmParser {
 2   string AsmParserClassName  = "AsmParser";
 3   string AsmParserInstCleanup  = "";
 4   bit ShouldEmitMatchRegisterName = 1;
 5   bit ShouldEmitMatchRegisterAltName = 0;
 6   bit AllowDuplicateRegisterNames = 0;
 7   bit HasMnemonicFirst = 1;
 8   bit ReportMultipleNearMisses = 0;
 9 }
10 Hexagon架構的Asmarser如下(defined in lib/Target/Hexagon/Hexagon.td):
11 def HexagonAsmParser : AsmParser {
12   let ShouldEmitMatchRegisterAltName = 1;
13   bit HasMnemonicFirst = 0;
14 }

Hexagon架構的Asmarser如下(defined in lib/Target/Hexagon/Hexagon.td):

1 def HexagonAsmParser : AsmParser {
2   let ShouldEmitMatchRegisterAltName = 1;
3   bit HasMnemonicFirst = 0;
4 }

Hexagon未定義parser的名字, 因此使用默認模板的字符串'AsmParser'; 默認的parser不匹配寄存器別名, 而Hexagon下ShouldEmitMatchegisterltName為true, 覆寫了默認值.

4. tablegen選項
  一般情況下並不會修改tablegen的代碼, 而是通過修改td文件實現所需的目標. 對任意一個架構而言, 不是所有tablegen選項都有效(例如不支持vliw的架構就沒有DFAPacketizer), 仍以Hexagon為例常見選項如下:
-gen-emitter
  output: [arch]##GenMCCodeEmitter.inc
  usage:  used to generate binary code for given instruction. included in [arch]MCCodeEmitter.cpp
-gen-register-info
  output: [arch]##GenRegisterInfo.inc
  usage:  output register enum and class, mask, etc. included in [arch]##BaseRegisterInfo.* and [arch]##MCTargetDesc.*
-gen-instr-info
  output: [arch]##GenInstrInfo.inc
  usage:  output instruction enum and class, mask, etc. included in [arch]##BaseInstrInfo.* and [arch]##MCTargetDesc.*
-gen-asm-writer
  output: [arch]##GenAsmWriter.inc
  usage:  generate assembly printer. included in [arch]##InstPrinter.cpp
-gen-asm-matcher
  output: [arch]##GenAsmMatcher.inc
  usage:  generate assembly matcher used in assemble parser. included in [arch]##AsmParser.cpp
-gen-disassembler
  output: [arch]##GenDisassemblerTables.inc
  usage:  generate disassembly emitter. included in [arch]##Disassembler.cpp
-gen-callingconv
  output: [arch]##GenCallingConv.inc
  usage:  implement static function used for calling conversion.
-gen-dag-isel
  output: [arch]##GenDAGISel.inc
  usage:  implement a DAG instruction selector. included in [arch]##ISelDAGToDAG.cpp
-gen-dfa-packetizer
  output: [arch]##GenDFAPacketizer.inc
  usage:  generate function to check whether an instruction can be added to a VLIW. included in [arch]##InstrInfo.cpp
-gen-subtarget
  output: [arch]##GenSubtargetInfo.inc
  usage:  generate subtarget enum.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM