LLVM 之后端篇(3):如何添加 MyRISCV 目标后端的第一条指令

Author: stormQ

Created: Sunday, 09. January 2022 11:47AM

Last Modified: Saturday, 13. August 2022 03:44PM



摘要

本文基于release/15.x版本的 LLVM 源码,介绍了在注册目标后端MyRISCV后如何为其添加第一条指令。从而,能够将本文的 LLVM IR 测试程序翻译成汇编代码。


测试程序

测试程序 test.ll:

define i32 @test() {
    ret i32 1
}

生成目标后端riscv32的汇编代码(作为对照结果):

$ llc -march=riscv32 -filetype=asm test.ll -o test.s

test.s 的内容如下:

    .text
    .attribute  4, 16
    .attribute  5, "rv32i2p0"
    .file   "test.ll"
    .globl  test                            # -- Begin function test
    .p2align    2
    .type   test,@function
test:                                   # @test
    .cfi_startproc
# %bb.0:
    addi    a0, zero, 1
    ret
.Lfunc_end0:
    .size   test, .Lfunc_end0-test
    .cfi_endproc
                                        # -- End function
    .section    ".note.GNU-stack","",@progbits

从上面的结果可以看出,目标后端riscv32将 LLVM IR 语句ret i32 1翻译成了addi a0, zero, 1ret两条汇编代码。

接下来,在目标后端MyRISCV中实现相同的功能。


描述目标属性

LLVM 中,<Target>.td文件用于描述目标属性,比如:支持的指令集、处理器等。同时,也作为主文件包含其它.td文件。

对于MyRISCV目标后端,MyRISCV.td位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 include "llvm/Target/Target.td"
  2 
  3 include "MyRISCVRegisterInfo.td"
  4 include "MyRISCVInstrInfo.td"
  5 include "MyRISCVCallingConv.td"
  6 
  7 def : ProcessorModel<"generic-rv32", NoSchedModel[]>;
  8 
  9 def MyRISCVInstrInfo : InstrInfo;
 10 
 11 def MyRISCV : Target {
 12   let InstructionSet = MyRISCVInstrInfo;
 13 }

定义寄存器和寄存器类

LLVM 中,<Target>RegisterInfo.td文件用于描述寄存器和寄存器类。寄存器类是一组具有相同大小的寄存器集合,同时也定义了寄存器分配的默认先后顺序。

对于MyRISCV目标后端,MyRISCVRegisterInfo.td位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 class MyRISCVReg<bits<5> enc, string name, list<string> alt = []>
  2     : Register<name, alt> {
  3   let HWEncoding{4-0} = enc;
  4   let Namespace = "MyRISCV";
  5 }
  6 
  7 def ABIRegAltName : RegAltNameIndex;
  8 
  9 let RegAltNameIndices = [ABIRegAltName] in {
 10   def X0  : MyRISCVReg<0,  "x0",  ["zero"]>;
 11   def X1  : MyRISCVReg<1,  "x1",  ["ra"]>;
 12   def X2  : MyRISCVReg<2,  "x2",  ["sp"]>;
 13   def X3  : MyRISCVReg<3,  "x3",  ["gp"]>;
 14   def X4  : MyRISCVReg<4,  "x4",  ["tp"]>;
 15   def X5  : MyRISCVReg<5,  "x5",  ["t0"]>;
 16   def X6  : MyRISCVReg<6,  "x6",  ["t1"]>;
 17   def X7  : MyRISCVReg<7,  "x7",  ["t2"]>;
 18   def X8  : MyRISCVReg<8,  "x8",  ["s0""fp"]>;
 19   def X9  : MyRISCVReg<9,  "x9",  ["s1"]>;
 20   def X10 : MyRISCVReg<10"x10", ["a0"]>;
 21   def X11 : MyRISCVReg<11"x11", ["a1"]>;
 22   def X12 : MyRISCVReg<12"x12", ["a2"]>;
 23   def X13 : MyRISCVReg<13"x13", ["a3"]>;
 24   def X14 : MyRISCVReg<14"x14", ["a4"]>;
 25   def X15 : MyRISCVReg<15"x15", ["a5"]>;
 26   def X16 : MyRISCVReg<16"x16", ["a6"]>;
 27   def X17 : MyRISCVReg<17"x17", ["a7"]>;
 28   def X18 : MyRISCVReg<18"x18", ["s2"]>;
 29   def X19 : MyRISCVReg<19"x19", ["s3"]>;
 30   def X20 : MyRISCVReg<20"x20", ["s4"]>;
 31   def X21 : MyRISCVReg<21"x21", ["s5"]>;
 32   def X22 : MyRISCVReg<22"x22", ["s6"]>;
 33   def X23 : MyRISCVReg<23"x23", ["s7"]>;
 34   def X24 : MyRISCVReg<24"x24", ["s8"]>;
 35   def X25 : MyRISCVReg<25"x25", ["s9"]>;
 36   def X26 : MyRISCVReg<26"x26", ["s10"]>;
 37   def X27 : MyRISCVReg<27"x27", ["s11"]>;
 38   def X28 : MyRISCVReg<28"x28", ["t3"]>;
 39   def X29 : MyRISCVReg<29"x29", ["t4"]>;
 40   def X30 : MyRISCVReg<30"x30", ["t5"]>;
 41   def X31 : MyRISCVReg<31"x31", ["t6"]>;
 42 }
 43 
 44 def GPR : RegisterClass<"MyRISCV", [i32], 32, (add
 45   (sequence "X%u"1017),
 46   (sequence "X%u"57),
 47   (sequence "X%u"2831),
 48   (sequence "X%u"89),
 49   (sequence "X%u"1827),
 50   (sequence "X%u"04)
 51 )>;

定义指令

LLVM 中,<Target>InstrInfo.td文件用于描述指令。

