LLVMにはすでにRISC-Vのバックエンドサポートが追加されている。しかし、勉強のために独自のRISC-V実装をLLVMに追加している。
第9章は、関数コールの実装だ。関数コールの実装は量が多すぎてまだ理解が及んでいないが、とりあえずJumpLinkの実装が難しい。
lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
/// Arithmetic Instructions (3-Operand, R-Type) def JALR : JumpFR<0b1100111, 0b000, "jalr", GPR>; // def : InstAlias<"jr $rs1", (JALR ZERO, GPR:$rs1, 0)>; def RET : RetBase<GPR>;
関数コールには基本的にJALR命令を使うことになると思うので、MYRISCVXJmpLink
を定義して、この上で命令を組み立てていくことにする。
lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
def SDT_MYRISCVXJmpLink : SDTypeProfile<0, 2, [SDTCisVT<1, iPTR>]>; ... // Call def MYRISCVXJmpLink : SDNode<"MYRISCVXISD::JmpLink",SDT_MYRISCVXJmpLink, [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>; ... def : Pat<(MYRISCVXJmpLink GPR:$rd, (i32 tglobaladdr:$dst)), (JALR GPR:$rd, tglobaladdr:$dst)>; def : Pat<(MYRISCVXJmpLink GPR:$rd, (i32 texternalsym:$dst)), (JALR GPR:$rd, texternalsym:$dst)>;
ここでテスト中に悩んでしまっているのだが、ch9_1.cpp
を実行すると以下のようにエラーが発生した。
./bin/llc -march=myriscvx32 -relocation-model=pic -filetype=asm ch9_1.bc -o -
Selecting: t48: ch = MYRISCVXISD::Ret t47, Register:i32 $a0, t47:1 Selecting: t47: ch,glue = CopyToReg t45, Register:i32 $a0, t46 Selecting: t46: i32,ch = load<(dereferenceable load 4 from %ir.a)> t45, FrameIndex:i32<1>, undef:i32 Selecting: t45: ch = store<(store 4 into %ir.a)> t43:1, t43, FrameIndex:i32<1>, undef:i32 Selecting: t43: i32,ch,glue = CopyFromReg t42, Register:i32 $a0, t42:1 Selecting: t42: ch,glue = callseq_end t41, TargetConstant:i32<24>, TargetConstant:i32<0>, t41:1 Selecting: t41: ch,glue = MYRISCVXISD::JmpLink t29, Register:i32 $gp, Register:i32 $a0, Register:i32 $a1, Register:i32 $gp, RegisterMask:Untyped, t39:1 LLVM ERROR: Cannot select: t41: ch,glue = MYRISCVXISD::JmpLink t29, Register:i32 $gp, Register:i32 $a0, Register:i32 $a1, Register:i32 $gp, RegisterMask:Untyped, t39:1 t31: i32 = Register $gp t35: i32 = Register $a0 ...
どうもMYRISCVXISD::JmpLink
の命令が作れないのか?
addi x2, x2, -8 sw x0, 4(x2) opcode = 126 Pseudo opcode found in EmitInstruction() UNREACHABLE executed at /home/masayuki/others/riscv/llvm/llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXAsmPrinter.cpp:120! Stack dump:
以下のようにスタックダンプが出て、Pseudo命令をプリントしてしまいそうな場合は、以下の生成されたファイルをチェックする。
build-myriscvx/lib/Target/MYRISCVX/MYRISCVXGenInstrInfo.inc.tmp
namespace MYRISCVX { enum { PHI = 0, ... G_BLOCK_ADDR = 125, ADJCALLSTACKDOWN = 126, ADJCALLSTACKUP = 127, CPRESTORE = 128, ...
この場合は、ADJCALLSTACKDOWN
, ADJCALLSTACKUP
が疑似命令であるので、これを削除しなければならない。このためには、eliminateCallFramePseudoInstr
を追加する。
diff --git a/lib/Target/MYRISCVX/MYRISCVXFrameLowering.cpp b/lib/Target/MYRISCVX/MYRISCVXFrameLowering.cpp index e6f64bfb642..78cdaed47d5 100644 --- a/lib/Target/MYRISCVX/MYRISCVXFrameLowering.cpp +++ b/lib/Target/MYRISCVX/MYRISCVXFrameLowering.cpp @@ -95,3 +95,11 @@ bool MYRISCVXFrameLowering::hasFP(const MachineFunction &MF) const { MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken() || TRI->needsStackRealignment(MF); } + + +// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions +MachineBasicBlock::iterator MYRISCVXFrameLowering:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + return MBB.erase(I); +} diff --git a/lib/Target/MYRISCVX/MYRISCVXFrameLowering.h b/lib/Target/MYRISCVX/MYRISCVXFrameLowering.h index 8e605a1c204..14fd90f6544 100644 --- a/lib/Target/MYRISCVX/MYRISCVXFrameLowering.h +++ b/lib/Target/MYRISCVX/MYRISCVXFrameLowering.h @@ -31,6 +31,11 @@ namespace llvm { static const MYRISCVXFrameLowering *create(const MYRISCVXSubtarget &ST); bool hasFP(const MachineFunction &MF) const override; + + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const override; }; /// Create MYRISCVXFrameLowering objects. diff --git a/lib/Target/MYRISCVX/MYRISCVXInstrInfo.cpp b/lib/Target/MYRISCVX/MYRISCVXInstrInfo.cpp index 0b7b40ec6ed..f86d5780f00 100644 --- a/lib/Target/MYRISCVX/MYRISCVXInstrInfo.cpp +++ b/lib/Target/MYRISCVX/MYRISCVXInstrInfo.cpp @@ -29,7 +29,9 @@ void MYRISCVXInstrInfo::anchor() {} //@MYRISCVXInstrInfo { MYRISCVXInstrInfo::MYRISCVXInstrInfo(const MYRISCVXSubtarget &STI) - : Subtarget(STI) {} + : + MYRISCVXGenInstrInfo(MYRISCVX::ADJCALLSTACKDOWN, MYRISCVX::ADJCALLSTACKUP), + Subtarget(STI) {} const MYRISCVXInstrInfo *MYRISCVXInstrInfo::create(MYRISCVXSubtarget &STI) { return llvm::createMYRISCVXSEInstrInfo(STI);
これでch9_1.cpp
をコンパイルして実行した。無事に命令が生成できたようだ。
./bin/clang -c -target mips ../lbdex/input/ch9_1.cpp -emit-llvm ./bin/llc -march=myriscvx32 -relocation-model=pic -filetype=asm ch9_1.bc -o -
_Z5sum_iiiiiii: .frame $x8,16,$x1 .mask 0x00000000,0 .set noreorder .cpload $t9 .set nomacro # %bb.0: # %entry lui x10, %hi(_gp_disp) addi x10, x10, %lo(_gp_disp) addi x2, x2, -16 lw x12, 36(x2) lw x12, 32(x2) lw x12, 28(x2) lw x12, 24(x2) sw x10, 12(x2) sw x11, 8(x2) lui x10, %got_hi(gI) add x10, x10, x3 lw x10, %got_lo(gI)(x10) lw x10, 0(x10) lw x11, 12(x2) add x10, x10, x11 lw x11, 8(x2) add x10, x10, x11 lw x11, 24(x2) add x10, x10, x11 lw x11, 28(x2) add x10, x10, x11 lw x11, 32(x2) add x10, x10, x11 lw x11, 36(x2) add x10, x10, x11 sw x10, 4(x2) lw x10, 4(x2) addi x1, x10, 0 addi x2, x2, 16 jalr x1 .set macro .set reorder .end _Z5sum_iiiiiii ... main: .frame $x8,32,$x1 .mask 0x00000000,0 .set noreorder .cpload $t9 .set nomacro # %bb.0: # %entry lui x10, %hi(_gp_disp) addi x10, x10, %lo(_gp_disp) addi x2, x2, -32 sw x0, 28(x2) addi x10, x0, 6 sw x10, 20(x2) addi x10, x0, 5 sw x10, 16(x2) addi x10, x0, 4 sw x10, 12(x2) addi x10, x0, 3 sw x10, 8(x2) lw x3, %call16(_Z5sum_iiiiiii)(x3) addi x10, x0, 1 addi x11, x0, 2 jalr x3 sw x10, 24(x2) lw x10, 24(x2) addi x1, x10, 0 addi x2, x2, 32 jalr x1 .set macro .set reorder .end main $func_end1: