RISC-V on LLVMについて少し調べている。 LLVMのソースコードを眺めていると、TargetとしてRISC-Vが追加されているのを発見した。 なんだ、追加されてるじゃないか。じゃあ動くんじゃないか。
という訳で最新版のLLVM(ver 8.0?)とClangを落としてきて、パッチを当てずにターゲットをRISC-Vにしてビルドを試行した。
mkdir build-llvm cd build-llvm cmake -G Ninja -DCMAKE_BUILD_TYPE="Release" -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="RISCV" ../llvm cmake --build .
一応ビルドは成功したようだ。 テストプログラムを流してみる。まずは、オブジェクトを生成するだけ。
$ cat hello.c int test_int(int a, int b) { return a + b; } float test_float(float a, float b) { return a + b; }
$ ./bin/clang --target=riscv64-unknown-elf -O3 hello.c -c -o hello.o fatal error: error in backend: Cannot select: 0x7fffd2df4fb8: i64 = sign_extend_inreg 0x7fffd2df4f50, ValueType:ch:i32 0x7fffd2df4f50: i64 = add 0x7fffd2df4c78, 0x7fffd2df4ba8 0x7fffd2df4c78: i64 = AssertSext 0x7fffd2df4ad8, ValueType:ch:i32 0x7fffd2df4ad8: i64,ch = CopyFromReg 0x7fffd2d9fc78, Register:i64 %1 0x7fffd2df4a70: i64 = Register %1 0x7fffd2df4ba8: i64 = AssertSext 0x7fffd2df4a08, ValueType:ch:i32 0x7fffd2df4a08: i64,ch = CopyFromReg 0x7fffd2d9fc78, Register:i64 %0 0x7fffd2df49a0: i64 = Register %0 In function: test_int clang-8: error: clang frontend command failed with exit code 70 (use -v to see invocation) clang version 8.0.0 (https://git.llvm.org/git/clang.git/ 3919b8d9833d23d98e8be71fe608627866d5c40c) (https://git.llvm.org/git/llvm.git 20a1e3c6acad46a947e7633f39c83eb00de22ea2) Target: riscv64-unknown-unknown-elf Thread model: posix InstalledDir: /home/msyksphinz/work/riscv/llvm-build/./bin clang-8: note: diagnostic msg: PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace, preprocessed source, and associated run script. clang-8: note: diagnostic msg: ******************** PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT: Preprocessed source(s) and associated run script(s) are located at: clang-8: note: diagnostic msg: /tmp/hello-3a45a2.c clang-8: note: diagnostic msg: /tmp/hello-3a45a2.sh clang-8: note: diagnostic msg: ********************
うお、いきなり落ちた!まだきちんと対応していないのか?
と思ったら、よく考えたらまだriscv32の対応に限定されているのか。riscv32-unknown-elfでリコンパイルしてみる。
$ ./bin/clang --target=riscv32-unknown-elf -O3 hello.c -c -o hello.o $ riscv64-unknown-elf-objdump -d hello.o hello.o: file format elf32-littleriscv Disassembly of section .text: 00000000 <test_int>: 0: 00a58533 add a0,a1,a0 4: 00008067 ret 00000008 <test_float>: 8: ff010113 addi sp,sp,-16 c: 00112623 sw ra,12(sp) 10: 00000097 auipc ra,0x0 14: 000080e7 jalr ra 18: 00c12083 lw ra,12(sp) 1c: 01010113 addi sp,sp,16 20: 00008067 ret
ちゃんと生成できている。と思ったらtest_floatの方は様子が変だぞ。こんなコードで浮動小数点の加算ができるはずがない。
ちゃんと-march
を指定しなきゃだめだ。
$ ./bin/clang --target=riscv32-unknown-elf -march=rv32gc -O3 hello.c -c -o hello.o $ riscv64-unknown-elf-objdump -d hello.o hello.o: file format elf32-littleriscv Disassembly of section .text: 00000000 <test_int>: 0: 952e add a0,a0,a1 2: 8082 ret 00000004 <test_float>: 4: f0058053 fmv.w.x ft0,a1 8: f00500d3 fmv.w.x ft1,a0 c: 0000f053 fadd.s ft0,ft1,ft0 10: e0000553 fmv.x.w a0,ft0 14: 8082 ret
よく考えたらこれもおかしい。なんで整数レジスタ経由で渡しているんだ?ABIを変えてみよう。
$ ./bin/clang --target=riscv32-unknown-elf -march=rv32gc -mabi=ilp32 -O3 hello.c -c -o hello.o $ riscv64-unknown-elf-objdump -d hello.o hello.o: file format elf32-littleriscv Disassembly of section .text: 00000000 <test_int>: 0: 952e add a0,a0,a1 2: 8082 ret 00000004 <test_float>: 4: f0058053 fmv.w.x ft0,a1 8: f00500d3 fmv.w.x ft1,a0 c: 0000f053 fadd.s ft0,ft1,ft0 10: e0000553 fmv.x.w a0,ft0 14: 8082 ret
それでも直らない。float経由で引数を渡すABIはあるはずだけど...