对于MyRISCV目标后端,MyRISCVInstrInfo.td位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 class RV32 : Instruction {
  2   let Size = 4;
  3   let Namespace = "MyRISCV";
  4   bits<32> Inst;
  5 }
  6 
  7 def MyRISCVRetFlag : SDNode<"MyRISCVISD::RET_FLAG", SDTNone,
  8                             [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
  9 
 10 def simm12 : Operand<i32>, ImmLeaf<i32, [{return isInt<12>(Imm);}]>;
 11 
 12 def ADDI : RV32 {
 13   let OutOperandList = (outs GPR:$rd);
 14   let InOperandList = (ins GPR:$rs1, simm12:$imm12);
 15   let AsmString = "addi $rd$rs1$imm12";
 16   let Pattern = [(set GPR:$rd, (add GPR:$rs1, simm12:$imm12))];
 17   bits<5> rd;
 18   bits<5> rs1;
 19   bits<12> imm12;
 20   let Inst{31-20} = imm12;
 21   let Inst{19-15} = rs1;
 22   let Inst{14-12} = 0b000;
 23   let Inst{11-7} = rd;
 24   let Inst{6-0} = 0b0010011;
 25 }
 26 
 27 def JALR : RV32 {
 28   let OutOperandList = (outs GPR:$rd);
 29   let InOperandList = (ins GPR:$rs1, simm12:$imm12);
 30   let AsmString = "jalr $rd${imm12}(${rs1})";
 31   bits<5> rd;
 32   bits<5> rs1;
 33   bits<12> imm12;
 34   let Inst{31-20} = imm12;
 35   let Inst{19-15} = rs1;
 36   let Inst{14-12} = 0b000;
 37   let Inst{11-7} = rd;
 38   let Inst{6-0} = 0b1101111;
 39   let isCall = 1;
 40 }
 41 
 42 def : InstAlias<"ret", (JALR X0, X1, 0), 4>;
 43 
 44 def PseudoRET : RV32, PseudoInstExpansion<(JALR X0, X1, 0)> {
 45   let OutOperandList = (outs);
 46   let InOperandList = (ins);
 47   let Pattern = [(MyRISCVRetFlag)];
 48   let isPseudo = 1;
 49   let isReturn = 1;
 50   let isTerminator = 1;
 51 }

定义调用约定

LLVM 中,<Target>CallingConv.td文件用于描述程序调用约定。

对于MyRISCV目标后端,MyRISCVCallingConv.td位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 def RetCC_MyRISCV : CallingConv<[
  2   CCIfType<[i1, i8, i16, i32], CCAssignToReg<[X10, X11]>>,
  3   CCIfType<[i32], CCAssignToStack<44>>,
  4 ]>;
  5 
  6 def CC_MyRISCV : CallingConv<[
  7   CCIfType<[i1, i8, i16, i32], CCAssignToReg<[X10, X11, X12, X13, X14, X15, X16, X17]>>,
  8   CCIfType<[i32], CCAssignToStack<44>>,
  9 ]>;
 10 
 11 def CC_Save : CalleeSavedRegs<(add X2, X8, X9, (sequence "X%u"1827))>;

支持生成汇编代码

step 0: 注册目标后端 MyRISCV

具体步骤参考上一篇《LLVM 之后端篇(2):如何扩展 llc 的目标后端》。

step 1: MyRISCV.h

MyRISCV.h用于声明全局函数,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MYRISCV_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MYRISCV_H
  3 
  4 namespace llvm {
  5 
  6 class MyRISCVTargetMachine;
  7 class FunctionPass;
  8 
  9 FunctionPass *createMyRISCVISelDag(MyRISCVTargetMachine &TM);
 10 
 11 } // end namespace llvm
 12 
 13 #endif // LLVM_LIB_TARGET_MYRISCV_MYRISCV_H

step 2: MyRISCVTargetMachine.h

MyRISCVTargetMachine.h用于声明继承自llvm::LLVMTargetMachine的派生类MyRISCVTargetMachine,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MYRISCVTARGETMACHINE_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MYRISCVTARGETMACHINE_H
  3 
  4 #include "MyRISCVSubtarget.h"
  5 #include "llvm/Target/TargetMachine.h"
  6 
  7 namespace llvm {
  8 
  9 class MyRISCVTargetMachine : public LLVMTargetMachine {
 10   MyRISCVSubtarget Subtarget;
 11   std::unique_ptr<TargetLoweringObjectFile> TLOF;
 12 
 13 public:
 14   MyRISCVTargetMachine(const Target &T, const Triple &TT, StringRef CPU    ,
 15                        StringRef FS, const TargetOptions &Options,
 16                        Optional<Reloc::Model> RM, Optional<CodeModel::M    odel> CM,
 17                        CodeGenOpt::Level OL, bool JIT);
 18 
 19   const MyRISCVSubtarget *getSubtargetImpl(const Function &F) const ove    rride {
 20     return &Subtarget;
 21   }
 22 
 23   const MyRISCVSubtarget *getSubtargetImpl() const return &Subtarget;     }
 24 
 25   TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
 26 
 27   TargetLoweringObjectFile *getObjFileLowering() const override {
 28     return TLOF.get();
 29   }
 30 };
 31 
 32 } // end namespace llvm
 33 
 34 #endif // LLVM_LIB_TARGET_MYRISCV_MYRISCVTARGETMACHINE_H

step 3: MyRISCVTargetMachine.cpp

