LLVM后端移植笔记1 c910 riscv示例
目录
4. AsmParser/RISCVAsmParser.cpp
5. MCTargetDesc/RISCVMCCodeEmitter.cpp
LLVM官方提供了两个关于后端的官方文档:
1、 The LLVM Target-Independent Code Generator
阅读2之前要求阅读1。将这两个文档参照起来读,基本上可以获取新建后端所需要的各类信息。这两个文档从三个层面解析了后端的架构,将后端从代码组织、执行环节和建立步骤都讲的很清楚。我们在这里就一起看看这三个层面:
一、后端的六大部分
- Target description classes: abstract target description interfaces (代码地址:include/llvm/Target/)
- Marchine code description classes: classes used to repesent the code being generated for a target (代码地址:include/llvm/CodeGen/)
- The "MC" Layer: use to represent and process code at the raw machine code level(代码地址:lib/MC include/llvm/MC)
- Target-independent code generation algorithms (代码地址:lib/CodeGen)
- Implementations of the abstract description interfaces for particular targets (代码地址: lib/Target)
- The target-independent JIT components (代码地址:lib/ExecutionEngine/JIT)
二、后端的七大环节
- Instruction Selection
- Scheduling and Formation
- SSA-based Machine Code Optimizations
- Register Allocation
- Prolog/Epilog Code Insertion
- Late Machine Code Optimizations
- Code Emission
三、建立新后端的七大步骤
1、建立一个TargetMachine的子类用于描述你的硬件特性。
2、描述目标机器的寄存器集。使用TableGen从目标机器的RegisterInfo.td中生成寄存器定义信息、同名信息、寄存器组信息。同时还需要编写TargetRegisterInfo子类来说明寄存器如何分派和 描述寄存器之间的关系。
3、描述目标机器的指令集。同样使用TableGen从目标机器的TargetInstrFormats.td和 TargetInstrInfo.td中生成指令信息。同时还需要编写TargetInstrInfo子类来说明目标机器所支持 的机器指令。
4、描述如何选择和转化LLVM IR,从一个DAG表示的指令到目标机器的本地指令。 基于 TargetInstrInfo.td提供的信息 ,使用TableGen生成模式匹配成功的指令。编写代码 XXXISelDAGToDAG.cpp来说明如何匹配模式和DAG-to-DAG指令选择等。同时还要编写 XXXISelLowering.cpp来替换或者移除目标机器不支持的类型操作。
5、编写汇编语言打印代码,来转换LLVM IR到GAS格式的汇编。
6、(可选)支持subtargets(***)。
7、(可选)增加JIT支持和建立一个机器码生成器,用于直接生成二进制码到内存。
四、后端介绍
1.后端目录
2.LLVM后端简介
利用llc工具生成汇编码:
$ llc test.bc -o test.s
$ llc test.bc -filetype=obj -o test.o //生成目标代
3.后端目录代码结构
后端实现分散在LLVM源树的不同目录中。 代码生成的主要库位于lib目录及其子文件夹CodeGen,MC,TableGen和 Target中:
•CodeGen目录包含所有通用代码生成算法的实现文件和头文件:指令选择, 调度程序,寄存器分配以及所有他们需要的分析。
•MC目录保留了汇编器(汇编解析器),松弛算法(反汇编器)和特定目 标文件惯用语(例如ELF,COFF,MachO等)的低级功能的实现。
•TableGen目录包含TableGen工具的完整实现,该工具用于根据.td文件中的 高级目标描述生成C代码。
•每个后端目标都在“Target”文件夹下的不同子文件夹中实现(例如,Target/Mips)
4.目标指令集的描述实现
在代码产生的早期阶段,LLVM IR代码会被转换成一个带节点的有选择的向无环图
(SelectionDAG)。这些节点含有目标指令的SDNote的实例。一个SDNode有一个操作
码,操作数,类型要求,操作属性。各种操作节点类型在include/lIvm/CodeGen/Selectio-
nDAGNodes.h中描述。
TableGen用如下的目标描述(输入文件来产生大部分的指令定义的代码:
1.Target. td-—定义Instruction,Operand,InstrInfo和其他基本类。
2.TargetSelectionDAG. td——SelectionDAG指令选择生成器使用。包含了SDTC*类(选择DAG类型约束条件),SelectionDAG节点的定义(如imm,cond,bb, add,fadd,sub)和模式支持(Pattern,Pat,PatFrag,PatLeaf,ComplexPattern);
3.XXXInstrFormats.td--一目标相关指令的定义模式;
4.xXXInstrInfo. td一-指令模板、条件代码、指令集的指令的目标相关定义。可以用不同的文件名表示体系结构的特征。例如,带有SSE(Streaming SIMD Extensions)指令的Pentium处理器,这个文件为SSE(Streaming SIMD Extensions)。如果是带MMX的Pentium处理器,则为X86InstrMMX. td。
另外还有一个目标相关文件XXX.td,XXX代表目标的名称。XXX.td文件包括了其
他.td 输入文件,相当于所有td文件的汇总在这个文件里,以便更好的管理td文件。此
外需要描述一个具体的目标相关类XXXInstrInfo,代表目标机器支持的机器指令。
xXXinstrinfo包含了XXXInstrDescriptor对象的一个数组。每个XXXInstrDescriptor对象
描述了一个指令。一个指令描述符定义了:
操作码助记符。
操作数的数量。
隐含寄存器定义和使用的列表。
目标无关的特性(如内存访问,是可以交换的)。
目标相关的标志。
指令类(Target.td中定义)是一个基础的类。其他复杂的指令类都基于此。指令类定义如下:
5.指令选择描述
5.riscv后端指令描述
5.1RISCVInstrForMatsC910.td
这个class定义了指令模板RVInstC910LS_1,其中的各个字段定义了这条指令的不同位置对应的二进制码.
5.2RISCVInstrInfoC910.td
在这个文件中定义了具体的指令描述
图中基于指令模板RVInstC910LS_1进一步定义了指令类Store_ss.
而这些指令就是Store_ss类的指令.
6.玄铁C910指令扩展示例
7.玄铁C910在编译器中注册示例
五. auipc指令设计实现
1. RISCVInstrInfo.td
// This file describes the RISC-V instructions in TableGen format.
// RISC-V specific DAG Nodes.
2. RISCVInstrFormats.td
// These instruction format definitions are structured to match the
// description in the RISC-V User-Level ISA specification as closely as
// possible. For instance, the specification describes instructions with the
// MSB (31st bit) on the left and the LSB (0th bit) on the right. This is
// reflected in the order of parameters to each instruction class.
//
// One area of divergence is in the description of immediates. The
// specification describes immediate encoding in terms of bit-slicing
// operations on the logical value represented. The immediate argument to
// these instruction formats instead represents the bit sequence that will be
// inserted into the instruction. e.g. although JAL's immediate is logically
// a 21-bit value (where the LSB is always zero), we describe it as an imm20
// to match how it is encoded.
3.RISCVExpandPseudoInsts.cpp
// This file contains a pass that expands pseudo instructions into target
// instructions. This pass should be run after register allocation but before
// the post-regalloc scheduling pass.
4. AsmParser/RISCVAsmParser.cpp
Parse RISCV assembly to MCInst instructions
5. MCTargetDesc/RISCVMCCodeEmitter.cpp
Convert RISCV code to machine code
六.xor指令设计实现
1. RISCVInstrInfo.td
RISCVInstrInfoC.td
七,RVV指令扩展