Draft: RISCV-NCG
This is my WIP of a RISCV NCG. Based mostly on the AArch64 NCG. The biggest issue I have with his, is that it just screams for some better refactoring, some generic RISC like superclass from which AArch64, and RV64G borrow.
- Rebased this on ghc-9.6 release branch
- Brought back the aarch64 test-suite (still needs work)
- built with
hadrian/build --build-root=_quick -j --flavour=quick+no_dynamic_ghc+llvm+native_bignum+no_profiled_libs
- test with
EXTRA_HC_OPTS='-fasm' ./hadrian/build --build-root=_quick -j --flavour=quick+no_dynamic_ghc+llvm+native_bignum+no_profiled_libs test --test-compiler=$PWD/_quick/stage1/bin/riscv64-unknown-linux-gnu-ghc --docs=none --verbose --test-way=vanilla
quite a bit is still missing, but it can compile Hello World, while linking against the LLVM compiled libraries (e.g.
$ cat <<EOF > Main.hs
main = putStrLn "Hello RiscV NCG!"
EOF
$ _quick/ghc-stage1 -fasm Main.hs
[1 of 2] Compiling Main ( Main.hs, Main.o )
[2 of 2] Linking Main
$ qemu-riscv64 Main
Hello RiscV NCG!
So what's missing (from the top of my head):
- no support for floats at all yet, code is there (aarch64), but that won't work for riscv.
- lots of misassumptions about riscv carried over from aarch64.
- Test Suite summary shows a lot of holes
SUMMARY for test run started at Sun Apr 30 13:44:57 2023 3:24:02.808092 spent to go through 9282 total tests, which gave rise to 36083 test cases, of which 27252 were skipped 7 had missing libraries 5709 expected passes 767 expected failures 15 caused framework failures 0 caused framework warnings 56 unexpected passes 2267 unexpected failures 0 unexpected stat failures 16 fragile tests
(biggest annoyance, #21292; still can't run test-suite against someas @TerrorJack has pointed out, this isEXEC_WRAPPER=qmeu-riscv64
).export CROSS_EMULATOR=qemu-riscv64
. - Linker/Relocator for riscv64-elf completely missing. The spec isn't so bad, but I think we should try to write the linker in Haskell instead of C. This likely will make it easier/faster/... the C linker is a mess. We could refactor it and try to improve, but I think Haskell would be much better here.
- Performance is abysmal. There are lots of things we could do (and some that would even benefit AArch64).
- Compressed (C) instructions might be helpful for performance. So would likely stripping unnecessary stack pointer bumps, and stupid loads. This would ideally be a post-processing phase, and one that AArch64 could also use to transform LDR/LDR into LDP (double register loads to load pair instructions; same for store). It might also allow for some instruction optimisation.
- We blow on registers, and use way way to much data moving around.
- The whole atomic situation needs to be rethought, as RISCV requires us to do some looping with acquire and conditional sets.