llvm/lib/Target/MyRISCV/MyRISCVTargetMachine.cpp 的内容如下:

  1 #include "MyRISCVTargetMachine.h"
  2 #include "MyRISCV.h"
  3 #include "TargetInfo/MyRISCVTargetInfo.h"
  4 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
  5 #include "llvm/CodeGen/TargetPassConfig.h"
  6 #include "llvm/MC/TargetRegistry.h"
  7 
  8 using namespace llvm;
  9 
 10 namespace {
 11 
 12 class MyRISCVPassConfig : public TargetPassConfig {
 13 public:
 14   MyRISCVPassConfig(MyRISCVTargetMachine &TM, PassManagerBase &PM)
 15       : TargetPassConfig(TM, PM) {}
 16 
 17   bool addInstSelector() override {
 18     addPass(createMyRISCVISelDag(getMyRISCVTargetMachine()));
 19     return false;
 20   }
 21 
 22 private:
 23   MyRISCVTargetMachine &getMyRISCVTargetMachine() const {
 24     return getTM<MyRISCVTargetMachine>();
 25   }
 26 };
 27 
 28 StringRef computeDataLayout(const Triple &TT) {
 29   assert(TT.isArch32Bit() && "Only RV32 is currently supported!");
 30   return "e-m:e-p:32:32-i64:64-n32-S128";
 31 }
 32 
 33 Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
 34   return RM.hasValue() ? *RM : Reloc::Static;
 35 }
 36 
 37 } // end anonymous namespace
 38 
 39 MyRISCVTargetMachine::MyRISCVTargetMachine(const Target &T, const Triple &TT,
 40                                            StringRef CPU, StringRef FS,
 41                                            const TargetOptions &Options,
 42                                            Optional<Reloc::Model> RM,
 43                                            Optional<CodeModel::Model> CM,
 44                                            CodeGenOpt::Level OL, bool JIT)
 45     : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
 46                         getEffectiveRelocModel(RM),
 47                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
 48       Subtarget(TT, CPU, CPU, FS, *this),
 49       TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
 50   initAsmInfo();
 51 }
 52 
 53 TargetPassConfig *MyRISCVTargetMachine::createPassConfig(PassManagerBase &PM) {
 54   return new MyRISCVPassConfig(*this, PM);
 55 }
 56 
 57 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMyRISCVTarget() {
 58   RegisterTargetMachine<MyRISCVTargetMachine> X(getMyRISCV32Target());
 59 }

step 4: MyRISCVSubtarget.h

MyRISCVSubtarget.h用于声明继承自llvm::MyRISCVGenSubtargetInfo(位于MyRISCVGenSubtargetInfo.inc文件)的派生类MyRISCVSubtarget,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MYRISCVSUBTARGET_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MYRISCVSUBTARGET_H
  3 
  4 #include "MyRISCVFrameLowering.h"
  5 #include "MyRISCVISelLowering.h"
  6 #include "MyRISCVInstrInfo.h"
  7 #include "MyRISCVRegisterInfo.h"
  8 #include "llvm/CodeGen/TargetSubtargetInfo.h"
  9 
 10 #define GET_SUBTARGETINFO_HEADER
 11 #include "MyRISCVGenSubtargetInfo.inc"
 12 
 13 namespace llvm {
 14 
 15 class MyRISCVTargetMachine;
 16 
 17 class MyRISCVSubtarget : public MyRISCVGenSubtargetInfo {
 18   MyRISCVTargetLowering TLInfo;
 19   MyRISCVFrameLowering FrameLowering;
 20   MyRISCVInstrInfo InstrInfo;
 21   MyRISCVRegisterInfo RegInfo;
 22 
 23 public:
 24   MyRISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
 25                    StringRef FS, MyRISCVTargetMachine &TM);
 26 
 27   const MyRISCVTargetLowering *getTargetLowering() const override {
 28     return &TLInfo;
 29   }
 30 
 31   const MyRISCVFrameLowering *getFrameLowering() const override {
 32     return &FrameLowering;
 33   }
 34 
 35   const MyRISCVInstrInfo *getInstrInfo() const override return &InstrInfo; }
 36 
 37   const MyRISCVRegisterInfo *getRegisterInfo() const override {
 38     return &RegInfo;
 39   }
 40 
 41 private:
 42   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
 43 
 44   MyRISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
 45                                                     StringRef CPU,
 46                                                     StringRef FS)
;
 47 };
 48 
 49 } // end namespace llvm
 50 
 51 #endif // LLVM_LIB_TARGET_MYRISCV_MYRISCVSUBTARGET_H

step 5: MyRISCVSubtarget.cpp

llvm/lib/Target/MyRISCV/MyRISCVSubtarget.cpp 的内容如下:

  1 #include "MyRISCVSubtarget.h"
  2 #include "MyRISCVTargetMachine.h"
  3 
  4 using namespace llvm;
  5 
  6 #define DEBUG_TYPE "riscv-subtarget"
  7 
  8 #define GET_SUBTARGETINFO_MC_DESC
  9 #define GET_SUBTARGETINFO_TARGET_DESC
 10 #define GET_SUBTARGETINFO_CTOR
 11 #include "MyRISCVGenSubtargetInfo.inc"
 12 
 13 MyRISCVSubtarget::MyRISCVSubtarget(const Triple &TT, StringRef CPU,
 14                                    StringRef TuneCPU, StringRef FS,
 15                                    MyRISCVTargetMachine &TM)
 16     : MyRISCVGenSubtargetInfo(TT, CPU, TuneCPU, FS), TLInfo(TM),
 17       FrameLowering(initializeSubtargetDependencies(TT, CPU, FS)),
 18       InstrInfo(*this), RegInfo(getHwMode()) {}
 19 
 20 MyRISCVSubtarget &
 21 MyRISCVSubtarget::initializeSubtargetDependencies(const Triple &TT,
 22                                                   StringRef CPU, StringRef FS) {
 23   if (CPU.empty()) {
 24     assert(TT.isArch32Bit() && "Only RV32 is currently supported!");
 25     CPU = "generic-rv32";
 26   }
 27   ParseSubtargetFeatures(CPU, CPU, FS);
 28   return *this;
 29 }

step 6: MyRISCVRegisterInfo.h

MyRISCVRegisterInfo.h用于声明继承自llvm::MyRISCVGenRegisterInfo(位于MyRISCVGenRegisterInfo.inc文件)的派生类MyRISCVRegisterInfo,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MYRISCVREGISTERINFO_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MYRISCVREGISTERINFO_H
  3 
  4 #include "llvm/CodeGen/TargetRegisterInfo.h"
  5 
  6 #define GET_REGINFO_HEADER
  7 #include "MyRISCVGenRegisterInfo.inc"
  8 
  9 namespace llvm {
 10 
 11 class MyRISCVRegisterInfo : public MyRISCVGenRegisterInfo {
 12 public:
 13   explicit MyRISCVRegisterInfo(unsigned HwMode);
 14 
 15   const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
 16 
 17   BitVector getReservedRegs(const MachineFunction &MF) const override;
 18 
 19   void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
 20                            unsigned FIOperandNum,
 21                            RegScavenger *RS = nullptr)
 const override
;
 22 
 23   Register getFrameRegister(const MachineFunction &MF) const override;
 24 };
 25 
 26 } // end namespace llvm
 27 
 28 #endif // LLVM_LIB_TARGET_MYRISCV_MYRISCVREGISTERINFO_H

