FPGA開発日記

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

オリジナルLLVM Backendを追加しよう (15. RISC-Vオリジナルターゲットの作り直し)

LLVMにはすでにRISC-Vのバックエンドサポートが追加されている。しかし、勉強のために独自のRISC-V実装をLLVMに追加している。

Chapter-3のサイズの大きなスタックフレームの処理に関して、どうにも解決できずに悩んでいる。 とりあえず最初から全体的に見直すために、いろいろ見直す場所もあるので最初から作り直している。

ディレクトリ構成

lib/Target/MYRISCVX
├── CMakeLists.txt
├── LLVMBuild.txt
├── MCTargetDesc
│?? ├── CMakeLists.txt
│?? ├── LLVMBuild.txt
│?? ├── MYRISCVXABIInfo.cpp
│?? ├── MYRISCVXABIInfo.h
│?? ├── MYRISCVXMCTargetDesc.cpp
│?? └── MYRISCVXMCTargetDesc.h
├── MYRISCVX.h
├── MYRISCVX.td
├── MYRISCVXCallingConv.td
├── MYRISCVXFrameLowering.cpp
├── MYRISCVXFrameLowering.h
├── MYRISCVXISelLowering.cpp
├── MYRISCVXISelLowering.h
├── MYRISCVXInstrFormats.td
├── MYRISCVXInstrInfo.cpp
├── MYRISCVXInstrInfo.h
├── MYRISCVXInstrInfo.td
├── MYRISCVXMachineFunction.cpp
├── MYRISCVXMachineFunction.h
├── MYRISCVXOther.td
├── MYRISCVXRegisterInfo.cpp
├── MYRISCVXRegisterInfo.h
├── MYRISCVXRegisterInfo.td
├── MYRISCVXSEFrameLowering.cpp
├── MYRISCVXSEFrameLowering.h
├── MYRISCVXSEISelLowering.cpp
├── MYRISCVXSEISelLowering.h
├── MYRISCVXSEInstrInfo.cpp
├── MYRISCVXSEInstrInfo.h
├── MYRISCVXSERegisterInfo.cpp
├── MYRISCVXSERegisterInfo.h
├── MYRISCVXSchedule.td
├── MYRISCVXSubtarget.cpp
├── MYRISCVXSubtarget.h
├── MYRISCVXTargetMachine.cpp
├── MYRISCVXTargetMachine.h
├── MYRISCVXTargetObjectFile.cpp
├── MYRISCVXTargetObjectFile.h
└── TargetInfo
    ├── CMakeLists.txt
    ├── LLVMBuild.txt
    └── MYRISCVXTargetInfo.cpp

TargetInfo/MYRISCVXTargetInfo.cpp

Targetを32bitと64bitの2つ登録する。どちらともリトルエンディアン。

-  extern Target TheMYRISCVXTarget;
-  extern Target TheMYRISCVXelTarget;
+  extern Target TheMYRISCVX32Target;
+  extern Target TheMYRISCVX64Target;

-Target llvm::TheMYRISCVX32Target, llvm::TheMYRISCVX64Target;
+namespace llvm {
+Target TheMYRISCVX32Target;
+Target TheMYRISCVX64Target;
+}

MYRISCVXTargetObjectFile.{h, cpp}

SmallDataSectionとBSSDataSectionを定義している。あとMYRISCVXTargetMachineオブジェクト。

SmallDataSectionのスレッショルド値は8と設定されている?

SSThreshold("MYRISCVX-ssection-threshold", cl::Hidden,
            cl::desc("Small data and bss section threshold size (default=8)"),
            cl::init(8));

Initializeにおいて、

  1. ELFの初期化 (InitializeELF())
  2. SmallSection の初期化 (.sdata) ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC
  3. SmallBSSSectionの初期化 (.sbss) ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC

MYRISCVXTargetMachine.{h, cpp}

isLittleという変数により、BigEndianとLittleEndianを判定する。

LLVMInitializeMYRISCVXTargetが定義され、BigEndian版とLittleEndian版が定義されるようだが、LittleEndianしか必要ない?というか、isLittleも必要ないのでMYRISCVXTargetMachineのみ定義することにした。

  MYRISCVXTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
                    StringRef FS, const TargetOptions &Options,
                    Optional<Reloc::Model> RM, CodeModel::Model CM,
                    CodeGenOpt::Level OL);

MYRISCVX{SE}FrameLowering.{h,cpp}

MYRISCVXのフレームを定義する。SEは32bit用という通例となっている。

とりあえず形だけ。

MYRISCVXSelILowering.{h,cpp}

LLVM IRをSelection DAGに変換する。

f:id:msyksphinz:20190131012633p:plain
MYRISCVXターゲットアーキテクチャLLVMディレクトリ構成