LLVMにはすでにRISC-Vのバックエンドサポートが追加されている。しかし、勉強のために独自のRISC-V実装をLLVMに追加している。 前回までで独自アーキテクチャのオプション(MYRISCVX)をllcに表示できるようになった。
実行してみると、アサーションで落ちる問題がある。
$ ./bin/llc -march=myriscvx -relocation-model=pic -filetype=asm ch3.riscv64.bcllc: /home/msyksphinz/work/riscv/llvm-myriscvx64/lib/MC/SubtargetFeature.cpp:179: static void llvm::SubtargetFeatures::ApplyFeatureFlag(llvm::FeatureBitset&, llvm::StringRef, llvm::ArrayRef<llvm::SubtargetFeatureKV>): Assertion `hasFlag(Feature)' failed. Stack dump: 0. Program arguments: ./bin/llc -march=myriscvx -relocation-model=pic -filetype=asm ch3.riscv64.bc #0 0x00007f4634d7373d llvm::sys::PrintStackTrace(llvm::raw_ostream&) /home/msyksphinz/work/riscv/llvm-myriscvx64/lib/Support/Unix/Signals.inc:490:0 #1 0x00007f4634d737d0 PrintStackTraceSignalHandler(void*) /home/msyksphinz/work/riscv/llvm-myriscvx64/lib/Support/Unix/Signals.inc:554:0 #2 0x00007f4634d7150c llvm::sys::RunSignalHandlers() /home/msyksphinz/work/riscv/llvm-myriscvx64/lib/Support/Signals.cpp:67:0
原因を調べていると、どうもFeatureの実装が問題らしい。MYRISCVXArchiFeature
には先頭に-
か+
を付けなければらならないらしい。
commit 9f7fd922439614e40d4c5efc13c44539f50ac1f0 (HEAD -> riscv_msyksphinz) Author: msyksphinz <msyksphinz_dev@gmail.com> Date: Sat Jan 12 13:36:02 2019 +0900 Bug: fix flag description diff --git a/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp b/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp index 13459c3b..b0befc56 100644 --- a/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp +++ b/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp @@ -46,7 +46,7 @@ static StringRef selectMYRISCVXArchFeature(const Triple &TT, StringRef CPU) { if (CPU.empty() || CPU == "generic") { if (TT.getArch() == Triple::myriscvx) { if (CPU.empty() || CPU == "myriscvx_impl") { - MYRISCVXArchFeature = "myriscvx64"; + MYRISCVXArchFeature = "+myriscvx64"; } } }
さらに、DAGToDAGのパスを追加する。これは、LLVM IRからターゲットのIRに変換するための処理らしい。
以下の資料を参考に実装する。
Backend structure — Tutorial: Creating an LLVM Backend for the Cpu0 Architecture
lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
let isReturn=1, isTerminator=1, hasDelaySlot=0, isBarrier=1, hasCtrlDep=1 in def RetLR : MYRISCVXPseudo<(outs), (ins), "", [(MYRISCVXRet)]>; def RET : RetBase<GPROut>;
GPROutというのは、汎用レジスタとして使用できるレジスタ群のことで、これを以下のように定義する。Cpu0ではSWを除去しているのだが、MYRISCVXでは汎用レジスタ群はすべて使用できる。
lib/Target/MYRISCVX/MYRISCVXGPROutForOther.td
//===----------------------------------------------------------------------===// // Register Classes //===----------------------------------------------------------------------===// def GPROut : RegisterClass<"MYRISCVX", [i32], 32, (add CPURegs)>;
lib/Target/MYRISCVX/MYRISCXRegisterInfo.td
//===----------------------------------------------------------------------===// //@Register Classes //===----------------------------------------------------------------------===// def CPURegs : RegisterClass<"MYRISCVX", [i32], 32, (add // Reserved ZERO, // Return Values and Arguments A0, A1, A2, A3, A4, A5, A6, A7, // Not preserved across procedure calls T0, T1, T2, T3, T4, T5, T6, // Callee save S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, // Reserved RA, SP, GP, TP )>;
これでビルドを実行してプログラムを実行してみる。
% ./bin/llc -march=myriscvx -relocation-model=pic -filetype=asm ch3.riscv64.bc Feature = +myriscvx64 Feature = +myriscvx64 ExpandIntegerResult #0: t2: i64 = FrameIndex<0> Do not know how to expand the result of this operator! UNREACHABLE executed at /home/masayuki/others/llvm/llvm-myriscvx/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp:1369! Stack dump: 0. Program arguments: ./bin/llc -march=myriscvx -relocation-model=pic -filetype=asm ch3.riscv64.bc 1. Running pass 'Function Pass Manager' on module 'ch3.riscv64.bc'. 2. Running pass 'MYRISCVX DAG->DAG Pattern Instruction Selection' on function '@main'
Assertionは落ちなくなったが、まだPassが足りないらしい。これから追加していこう。