step 7: MyRISCVRegisterInfo.cpp

llvm/lib/Target/MyRISCV/MyRISCVRegisterInfo.cpp 的内容如下:

  1 #include "MyRISCVRegisterInfo.h"
  2 #include "MCTargetDesc/MyRISCVMCTargetDesc.h"
  3 #include "MyRISCVFrameLowering.h"
  4 #include "MyRISCVSubtarget.h"
  5 #include "llvm/CodeGen/MachineFunction.h"
  6 
  7 #define GET_REGINFO_TARGET_DESC
  8 #include "MyRISCVGenRegisterInfo.inc"
  9 
 10 using namespace llvm;
 11 
 12 MyRISCVRegisterInfo::MyRISCVRegisterInfo(unsigned HwMode)
 13     : MyRISCVGenRegisterInfo(MyRISCV::X1, /*DwarfFlavour*/ 0/*EHFlavor*/ 0,
 14                              /*PC*/ 0, HwMode) {}
 15 
 16 const MCPhysReg *
 17 MyRISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
 18   return CC_Save_SaveList;
 19 }
 20 
 21 BitVector
 22 MyRISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
 23   BitVector Reserved(getNumRegs());
 24   Reserved.set(MyRISCV::X0);
 25   Reserved.set(MyRISCV::X2);
 26   Reserved.set(MyRISCV::X3);
 27   Reserved.set(MyRISCV::X4);
 28   return Reserved;
 29 }
 30 
 31 void MyRISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
 32                                               int SPAdj, unsigned FIOperandNum,
 33                                               RegScavenger *RS) const {}
 34 
 35 Register
 36 MyRISCVRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
 37   return MyRISCV::X8;
 38 }

step 8: MyRISCVMCInstLower.h

MyRISCVMCInstLower.h用于声明类MyRISCVMCInstLower,该类负责将机器指令的表示形式从MachineInstr转换为轻量级的MCInst,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MYRISCVMCINSTLOWER_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MYRISCVMCINSTLOWER_H
  3 
  4 namespace llvm {
  5 
  6 class MCContext;
  7 class AsmPrinter;
  8 class MachineInstr;
  9 class MachineOperand;
 10 class MCInst;
 11 class MCOperand;
 12 
 13 class MyRISCVMCInstLower {
 14   MCContext &Ctx;
 15   AsmPrinter &Printer;
 16 
 17 public:
 18   MyRISCVMCInstLower(MCContext &Ctx, AsmPrinter &Printer);
 19 
 20   void Lower(const MachineInstr *MI, MCInst &OutMI) const;
 21 
 22 private:
 23   bool LowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;
 24 };
 25 
 26 } // end namespace llvm
 27 
 28 #endif // LLVM_LIB_TARGET_MYRISCV_MYRISCVMCINSTLOWER_H

step 9: MyRISCVMCInstLower.cpp

llvm/lib/Target/MyRISCV/MyRISCVMCInstLower.cpp 的内容如下:

  1 #include "MyRISCVMCInstLower.h"
  2 #include "llvm/CodeGen/AsmPrinter.h"
  3 #include "llvm/CodeGen/MachineInstr.h"
  4 #include "llvm/CodeGen/MachineOperand.h"
  5 #include "llvm/MC/MCContext.h"
  6 #include "llvm/MC/MCExpr.h"
  7 #include "llvm/MC/MCInst.h"
  8 
  9 using namespace llvm;
 10 
 11 MyRISCVMCInstLower::MyRISCVMCInstLower(MCContext &Ctx, AsmPrinter &Printer)
 12     : Ctx(Ctx), Printer(Printer) {}
 13 
 14 void MyRISCVMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
 15   OutMI.setOpcode(MI->getOpcode());
 16 
 17   for (const MachineOperand &MO : MI->operands()) {
 18     MCOperand MCOp;
 19     if (LowerOperand(MO, MCOp)) {
 20       OutMI.addOperand(MCOp);
 21     }
 22   }
 23 }
 24 
 25 bool MyRISCVMCInstLower::LowerOperand(const MachineOperand &MO,
 26                                       MCOperand &MCOp) const {
 27   switch (MO.getType()) {
 28   case MachineOperand::MO_Register:
 29     if (MO.isImplicit()) {
 30       return false;
 31     }
 32     MCOp = MCOperand::createReg(MO.getReg());
 33     break;
 34   case MachineOperand::MO_Immediate:
 35     MCOp = MCOperand::createImm(MO.getImm());
 36     break;
 37   default:
 38     llvm_unreachable("Unknown operand type!");
 39   }
 40   return true;
 41 }

step 10: MyRISCVISelLowering.h

MyRISCVRegisterInfo.h用于声明继承自llvm::TargetLowering的派生类MyRISCVTargetLowering,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MYRISCVISELLOWERING_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MYRISCVISELLOWERING_H
  3 
  4 #include "llvm/CodeGen/SelectionDAG.h"
  5 #include "llvm/CodeGen/TargetLowering.h"
  6 
  7 namespace llvm {
  8 
  9 class MyRISCVSubtarget;
 10 class MyRISCVTargetMachine;
 11 
 12 namespace MyRISCVISD {
 13 
 14 enum NodeType {
 15   FIRST_NUMBER = ISD::BUILTIN_OP_END,
 16   RET_FLAG,
 17 };
 18 
 19 } // namespace MyRISCVISD
 20 
 21 class MyRISCVTargetLowering : public TargetLowering {
 22   const MyRISCVSubtarget &Subtarget;
 23 
 24 public:
 25   explicit MyRISCVTargetLowering(MyRISCVTargetMachine &TM);
 26 
 27   const char *getTargetNodeName(unsigned Opcode) const override;
 28 
 29   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
 30                                bool IsVarArg,
 31                                const SmallVectorImpl<ISD::InputArg> &Ins,
 32                                const SDLoc &DL, SelectionDAG &DAG,
 33                                SmallVectorImpl<SDValue> &InVals)
 const override
;
 34 
 35   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
 36                       const SmallVectorImpl<ISD::OutputArg> &Outs,
 37                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
 38                       SelectionDAG &DAG)
 const override
