擴展LLVM:添加指令、內部函數、類型等


擴展LLVM:添加指令、內部函數、類型等

  1. Introduction and Warning
  2. Adding a new intrinsic function
  3. Adding a new instruction
  4. Adding a new SelectionDAG node
  5. Adding a new type
    1. Adding a new fundamental type
    2. Adding a new derived 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)

  1. 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

 

 


免責聲明!

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



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