LLVMにはすでにRISC-Vのバックエンドサポートが追加されている。しかし、勉強のために独自のRISC-V実装をLLVMに追加している。 少しずつ進んでいるが、まだターゲットのプログラムを正しくバイナリに変換することができない。
SubtargetFeature.cppを確認してみると、このアサーションで落ちている。 確かに、Featureの文字列を設定した場所がどこにも確認できない。
lib/MC/SubtargetFeature.cpp
static inline bool hasFlag(StringRef Feature) { assert(!Feature.empty() && "Empty string"); // Get first character char Ch = Feature[0]; // Check if first character is '+' or '-' flag return Ch == '+' || Ch =='-'; }
MIPSの実装では、以下で設定がされているようだった。
lib/Target/Mips/MipsTargetMachine.cpp
MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, ... NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", isLittle, *this, Options.StackAlignmentOverride), Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16", isLittle, *this, Options.StackAlignmentOverride) { ... }
同じような実装で、RISCV(本家の実装)の場合は設定がされていない?これはなぜだろう。RISC-Vもターゲットを追加して再度ビルドして様子を見た。
RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, ... TLOF(make_unique<RISCVELFTargetObjectFile>()), Subtarget(TT, CPU, FS, *this) { initAsmInfo(); ...
ターゲットをRISC-Vとしてllcを起動すると、+64bit
と-64bit
が使われている。これはどこで登録されているんだろう?
./bin/llc -march=riscv32 -relocation-model=pic -filetype=asm ch3.riscv64.bc -o - Feature : -64bit Feature : -64bit Feature : +64bit Feature : +64bit ...
RISCV.td
に登録されている以下が気になる。
lib/Target/RISCV/RISCV.td
def RV64 : HwMode<"+64bit">; def RV32 : HwMode<"-64bit">;
$ ./bin/llc -march=myriscvx -relocation-model=pic -filetype=asm ch3.riscv64.bc -o - Feature : +myriscvx64 Feature : +myriscvx64 Feature : +myriscvx64 Feature : +myriscvx64 .text .section .mdebug.abilp64 .previous .file "ch3.cpp" Feature : +myriscvx64 Feature : +myriscvx64 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/msyksphinz/work/riscv/llvm-myriscvx64/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp:1369! Stack dump:
いろいろ調べていって、結局FeatureStringを登録するためにの方法が分かってきた。 一つは、MipsのようにSubtargetを登録する際に追加すること。
lib/Target/Mips/MipsTargetMachine.cpp
MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", isLittle, *this, Options.StackAlignmentOverride), Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16", isLittle, *this, Options.StackAlignmentOverride) { ... const MipsSubtarget * MipsTargetMachine::getSubtargetImpl(const Function &F) const { if (hasMips16Attr) FS += FS.empty() ? "+mips16" : ",+mips16"; else if (hasNoMips16Attr) FS += FS.empty() ? "-mips16" : ",-mips16"; if (HasMicroMipsAttr) FS += FS.empty() ? "+micromips" : ",+micromips"; else if (HasNoMicroMipsAttr) FS += FS.empty() ? "-micromips" : ",-micromips"; if (softFloat) FS += FS.empty() ? "+soft-float" : ",+soft-float";
もう一つは、RISC-Vのように生成された関数を使用することだ。
lib/Target/RISCV/RISCVSubtarget.cpp
RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies(StringRef CPU,
StringRef FS,
bool Is64Bit) {
...
ParseSubtargetFeatures(CPUName, FS);
...
- (ビルドディレクトリ側)
lib/Target/RISCV/RISCVGenSubtargetInfo.inc
// ParseSubtargetFeatures - Parses features string setting specified // subtarget options. void llvm::RISCVSubtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) { LLVM_DEBUG(dbgs() << "\nFeatures:" << FS); LLVM_DEBUG(dbgs() << "\nCPU:" << CPU << "\n\n"); InitMCProcessorInfo(CPU, FS); ...
lib/MC/MCSubtargetInfo.cpp
static FeatureBitset getFeatures(StringRef CPU, StringRef FS, ArrayRef<SubtargetFeatureKV> ProcDesc, ArrayRef<SubtargetFeatureKV> ProcFeatures) { SubtargetFeatures Features(FS); return Features.getFeatureBits(CPU, ProcDesc, ProcFeatures); } void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) { FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures); if (!CPU.empty()) CPUSchedModel = &getSchedModelForCPU(CPU); else CPUSchedModel = &MCSchedModel::GetDefaultSchedModel(); } ...
まずは手動でFSの文字列を追加してみた。
diff --git a/lib/Target/MYRISCVX/MYRISCVXTargetMachine.cpp b/lib/Target/MYRISCVX/MYRISCVXTargetMachine.cpp index 2f60ab55..91466345 100644 --- a/lib/Target/MYRISCVX/MYRISCVXTargetMachine.cpp +++ b/lib/Target/MYRISCVX/MYRISCVXTargetMachine.cpp @@ -97,7 +97,7 @@ MYRISCVXTargetMachine::getSubtargetImpl(const Function &F) const { ? FSAttr.getValueAsString().str() : TargetFS; - // FS += "+myriscvx64"; + FS += "+myriscvx64"; auto &I = SubtargetMap[CPU + FS]; if (!I) {
これで再度ビルドすると、Assertionのエラーは発生しなくなった。
$ ./bin/llc -march=myriscvx -relocation-model=pic -filetype=asm ch3.riscv64.bc -o - .text .section .mdebug.abilp64 .previous .file "ch3.cpp" Feature : +myriscvx64 Feature : +myriscvx64 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/msyksphinz/work/riscv/llvm-myriscvx64/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp:1369! Stack dump: ...
ただし、今度はDAGの選択に失敗する。これは単純に追加しているDAGが少ないからかな? 解析を進めていこう。