;
 39 };
 40 
 41 } // end namespace llvm
 42 
 43 #endif // LLVM_LIB_TARGET_MYRISCV_MYRISCVISELLOWERING_H

step 11: MyRISCVISelLowering.cpp

llvm/lib/Target/MyRISCV/MyRISCVISelLowering.cpp 的内容如下:

  1 #include "MyRISCVISelLowering.h"
  2 #include "MCTargetDesc/MyRISCVMCTargetDesc.h"
  3 #include "MyRISCVSubtarget.h"
  4 #include "MyRISCVTargetMachine.h"
  5 #include "llvm/CodeGen/CallingConvLower.h"
  6 
  7 using namespace llvm;
  8 
  9 #include "MyRISCVGenCallingConv.inc"
 10 
 11 MyRISCVTargetLowering::MyRISCVTargetLowering(MyRISCVTargetMachine &TM)
 12     : TargetLowering(TM), Subtarget(*TM.getSubtargetImpl()) {
 13   addRegisterClass(MVT::i32, &MyRISCV::GPRRegClass);
 14   computeRegisterProperties(Subtarget.getRegisterInfo());
 15 }
 16 
 17 const char *MyRISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
 18   switch (Opcode) {
 19   case MyRISCVISD::RET_FLAG:
 20     return "MyRISCVISD::RET_FLAG";
 21   default:
 22     return nullptr;
 23   }
 24 }
 25 
 26 SDValue MyRISCVTargetLowering::LowerFormalArguments(
 27     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
 28     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
 29     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
 30   SmallVector<CCValAssign, 16> ArgLocs;
 31   MachineFunction &MF = DAG.getMachineFunction();
 32   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
 33   CCInfo.AnalyzeFormalArguments(Ins, CC_MyRISCV);
 34 
 35   for (unsigned i = 0, e = ArgLocs.size(); i < e; ++i) {
 36     CCValAssign &VA = ArgLocs[i];
 37   }
 38 
 39   return Chain;
 40 }
 41 
 42 SDValue
 43 MyRISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
 44                                    bool IsVarArg,
 45                                    const SmallVectorImpl<ISD::OutputArg> &Outs,
 46                                    const SmallVectorImpl<SDValue> &OutVals,
 47                                    const SDLoc &DL, SelectionDAG &DAG) const {
 48   SmallVector<CCValAssign, 16> RVLocs;
 49 
 50   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
 51                  *DAG.getContext());
 52   CCInfo.AnalyzeReturn(Outs, RetCC_MyRISCV);
 53 
 54   SDValue Glue;
 55   SmallVector<SDValue, 4> RetOps(1, Chain);
 56 
 57   for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) {
 58     CCValAssign &VA = RVLocs[i];
 59     assert(VA.isRegLoc() && "Can only return in registers!");
 60     Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Glue);
 61     Glue = Chain.getValue(1);
 62     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
 63   }
 64 
 65   RetOps[0] = Chain;
 66 
 67   if (Glue.getNode()) {
 68     RetOps.push_back(Glue);
 69   }
 70 
 71   return DAG.getNode(MyRISCVISD::RET_FLAG, DL, MVT::Other, RetOps);
 72 }

step 12: MyRISCVISelDAGToDAG.cpp

MyRISCVISelDAGToDAG.cpp用于定义继承自llvm::SelectionDAGISel的派生类MyRISCVDAGToDAGISel,该类用于选择机器指令,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #include "MCTargetDesc/MyRISCVMCTargetDesc.h"
  2 #include "MyRISCV.h"
  3 #include "MyRISCVTargetMachine.h"
  4 #include "llvm/CodeGen/SelectionDAGISel.h"
  5 
  6 using namespace llvm;
  7 
  8 namespace {
  9 
 10 class MyRISCVDAGToDAGISel : public SelectionDAGISel {
 11 public:
 12   explicit MyRISCVDAGToDAGISel(MyRISCVTargetMachine &TM)
 13       : SelectionDAGISel(TM) {}
 14 
 15   StringRef getPassName() const override {
 16     return "MyRISCV DAG->DAG Pattern Instruction Selection";
 17   }
 18 
 19   void Select(SDNode *N) override;
 20 
 21 private:
 22 #include "MyRISCVGenDAGISel.inc"
 23 };
 24 
 25 } // end anonymous namespace
 26 
 27 void MyRISCVDAGToDAGISel::Select(SDNode *N) {
 28   SDLoc DL(N);
 29 
 30   switch (N->getOpcode()) {
 31   case ISD::Constant: {
 32     int64_t Imm = cast<ConstantSDNode>(N)->getSExtValue();
 33     if (-2048 <= Imm && Imm <= 2047) {
 34       SDValue SDImm = CurDAG->getTargetConstant(Imm, DL, MVT::i32);
 35       SDValue SrcReg = CurDAG->getRegister(MyRISCV::X0, MVT::i32);
 36       SDNode *Result =
 37           CurDAG->getMachineNode(MyRISCV::ADDI, DL, MVT::i32, SrcReg, SDImm);
 38       ReplaceNode(N, Result);
 39       return;
 40     }
 41   }
 42   }
 43 
 44   SelectCode(N);
 45 }
 46 
 47 FunctionPass *llvm::createMyRISCVISelDag(MyRISCVTargetMachine &TM) {
 48   return new MyRISCVDAGToDAGISel(TM);
 49 }

step 13: MyRISCVInstrInfo.h

MyRISCVInstrInfo.h用于声明继承自llvm::MyRISCVGenInstrInfo(位于MyRISCVGenInstrInfo.inc文件)的派生类MyRISCVInstrInfo,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MYRISCVINSTRINFO_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MYRISCVINSTRINFO_H
  3 
  4 #include "llvm/CodeGen/TargetInstrInfo.h"
  5 
  6 #define GET_INSTRINFO_HEADER
  7 #include "MyRISCVGenInstrInfo.inc"
  8 
  9 namespace llvm {
 10 
 11 class MyRISCVSubtarget;
 12 
 13 class MyRISCVInstrInfo : public MyRISCVGenInstrInfo {
 14   const MyRISCVSubtarget &STI;
 15 
 16 public:
 17   explicit MyRISCVInstrInfo(MyRISCVSubtarget &STI);
 18 };
 19 
 20 } // end namespace llvm
 21 
 22 #endif // LLVM_LIB_TARGET_MYRISCV_MYRISCVINSTRINFO_H

