扩展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

 

 

上一篇:vscode C/C++ 语法检查


下一篇:LLVM笔记(18) - IR基础详解(二) Instruction