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