step 14: MyRISCVInstrInfo.cpp

llvm/lib/Target/MyRISCV/MyRISCVInstrInfo.cpp 的内容如下:

  1 #include "MyRISCVInstrInfo.h"
  2 #include "MCTargetDesc/MyRISCVMCTargetDesc.h"
  3 #include "MyRISCVSubtarget.h"
  4 
  5 using namespace llvm;
  6 
  7 #define GET_INSTRINFO_CTOR_DTOR
  8 #include "MyRISCVGenInstrInfo.inc"
  9 
 10 MyRISCVInstrInfo::MyRISCVInstrInfo(MyRISCVSubtarget &STI)
 11     : MyRISCVGenInstrInfo(), STI(STI) {}

step 15: MyRISCVFrameLowering.h

MyRISCVInstrInfo.h用于声明继承自llvm::TargetFrameLowering的派生类MyRISCVFrameLowering,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MYRISCVFRAMELOWERING_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MYRISCVFRAMELOWERING_H
  3 
  4 #include "llvm/CodeGen/TargetFrameLowering.h"
  5 
  6 namespace llvm {
  7 
  8 class MyRISCVSubtarget;
  9 
 10 class MyRISCVFrameLowering : public TargetFrameLowering {
 11   const MyRISCVSubtarget &STI;
 12 
 13 public:
 14   explicit MyRISCVFrameLowering(const MyRISCVSubtarget &STI)
 15       : TargetFrameLowering(StackGrowsDown,
 16                             /*StackAlignment=*/Align(16
),
 17                             /*LocalAreaOffset=*/0),
 18         STI(STI
{}
 19 
 20   void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBBconst override;
 21 
 22   void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBBconst override;
 23 
 24   bool hasFP(const MachineFunction &MFconst override;
 25 };
 26 
 27 } // end namespace llvm
 28 
 29 #endif // LLVM_LIB_TARGET_MYRISCV_MYRISCVFRAMELOWERING_H

step 16: MyRISCVFrameLowering.cpp

llvm/lib/Target/MyRISCV/MyRISCVFrameLowering.cpp 的内容如下:

  1 #include "MyRISCVFrameLowering.h"
  2 #include "llvm/CodeGen/MachineFunction.h"
  3 
  4 using namespace llvm;
  5 
  6 void MyRISCVFrameLowering::emitPrologue(MachineFunction &MF,
  7                                         MachineBasicBlock &MBB) const {}
  8 
  9 void MyRISCVFrameLowering::emitEpilogue(MachineFunction &MF,
 10                                         MachineBasicBlock &MBB) const {}
 11 
 12 bool MyRISCVFrameLowering::hasFP(const MachineFunction &MF) const {
 13   return false;
 14 }

step 17: MyRISCVAsmPrinter.cpp

MyRISCVAsmPrinter.cpp用于定义继承自llvm::AsmPrinter的派生类MyRISCVAsmPrinter,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #include "MCTargetDesc/MyRISCVMCTargetDesc.h"
  2 #include "MyRISCVMCInstLower.h"
  3 #include "TargetInfo/MyRISCVTargetInfo.h"
  4 #include "llvm/CodeGen/AsmPrinter.h"
  5 #include "llvm/MC/MCStreamer.h"
  6 #include "llvm/MC/TargetRegistry.h"
  7 
  8 using namespace llvm;
  9 
 10 namespace {
 11 
 12 class MyRISCVAsmPrinter : public AsmPrinter {
 13   MyRISCVMCInstLower MCInstLowering;
 14 
 15 public:
 16   MyRISCVAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
 17       : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this) {
 18   }
 19 
 20   void emitInstruction(const MachineInstr *MI) override;
 21 
 22 private:
 23   bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
 24                                    const MachineInstr *MI)
;
 25 };
 26 
 27 } // end anonymous namespace
 28 
 29 #include "MyRISCVGenMCPseudoLowering.inc"
 30 
 31 void MyRISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
 32   if (emitPseudoExpansionLowering(*OutStreamer, MI)) {
 33     return;
 34   }
 35 
 36   MCInst TmpInst;
 37   MCInstLowering.Lower(MI, TmpInst);
 38   EmitToStreamer(*OutStreamer, TmpInst);
 39 }
 40 
 41 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMyRISCVAsmPrinter() {
 42   RegisterAsmPrinter<MyRISCVAsmPrinter> X(getMyRISCV32Target());
 43 }

step 18: CMakeLists.txt

llvm/lib/Target/MyRISCV/CMakeLists.txt 的内容如下:

add_llvm_component_group(MyRISCV)

set(LLVM_TARGET_DEFINITIONS MyRISCV.td)

tablegen(LLVM MyRISCVGenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM MyRISCVGenCallingConv.inc -gen-callingconv)
tablegen(LLVM MyRISCVGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM MyRISCVGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM MyRISCVGenMCPseudoLowering.inc -gen-pseudo-lowering)
tablegen(LLVM MyRISCVGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM MyRISCVGenSubtargetInfo.inc -gen-subtarget)

add_public_tablegen_target(MyRISCVCommonTableGen)

set(sources
  MyRISCVTargetMachine.cpp
  MyRISCVISelDAGToDAG.cpp
  MyRISCVAsmPrinter.cpp
  MyRISCVSubtarget.cpp
  MyRISCVISelLowering.cpp
  MyRISCVFrameLowering.cpp
  MyRISCVInstrInfo.cpp
  MyRISCVRegisterInfo.cpp
  MyRISCVMCInstLower.cpp
)

add_llvm_target(MyRISCVCodeGen ${sources}
  LINK_COMPONENTS
  AsmPrinter
  Core
  CodeGen
  MC
  MyRISCVDesc
  MyRISCVInfo
  SelectionDAG
  Support
  Target

  ADD_TO_COMPONENT
  MyRISCV
)

add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)

step 19: MyRISCVMCTargetDesc.h

