FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

LLVMのバックエンドを作るための第一歩 (14. LLVMInitializeCPUTargetMC()により登録されるクラス群)

printInstruction()などの命令プリントメソッドとMYRISCVXTargetMachineとの関連付けは、MCTargetDesc/MYRISCVXMCTargetDesc.cppで行われている。

f:id:msyksphinz:20190528001406p:plain
LLVMInitializeMYRISCVXTargetMC()により登録されるクラス群
  • llvm-myriscvx/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp
// MYRISCVXInstPrinterメソッドを返す。
static MCInstPrinter *createMYRISCVXMCInstPrinter(const Triple &T,
                                                  unsigned SyntaxVariant,
                                                  const MCAsmInfo &MAI,
                                                  const MCInstrInfo &MII,
                                                  const MCRegisterInfo &MRI) {
  return new MYRISCVXInstPrinter(MAI, MII, MRI);
}

extern "C" void LLVMInitializeMYRISCVXTargetMC() {
  for (Target *T : {&getTheMYRISCVX32Target(), &getTheMYRISCVX64Target()}) {
    // Register the MC asm info.
    RegisterMCAsmInfoFn X(*T, createMYRISCVXMCAsmInfo);

    // Register the MC instruction info.
    TargetRegistry::RegisterMCInstrInfo(*T, createMYRISCVXMCInstrInfo);

    // Register the MC register info.
    TargetRegistry::RegisterMCRegInfo(*T, createMYRISCVXMCRegisterInfo);

    // Register the MC subtarget info.
    TargetRegistry::RegisterMCSubtargetInfo(*T,
                                            createMYRISCVXMCSubtargetInfo);
    // Register the MC instruction analyzer.
    TargetRegistry::RegisterMCInstrAnalysis(*T, createMYRISCVXMCInstrAnalysis);

    // createMYRISCVXMCInstPrinterクラスを通じて、MYRISCVXInstPrintクラスを登録する。
    TargetRegistry::RegisterMCInstPrinter(*T,
                                          createMYRISCVXMCInstPrinter);
  }

}

このLLVMInitializeMYRISCVXTargetMCでは、各TargetMachineに必要な処理を登録している。

MYRISCVXは2つのTargetMachineMYRISCVX32TargetMachineMYRISCVX64TargetMachineの2つがあるので、それぞれに命令を生成するためのメソッドを登録している。

  • RegisterMCAsmInfo : アセンブリ言語生成のためのルーチンを登録する。ここで登録するルーチンはMYRISCVXMCAsmInfoクラスをベースにして生成される。 MYRISCVXAsmInfo()では、アセンブリ出力時のファイルの先頭に出す基本的な情報を記載している。

    • llvm-myriscvx/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCAsmInfo.cpp
  MYRISCVXMCAsmInfo::MYRISCVXMCAsmInfo(const Triple &TheTriple) {
    AlignmentIsInBytes          = false;
    Data16bitsDirective         = "\t.2byte\t";
    Data32bitsDirective         = "\t.4byte\t";
    Data64bitsDirective         = "\t.8byte\t";
    PrivateGlobalPrefix         = "$";
    // PrivateLabelPrefix: display $BB for the labels of basic block
    PrivateLabelPrefix          = "$";
    CommentString               = "#";
    ZeroDirective               = "\t.space\t";
    GPRel32Directive            = "\t.gpword\t";
    GPRel64Directive            = "\t.gpdword\t";
    WeakRefDirective            = "\t.weak\t";
    UseAssignmentForEHBegin = true;
  
    SupportsDebugInformation = true;
    ExceptionsType = ExceptionHandling::DwarfCFI;
    DwarfRegNumForCFI = true;
  }
  • RegisterMCInstrInfo : MYRISCVXに属する命令に関する情報を持つクラスを登録する。ここで登録するクラスはMCInstrInfoクラスだ。MCInstrInfoクラスを生成し、MYRISCVXGenInstrInfo.incで生成したMYRISCVX命令群の基本情報を登録してTargetMachineに登録する。

    • llvm-myriscvx/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp
  static MCInstrInfo *createMYRISCVXMCInstrInfo() {
    MCInstrInfo *X = new MCInstrInfo();
    InitMYRISCVXMCInstrInfo(X); // defined in MYRISCVXGenInstrInfo.inc
    return X;
  }
  • RegisterMCRegInfo : MYRISCVXに属するレジスタの情報を持つクラスを登録する。ここで登録するクラスはMCRegisterInfoクラスだ。MCRegisterInfoクラスを生成し、MYRISCVXGenRegisterInfo.incd絵生成したMYRISCVXのレジスタ群の基本情報を追加してTargetMachineに登録する。

    • llvm-myriscvx/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp
  static MCRegisterInfo *createMYRISCVXMCRegisterInfo(const Triple &TT) {
    MCRegisterInfo *X = new MCRegisterInfo();
    InitMYRISCVXMCRegisterInfo(X, MYRISCVX::RA); // defined in MYRISCVXGenRegisterInfo.inc
    return X;
  }
  • RegisterMCSubtargetInfo : MYRISCVXに属するサブターゲットの情報を登録する。サブターゲットはMYRISCVXSubtarget.hで登録したように、MYRISCVXの様々なアーキテクチャとCPUオプションを凝縮している。これらのサブターゲットの情報をTargetMachineに登録する。

    • llvm-myriscvx/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp
  static MCSubtargetInfo *createMYRISCVXMCSubtargetInfo(const Triple &TT,
                                                        StringRef CPU, StringRef FS) {
    std::string ArchFS = selectMYRISCVXArchFeature(TT, CPU);
  
    if (!FS.empty()) {
      if (!ArchFS.empty())
        ArchFS = ArchFS + "," + FS.str();
      else
        ArchFS = FS;
    }
    return createMYRISCVXMCSubtargetInfoImpl(TT, CPU, ArchFS);
    // createMYRISCVXMCSubtargetInfoImpl defined in MYRISCVXGenSubtargetInfo.inc
  }
  • RegisterMCInstrAnalysis : MYRISCVXに関する命令解析の情報を登録する。この時点では特に命令解析に関して特別なことをする必要はないので、MCInstrAnalysisクラスをそのまま継承してMYRISCVXInstrAnalysisクラスを作成して登録している。

    • llvm-myriscvx/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp
  class MYRISCVXMCInstrAnalysis : public MCInstrAnalysis {
   public:
    MYRISCVXMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
  };
  }
  
  static MCInstrAnalysis *createMYRISCVXMCInstrAnalysis(const MCInstrInfo *Info) {
    return new MYRISCVXMCInstrAnalysis(Info);
  }
  • RegisterMCInstPrinter : 命令を出力するためのルーチンだ。MYRISCVXInstPrinterクラスを生成してそのまま返する。TargetMachineにコンパイル後の命令をファイルに出力するためのルーチンを登録する。

    • llvm-myriscvx/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp
  static MCInstPrinter *createMYRISCVXMCInstPrinter(const Triple &T,
                                                    unsigned SyntaxVariant,
                                                    const MCAsmInfo &MAI,
                                                    const MCInstrInfo &MII,
                                                    const MCRegisterInfo &MRI) {
    return new MYRISCVXInstPrinter(MAI, MII, MRI);
  }