擴展LLVM:添加指令、內部函數、類型等
- Introduction and Warning
- Adding a new intrinsic function
- Adding a new instruction
- Adding a new SelectionDAG node
- Adding a new type
Introduction and Warning
在使用LLVM的過程中,可能希望為研究項目或實驗定制它。此時,可能意識到需要向LLVM添加一些內容,不管是新的基本類型、新的內在函數還是全新的指令。
當意識到這一點時,停下來想想。真的需要擴展LLVM嗎?它是LLVM在其當前化身中不支持的一個新的基本功能,還是可以從已經存在的LLVM元素合成它?如果不確定,詢問LLVM dev列表。原因是,擴展LLVM將涉及到更新所有不同的傳遞,使用擴展,並且有許多LLVM分析和轉換,所以這可能是相當多的工作。
添加內部函數比添加指令容易得多,並且對優化過程是透明的。如果添加的功能可以表示為函數調用,則內部函數是LLVM擴展的首選方法。
在投入大量的精力在一個非常重要的擴展上之前,先問一下想要做的事情是否可以用已經存在的基礎架構來完成,或者也許其他人已經在做了。這樣做會節省很多時間和精力。
Adding a new intrinsic function
向LLVM添加一個新的內部函數比添加一個新的指令要容易得多。幾乎所有對LLVM的擴展都應該從一個內在函數開始,然后在有必要的情況下轉換為指令。
llvm/docs/LangRef.html:記錄內部。確定它是否特定於代碼生成器,以及限制是什么。
llvm/include/llvm/Intrinsics*.td:為內在函數添加一個條目。描述它的內存訪問特性以進行優化(控制它是否是DCE'd、CSE'd等)。請注意,tblgen將llvm_int_ty type用於參數的任何內在函數,都將被tblgen視為重載,並且在內部函數的名稱上需要相應的后綴。 llvm/lib/Analysis/ConstantFolding.cpp:如果可以常量折疊內部函數,請在canConstantFoldCallTo和ConstantFoldCall函數中添加對它的支持。
llvm/test/Regression/*:將測試用例添加到測試套件中
一旦內在函數被添加到系統中,就必須為其添加代碼生成器支持。
通常必須執行以下步驟:
在lib/Target/CBackend中添加對C后端的支持/
根據內在特性,有幾種方法可以實現這一點。對於大多數intrinsic,在llib/CodeGen/IntrinsicLowering.cpp的LowerIntrinsicCall中添加代碼來降低內部函數是有意義的。
第二,在所有情況下將內部代碼降低到擴展的C代碼序列是有意義的,那么只需在Writer.cpp中的visitCallist中發出。如果內在函數有某種方式可以用GCC(或任何其它編譯器)擴展來表示,那么可以根據編譯CBE輸出的編譯器來有條件地支持它(參見llvm.prefetch示例)。
第三,如果內在函數真的沒有降低的方法,只需讓代碼生成器發出打印錯誤消息的代碼,並在執行時調用abort。
將選擇的目標文件lib/Target/*/*.td添加到目標文件中。
通常是向.td文件中添加一個與內在模式匹配的模式的問題,盡管很明顯,可能還需要添加要生成的指令。在PowerPC和X86后端中有許多示例可以遵循。
Adding a new SelectionDAG node
與內部函數一樣,向LLVM添加一個新的SelectionDAG節點比添加一個新的指令要容易得多。通常會添加新節點來幫助表示多個目標通用的指令。這些節點通常映射到LLVM指令(add,sub)或內在(byteswap,population count)。在其他情況下,添加了新的節點以允許許多目標執行一個共同的任務(在浮點和整數表示之間轉換)或在單個節點中捕獲更復雜的行為(旋轉)。
include/llvm/CodeGen/SelectionDAGNodes.h:為新的SelectionDAG節點添加枚舉值。
lib/CodeGen/SelectionDAG/SelectionDAG.cpp:添加代碼以將節點打印到getOperationName。如果在給定常量參數時可以在編譯時對新節點求值(例如用另一個常量添加一個常量),請找到接受適當數量參數的getNode方法,並將節點的大小寫添加到switch語句中,該語句對采用與新節點相同數量參數的節點執行常量折疊。
lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:根據需要添加代碼以使節點合法化、升級和擴展。需要在LegalizeOp中為節點添加case語句,該語句將對節點的算子調用LegalizeOp,並在任何算子因合法化而更改時返回新節點。可能並非SelectionDAG框架支持的所有目標都會在本機支持新節點。在這種情況下,還必須在LegalizeOp中的節點case語句中添加代碼,以便將節點擴展為更簡單、合法的操作。將余數展開為除法、乘法和減法的ISD::UREM就是一個很好的例子。
Adding a new instruction
警告:添加指令會更改位碼格式,需要一些努力才能保持與以前版本的兼容性。只有在絕對必要時才添加指令。
l llvm/include/llvm/Instruction.def: add a number for your instruction and an enum name為指令添加數字和枚舉名稱
l llvm/include/llvm/Instructions.h: add a definition for the class that will represent your instruction為將表示指令的類添加定義
l llvm/include/llvm/Support/InstVisitor.h: add a prototype for a visitor to your new instruction type為新的指令類型添加訪問者原型
l llvm/lib/AsmParser/Lexer.l: add a new token to parse your instruction from assembly text file添加一個新的標記來解析程序集文本文件中的指令
l llvm/lib/AsmParser/llvmAsmParser.y: add the grammar on how your instruction can be read and what it will construct as a result添加語法,說明如何讀取指令以及它將作為結果構造什么
l llvm/lib/Bitcode/Reader/Reader.cpp: add a case for your instruction and how it will be parsed from bitcode為指令添加大小寫,以及如何從位代碼解析它
l llvm/lib/VMCore/Instruction.cpp: add a case for how your instruction will be printed out to assembly添加一個案例,說明如何將指令打印到程序集
l llvm/lib/VMCore/Instructions.cpp: implement the class you defined in llvm/include/llvm/Instructions.h實現在llvm/include/llvm/Instructions.h中定義的類
l 測試你的指令
l Test your instruction
l llvm/lib/Target/*: Add support for your instruction to code generators, or add a lowering pass. 向代碼生成器添加對指令的支持,或添加降低傳遞。
l llvm/test/Regression/*: add your test cases to the test suite. 將測試用例添加到測試套件中。
Adding a new type
警告:添加新類型會更改位碼格式,並將破壞與當前現有LLVM安裝的兼容性。只有在絕對必要時才添加新類型。
Adding a fundamental type
l llvm/include/llvm/Type.h: add enum for the new type; add static Type* for this type
l llvm/lib/VMCore/Type.cpp: add mapping from TypeID => Type*; initialize the static Type*
l llvm/lib/AsmReader/Lexer.l: add ability to parse in the type from text assembly
l llvm/lib/AsmReader/llvmAsmParser.y: add a token for that type
Adding a derived type
l llvm/include/llvm/Type.h: add enum for the new type; add a forward declaration of the type also
l llvm/include/llvm/DerivedTypes.h: add new class to represent new class in the hierarchy; add forward declaration to the TypeMap value type
l llvm/lib/VMCore/Type.cpp: add support for derived type to:
l std::string getTypeDescription(const Type &Ty,
l std::vector<const Type*> &TypeStack)
l bool TypesEqual(const Type *Ty, const Type *Ty2,
l std::map<const Type*, const Type*> & EqTypes)
- add necessary member functions for type, and factory methods
l llvm/lib/AsmReader/Lexer.l: add ability to parse in the type from text assembly
l llvm/lib/BitCode/Writer/Writer.cpp: modify void BitcodeWriter::outputType(const Type *T) to serialize your type
l llvm/lib/BitCode/Reader/Reader.cpp: modify const Type *BitcodeReader::ParseType() to read your data type
l llvm/lib/VMCore/AsmWriter.cpp: modify
void calcTypeName(const Type *Ty,
std::vector<const Type*> &TypeStack,
std::map<const Type*,std::string> &TypeNames,
std::string & Result)
to output the new derived type