llvm/lib/Target/MyRISCV/MCTargetDesc/MyRISCVMCTargetDesc.h 的内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MCTARGETDESC_MYRISCVMCTARGETDESC_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MCTARGETDESC_MYRISCVMCTARGETDESC_H
  3 
  4 #define GET_REGINFO_ENUM
  5 #include "MyRISCVGenRegisterInfo.inc"
  6 
  7 #define GET_INSTRINFO_ENUM
  8 #include "MyRISCVGenInstrInfo.inc"
  9 
 10 #define GET_SUBTARGETINFO_ENUM
 11 #include "MyRISCVGenSubtargetInfo.inc"
 12 
 13 #endif // LLVM_LIB_TARGET_MYRISCV_MCTARGETDESC_MYRISCVMCTARGETDESC_H

step 20: MyRISCVMCTargetDesc.cpp

llvm/lib/Target/MyRISCV/MCTargetDesc/MyRISCVMCTargetDesc.cpp 的内容如下:

  1 #include "MyRISCVMCTargetDesc.h"
  2 #include "MyRISCVInstPrinter.h"
  3 #include "MyRISCVMCAsmInfo.h"
  4 #include "TargetInfo/MyRISCVTargetInfo.h"
  5 #include "llvm/MC/MCInstrInfo.h"
  6 #include "llvm/MC/MCRegisterInfo.h"
  7 #include "llvm/MC/MCSubtargetInfo.h"
  8 #include "llvm/MC/TargetRegistry.h"
  9 
 10 #define GET_INSTRINFO_MC_DESC
 11 #include "MyRISCVGenInstrInfo.inc"
 12 
 13 #define GET_REGINFO_MC_DESC
 14 #include "MyRISCVGenRegisterInfo.inc"
 15 
 16 #define GET_SUBTARGETINFO_MC_DESC
 17 #include "MyRISCVGenSubtargetInfo.inc"
 18 
 19 using namespace llvm;
 20 
 21 namespace {
 22 
 23 MCInstrInfo *createMyRISCVMCInstrInfo() {
 24   MCInstrInfo *X = new MCInstrInfo();
 25   InitMyRISCVMCInstrInfo(X);
 26   return X;
 27 }
 28 
 29 MCRegisterInfo *createMyRISCVMCRegisterInfo(const Triple &TT) {
 30   MCRegisterInfo *X = new MCRegisterInfo();
 31   InitMyRISCVMCRegisterInfo(X, MyRISCV::X1);
 32   return X;
 33 }
 34 
 35 MCAsmInfo *createMyRISCVMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TT,
 36                                   const MCTargetOptions &Options)
 
{
 37   return new MyRISCVMCAsmInfo(TT);
 38 }
 39 
 40 MCSubtargetInfo *createMyRISCVMCSubtargetInfo(const Triple &TT, StringRef CPU,
 41                                               StringRef FS)
 
{
 42   if (CPU.empty()) {
 43     assert(TT.isArch32Bit() && "Only RV32 is currently supported!");
 44     CPU = "generic-rv32";
 45   }
 46   return createMyRISCVMCSubtargetInfoImpl(TT, CPU, CPU, FS);
 47 }
 48 
 49 MCInstPrinter *createMyRISCVMCInstPrinter(const Triple &T,
 50                                           unsigned SyntaxVariant,
 51                                           const MCAsmInfo &MAI,
 52                                           const MCInstrInfo &MII,
 53                                           const MCRegisterInfo &MRI)
 
{
 54   return new MyRISCVInstPrinter(MAI, MII, MRI);
 55 }
 56 
 57 } // end anonymous namespace
 58 
 59 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMyRISCVTargetMC() {
 60   Target &RV32 = getMyRISCV32Target();
 61   TargetRegistry::RegisterMCAsmInfo(RV32, createMyRISCVMCAsmInfo);
 62   TargetRegistry::RegisterMCInstrInfo(RV32, createMyRISCVMCInstrInfo);
 63   TargetRegistry::RegisterMCRegInfo(RV32, createMyRISCVMCRegisterInfo);
 64   TargetRegistry::RegisterMCSubtargetInfo(RV32, createMyRISCVMCSubtargetInfo);
 65   TargetRegistry::RegisterMCInstPrinter(RV32, createMyRISCVMCInstPrinter);
 66 }

step 21: MyRISCVMCAsmInfo.h

llvm/lib/Target/MyRISCV/MCTargetDesc/MyRISCVMCAsmInfo.h 的内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MCTARGETDESC_MYRISCVMCASMINFO_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MCTARGETDESC_MYRISCVMCASMINFO_H
  3 
  4 #include "llvm/MC/MCAsmInfoELF.h"
  5 
  6 namespace llvm {
  7 
  8 class Triple;
  9 
 10 class MyRISCVMCAsmInfo : public MCAsmInfoELF {
 11 public:
 12   explicit MyRISCVMCAsmInfo(const Triple &TT);
 13 };
 14 
 15 } // end namespace llvm
 16 
 17 #endif // LLVM_LIB_TARGET_MYRISCV_MCTARGETDESC_MYRISCVMCASMINFO_H

step 22: MyRISCVMCAsmInfo.cpp

llvm/lib/Target/MyRISCV/MCTargetDesc/MyRISCVMCAsmInfo.cpp 的内容如下:

  1 #include "MyRISCVMCAsmInfo.h"
  2 #include "llvm/ADT/Triple.h"
  3 
  4 using namespace llvm;
  5 
  6 MyRISCVMCAsmInfo::MyRISCVMCAsmInfo(const Triple &TT) {
  7   assert(TT.isArch32Bit() && "Only RV32 is currently supported!");
  8   CodePointerSize = CalleeSaveStackSlotSize = TT.isArch32Bit() ? 4 : 4;
  9   CommentString = "#";
 10   Data16bitsDirective = "\t.half\t";
 11   Data32bitsDirective = "\t.word\t";
 12 }

step 23: MyRISCVInstPrinter.h

