FPGA開発日記

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

LLVMのバックエンドを作るための第一歩 (53. RV64 / RV32両方のサポート格闘中)

f:id:msyksphinz:20190425001356p:plain

RV64の64ビットモードでLLVMアセンブラを生成できるように格闘している。とりあえずサンプルプログラムとして以下を用意した。

  • xlen64_func.cpp
#include <stdint.h>

int64_t func()
{
  return 0x100;
}

要点としては、0x100の戻り値をint64_tのデータ型で返せるか、というところだ。引数渡しのCalling Conventionまで一気にサポートすると大変なのでまずは一歩ずつ進める。

これをClangで処理してIRを出力すると以下のようなIRが作られる。

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i64 @_Z4funcv() #0 {
entry:
  ret i64 16
}

さらに、llcのSelectionDAGによって以下のようなノードが生成された。

Enabling fast-isel
Creating constant: t1: i64 = Constant<16>
Creating constant: t2: i32 = Constant<1>
Creating constant: t3: i32 = Constant<0>
Creating constant: t4: i32 = Constant<16>
Creating new node: t6: ch,glue = CopyToReg t0, Register:i32 $v0, Constant:i32<0>
Creating new node: t8: ch,glue = CopyToReg t6, Register:i32 $v1, Constant:i32<16>, t6:1
Creating new node: t9: ch = MipsISD::Ret t8, Register:i32 $v0, Register:i32 $v1, t8:1

うーん?このConstant<1>とかConstant<0>はどこで使うんだ?実際、私のMYRISCVXの実装では、Constantが処理できなくて落ちてしまう。実際、この定数<1>は不要なはずだが...

Enabling fast-isel
Creating constant: t1: i64 = Constant<16>
Creating constant: t2: i32 = Constant<1>
Creating constant: t3: i32 = Constant<0>
Creating constant: t4: i32 = Constant<16>
Return operand #1 has unhandled type i32
UNREACHABLE executed at /home/masayuki/others/llvm/llvm-myriscvx90/lib/CodeGen/CallingConvLower.cpp:130!

これはよく見てみるとMIPSでも同じような不要なノードが作成されている。何故だろう?