LLVMにはすでにRISC-Vのバックエンドサポートが追加されている。しかし、勉強のために独自のRISC-V実装をLLVMに追加している。
前回までで、簡単なReturn命令は生成されるようになったが、まだ-O2オプションを付加しないとエラーが発生する。 EmitPrologueとEmitEpilogueを実装したのだが、まだ途中でスタックダンプしてしまい、正しく動作していない様だ。
とりあえず、bin/llc
を実行した際に-march=riscv64
と-march=myriscvx
でどのように挙動が変わるのかを観測した。
Legalizing node: t7: i32 = Register $a0 Ignoring node results Legally typed node: t7: i32 = Register $a0 Legalizing node: t6: i32 = Constant<4> Analyzing result type: i32 Legal result type Legally typed node: t6: i32 = Constant<4> Legalizing node: t4: i64 = undef Analyzing result type: i64 Expand integer result: t4: i64 = undef Creating new node: t10: i32 = undef Legalizing node: t10: i32 = undef Analyzing result type: i32 Legal result type Legally typed node: t10: i32 = undef Legalizing node: t2: i64 = FrameIndex<0> Analyzing result type: i64 Expand integer result: t2: i64 = FrameIndex<0> 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!
-O2でコンパイルしたものはllvm-disで逆アセンブルすると以下のようになる。
; Function Attrs: norecurse nounwind readnone define dso_local signext i32 @main() local_unnamed_addr #0 { entry: ret i32 0 }
一方で、-O2を付加しないものはllvm-disで逆アセンブルすると以下のようになる。
; Function Attrs: noinline norecurse nounwind optnone define dso_local signext i32 @main() #0 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval, align 4 ret i32 0 }
FrameIndexというNodeを変換するときに失敗する。FrameIndexについていろいろ調べてみると、どうも関数フレームを処理するためのポインタの処理を行っているらしい。しかもExpandIntegerResult
ということは値の拡張をしようとしているので、どうもそこで引っかかっている気がする。
まさかと思って、ポインタのサイズの定義を64bitから32bitに変えてみた。
diff --git a/lib/Target/MYRISCVX/MYRISCVXTargetMachine.cpp b/lib/Target/MYRISCVX/MYRISCVXTargetMachine.cpp index 1053f2428d8..0cadaed5cc5 100644 --- a/lib/Target/MYRISCVX/MYRISCVXTargetMachine.cpp +++ b/lib/Target/MYRISCVX/MYRISCVXTargetMachine.cpp @@ -36,7 +36,7 @@ static std::string computeDataLayout(const Triple &TT, StringRef CPU, std::string Ret = ""; Ret += "e"; Ret += "-m:m"; - Ret += "-p:64:64-i64:64-i128:128-n64-S128"; + Ret += "-p:32:32-i64:64-i128:128-n64-S128"; return Ret; }
これでビルドを行った。すると問題となっていた部分は通過した。やはり、32bitから64bitへの拡張ができていなかったのか。 とりあえず、32bitのアドレッシングで進めることにしよう。あとで修正する。
ただ、llcの途中でまだ固まってしまう。
1: nullptr 2: %bb.0 Found roots: %bb.0 discovered a new reachable node nullptr discovered a new reachable node %bb.0 Skipping pass 'Shrink Wrapping analysis' on function main alloc FI(0) at SP[-4]
フレームについてもう少し実装を進めてみる。
lib/Target/MYRISCVX/MYRISCVXRegisterInfo.cpp
// FrameIndex represent objects inside a abstract stack. // We must replace FrameIndex with an stack/frame pointer // direct reference. void MYRISCVXRegisterInfo:: eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const { ... // The following stack frame objects are always referenced relative to $sp: // 1. Outgoing arguments. // 2. Pointer to dynamically allocated stack space. // 3. Locations for callee-saved registers. // Everything else is referenced relative to whatever register // getFrameRegister() returns. unsigned FrameReg; FrameReg = MYRISCVX::SP; // Calculate final offset. // - There is no need to change the offset if the frame object is one of the // following: an outgoing argument, pointer to a dynamically allocated // stack space or a $gp restore location, // - If the frame object is any of the following, its offset must be adjusted // by adding the size of the stack: // incoming argument, callee-saved register location or local variable. int64_t Offset; Offset = spOffset + (int64_t)stackSize; Offset += MI.getOperand(i+1).getImm(); dbgs() << "Offset : " << Offset << "\n" << "<--------->\n"; // If MI is not a debug value, make sure Offset fits in the 16-bit immediate // field. if (!MI.isDebugValue() && !isInt<16>(Offset)) { assert("(!MI.isDebugValue() && !isInt<16>(Offset))"); } MI.getOperand(i).ChangeToRegister(FrameReg, false); MI.getOperand(i+1).ChangeToImmediate(Offset);
これで無事に命令を生成することができた。
./bin/llc -march=myriscvx -relocation-model=pic --debug -filetype=asm ch3.bc -o -
********** COMPUTING STACKMAP LIVENESS: main ********** .globl main # -- Begin function main .type main,@function .ent main # @main main: .frame $x8,8,$x1 .mask 0x00000000,0 .set noreorder .set nomacro discovered a new reachable node %bb.0 # %bb.0: # %entry addi $x2, $x2, -8 addi $x10, $x0, 0 st $x10, 4($x2) addi $x10, $x0, 4 addi $x2, $x2, 8 ret $x1 .set macro .set reorder .end main $func_end0: .size main, ($func_end0)-main # -- End function .ident "clang version 7.0.1 (https://git.llvm.org/git/clang.git/ 65f84326edb6105fb0263f0b023719b491f8cf1a) (https://github.com/msyksphinz/llvm.git 232d729230027419ef0c460c2289d5f1147e61a3)" .section ".note.GNU-stack","",@progbits