MyRISCVInstPrinter.h用于声明继承自llvm::MCInstPrinter的派生类MyRISCVInstPrinter,该类负责打印汇编代码,位于llvm/lib/Target/MyRISCV目录中,其内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_MCTARGETDESC_MYRISCVINSTPRINTER_H
  2 #define LLVM_LIB_TARGET_MYRISCV_MCTARGETDESC_MYRISCVINSTPRINTER_H
  3 
  4 #include "llvm/MC/MCInstPrinter.h"
  5 
  6 namespace llvm {
  7 
  8 class MyRISCVInstPrinter : public MCInstPrinter {
  9 public:
 10   MyRISCVInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
 11                      const MCRegisterInfo &MRI)
 12       : MCInstPrinter(MAI, MII, MRI) {}
 13 
 14   void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
 15                  const MCSubtargetInfo &STI, raw_ostream &OS)
 override
;
 16 
 17 private:
 18   std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) override;
 19 
 20   void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
 21 
 22   bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &O);
 23 
 24   static const char *getRegisterName(unsigned RegNo, unsigned AltIdx);
 25 
 26   void printCustomAliasOperand(const MCInst *MI, uint64_t Address,
 27                                unsigned OpIdx, unsigned PrintMethodIdx,
 28                                raw_ostream &O)
;
 29 
 30   void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
 31 };
 32 
 33 } // end namespace llvm
 34 
 35 #endif // LLVM_LIB_TARGET_MYRISCV_MCTARGETDESC_MYRISCVINSTPRINTER_H

step 24: MyRISCVInstPrinter.cpp

llvm/lib/Target/MyRISCV/MCTargetDesc/MyRISCVInstPrinter.cpp 的内容如下:

  1 #include "MyRISCVInstPrinter.h"
  2 #include "MCTargetDesc/MyRISCVMCTargetDesc.h"
  3 #include "llvm/MC/MCExpr.h"
  4 #include "llvm/MC/MCInst.h"
  5 #include "llvm/Support/FormattedStream.h"
  6 
  7 using namespace llvm;
  8 
  9 #define PRINT_ALIAS_INSTR
 10 #include "MyRISCVGenAsmWriter.inc"
 11 
 12 void MyRISCVInstPrinter::printInst(const MCInst *MI, uint64_t Address,
 13                                    StringRef Annot, const MCSubtargetInfo &STI,
 14                                    raw_ostream &OS) {
 15   if (!printAliasInstr(MI, Address, OS)) {
 16     printInstruction(MI, Address, OS);
 17   }
 18 }
 19 
 20 void MyRISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
 21                                       raw_ostream &OS) {
 22   const MCOperand &MO = MI->getOperand(OpNo);
 23 
 24   if (MO.isReg()) {
 25     OS << getRegisterName(MO.getReg(), MyRISCV::ABIRegAltName);
 26     return;
 27   }
 28 
 29   if (MO.isImm()) {
 30     OS << MO.getImm();
 31     return;
 32   }
 33 
 34   assert(MO.isExpr() && "Unknown operand kind in printOperand!");
 35   MO.getExpr()->print(OS, &MAI);
 36 }

step 25: MCTargetDesc/CMakeLists.txt

llvm/lib/Target/MyRISCV/MCTargetDesc/CMakeLists.txt 的内容如下:

add_llvm_component_library(LLVMMyRISCVDesc
  MyRISCVMCTargetDesc.cpp
  MyRISCVMCAsmInfo.cpp
  MyRISCVInstPrinter.cpp

  LINK_COMPONENTS
  MC
  MyRISCVInfo
  Support

  ADD_TO_COMPONENT
  MyRISCV
)

step 26: MyRISCVTargetInfo.h

llvm/lib/Target/MyRISCV/TargetInfo/MyRISCVTargetInfo.h 的内容如下:

  1 #ifndef LLVM_LIB_TARGET_MYRISCV_TARGETINFO_MYRISCVTARGETINFO_H
  2 #define LLVM_LIB_TARGET_MYRISCV_TARGETINFO_MYRISCVTARGETINFO_H
  3 
  4 namespace llvm {
  5 
  6 class Target;
  7 
  8 Target &getMyRISCV32Target();
  9 
 10 } // end namespace llvm
 11 
 12 #endif // LLVM_LIB_TARGET_MYRISCV_TARGETINFO_MYRISCVTARGETINFO_H

step 27: MyRISCVTargetInfo.cpp

llvm/lib/Target/MyRISCV/TargetInfo/MyRISCVTargetInfo.cpp 的内容如下:

  1 #include "TargetInfo/MyRISCVTargetInfo.h"
  2 #include "llvm/MC/TargetRegistry.h"
  3 
  4 using namespace llvm;
  5 
  6 namespace llvm {
  7 
  8 Target &getMyRISCV32Target() {
  9   static Target MyRISCV32Target;
 10   return MyRISCV32Target;
 11 }
 12 
 13 } // end namespace llvm
 14 
 15 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMyRISCVTargetInfo() {
 16   RegisterTarget<Triple::myriscv32> X(getMyRISCV32Target(), "myriscv32",
 17                                       "32-bit RISC-V""RISCV");
 18 }

step 28: TargetInfo/CMakeLists.txt

llvm/lib/Target/MyRISCV/TargetInfo/CMakeLists.txt 的内容如下:

add_llvm_component_library(LLVMMyRISCVInfo
  MyRISCVTargetInfo.cpp

  LINK_COMPONENTS
  MC

  ADD_TO_COMPONENT
  MyRISCV
)

构建并运行

step 1: 编译

在构建目录中执行如下命令:

$ ninja

step 2: 运行

在构建目录的子目录bin中执行如下命令:

$ llc -march=myriscv32 -filetype=asm test.ll -o test_my.s

test_my.s 的内容如下:

    .text
    .file   "test.ll"
    .globl  test                            # -- Begin function test
    .type   test,@function
test:                                   # @test
# %bb.0:
    addi a0, zero, 1
    ret
.Lfunc_end0:
    .size   test, .Lfunc_end0-test
                                        # -- End function
    .section    ".note.GNU-stack","",@progbits

从上面的结果可以看出,目标后端MyRISCV也将 LLVM IR 语句ret i32 1翻译成了addi a0, zero, 1ret两条汇编代码。


References


下一篇:LLVM 之后端篇(4):理解指令选择的 dump 输出

上一篇:LLVM 之后端篇(2):如何扩展 llc 的目标后端

首页