RISC-V LLVM
About
This repository hosts a series of patches implementing a RISC-V backend for LLVM as well as initial tutorial material. For more information, see:
- September RISC-V LLVM status update
- The most recent status update to the LLVM mailing list
- The lowRISC RISC-V LLVM status page
- The initial RFC for more about the implementation approach being taken with this port.
Our intent is that development and code review primarily occurs upstream on LLVM infrastructure. However, there is value is maintaining the RISC-V backend implementation as a set of clean patches. These will be continually rebased with the intention that they provide a useful reference for anybody starting a new LLVM backend or who wants to better understand backend implementation.
Mini FAQ
Should I be compiling my code with Clang and the RISC-V LLVM backend?
If you simply want to compile your C/C++ codebase for RISC-V then for the time being, just using GCC is a simpler starting point. Once RISC-V LLVM support is included in an official LLVM release in the future and is made slightly more user friendly, the answer to this question should change.
When should I use this repository and when should I use upstream LLVM/Clang
If you find the step-by-step patch history useful for educational purposes or want to check if there are any patches that I'm preparing for upstream but haven't submitted yet, then using this repository may be worthwhile. In all other cases, and especially if you want to contribute to the effort you are strongly advised to use the upstream LLVM repositories.
How can I build upstream LLVM+Clang and use it to cross-compile for a riscv32 target?
First you will need a built RISC-V gcc toolchain. The linker, compiled libraries, and libc header files will be used. You can build your own by following the instructions at the riscv-gnu-toolchain repo. It is sufficient to do the following:
git clone --recursive https://github.com/riscv/riscv-gnu-toolchain
cd riscv-gnu-toolchain
./configure --prefix=/your/gccinstallpath --with-arch=rv32imc --with-abi=ilp32
make -j9
You can then check out upstream LLVM and Clang and build it. llvm.org has useful documentation on building LLVM with CMake, but you should find enough to get started below. Note that you will need to apply a single out-of-tree patch for riscv32-unknown-elf target support in Clang until it is reviewed and committed.
git clone https://git.llvm.org/git/llvm.git
cd llvm/tools
git clone https://git.llvm.org/git/clang.git/
cd clang
wget https://reviews.llvm.org/D46822?download=true -O baremetal.patch
patch -p0 < baremetal.patch
cd ../../
mkdir build && cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE="Debug" \
-DBUILD_SHARED_LIBS=True -DLLVM_USE_SPLIT_DWARF=True \
-DLLVM_OPTIMIZED_TABLEGEN=True \
-DLLVM_BUILD_TESTS=True \
-DDEFAULT_SYSROOT="/path/to/riscv-gcc-install-path/riscv32-unknown-elf" \
-DGCC_INSTALL_PREFIX="/path/to/riscv-gcc-install-path" \
-DLLVM_DEFAULT_TARGET_TRIPLE="riscv32-unknown-elf" \
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="RISCV" ../
cmake --build .
./bin/clang /path/to/testfile.c
A few notes on the above CMake invocation and issues you might encounter:
- It's possible to build LLVM with RISC-V support with a much simpler CMake
invocation. Ultimately you need to ensure you set
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="RISCV"
- This produces a debug build of LLVM and Clang which is significantly more useful for bug reporting if you encounter any issues. The downsides are that it will execute more slowly and compilation requires a large amount of disk space (~12G).
- Building LLVM puts a heavy load on your linker. If you have lld installed,
you may find significantly less memory is required to link if you set
-DLLVM_ENABLE_LLD=True
. Alternatively, ensure that /bin/ld is symlinked to ld.gold rather than ld.bfd. - It isn't necessary to set the default sysroot, gcc install prefix and
default target triple when building clang, but doing so means you don't need
to pass these arguments explicitly when invoking it. If you prefer, you can
explicitly pass these flags when cross-compiling:
-target riscv32-unknown-elf --sysroot=/path/to/riscv-gcc-install-path/riscv32-unknown-elf --gcc-toolchain=/path/to/riscv-gcc-install-path
- You can also compile for
riscv32-unknown-linux-elf
in conjunction with a multilib toolchain as produced by the scripts in the riscv-gnu-toolchain repository. Note that only the ilp32 ABI is supported for the moment.
Status
As of May 2018, the vast majority of these patches are now upstream and most users wishing to experiment with support for RISC-V in LLVM projects will likely be best served by building directly from the upstream repositories. You may prefer to follow this repository if you want to study how the backend is put together.
Note that the patches in this repository are over-due for another rebase. I hope to address this soon.
The current patchset allows the entirety of the GCC torture suite to compile and run for {RV32I, RV32IM, RV32IFD}. Additionally, all torture suite tests compile and run for RV64I at O1, O2, O3, and Os. MC-layer support is present for RV32IMAFDC+RV64IMAFDC, and codegen support for RV32IMFDC and RV64I. See the lowRISC RISC-V LLVM status page for more details.
Future plans
As well as the obvious implementation tasks, it is also our intent to augment this patchset with copious documentation. The initial draft of this documentation is available in this repository.
Our aim is that RISC-V is the cleanest and most documented LLVM backend. As well as benefiting the wider LLVM community, this will make it substantially easier for research groups and hobbyists to explore hardware/software co-design with RISC-V.
Our lowRISC project is working to produce a completely open source System-on-Chip implementing the RISC-V instruction set architecture. One of the features we are pursuing is tagged memory. This repository will eventually host compiler support for that feature, although this may need time to mature before being ready to upstream and so may be developed in a separate branch.
RFCs
This work has so far produced a number of request for comment (RFC) threads on the LLVM mailing list:
- [RFC] 'Review corner' section in LLVM Weekly
- RFC/bikeshedding: Separation of instruction and pattern definitions in LLVM backends
- [RFC] The future of the
va_arg
instruction - RFC: Setting MachineInstr flags through storeRegToStackSlot
- RFC: Improving the experience of first-time contributors
- [RFC] RISC-V backend
License
All patches are under the LLVM license.
The docs/ directory is under the Creative Commons CC-BY-SA 4.0 license https://creativecommons.org/licenses/by-sa/4.0/.
How to build the patchset in this repository
There are two things to note:
- This repository currently serves a dual purpose - providing a clean and constantly rebased "perfect" history of the full RISC-V patchset, as well as being a way to grab all patches in one go, including those that haven't yet been committed upstream. As more and more patches are committed upstream, this repository will become mainly interesting as a reference on how to implement an LLVM backend, and aid in understanding the RISC-V backend. If you just want to test out the latest RISC-V LLVM support, chekcing out and building upstream LLVM is probably your best choice.
- This LLVM and Clang work is not quite at a stage where end-users are likely to find it useful. However, building and trying it out is a great first step towards contributing to the development effort.
You might build LLVM and Clang with these patches applied by doing something like the below. See the LLVM documentation for more general guidance. You will need ~7GiB space for a debug build of LLVM+Clang.
export REV=326957 # Check the most recent commit on this repo to ensure this is correct
svn co http://llvm.org/svn/llvm-project/llvm/trunk@$REV llvm
cd llvm/tools
svn co http://llvm.org/svn/llvm-project/cfe/trunk@$REV clang
cd ..
for P in /path/to/riscv-llvm/*.patch; do patch -p1 < $P; done
for P in /patch/to/riscv-llvm/clang/*.patch; do patch -d tools/clang -p1 < $P; done
mkdir build
cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE="Debug" \
-DBUILD_SHARED_LIBS=True -DLLVM_USE_SPLIT_DWARF=True \
-DLLVM_OPTIMIZED_TABLEGEN=True \
-DLLVM_BUILD_TESTS=True \
-DDEFAULT_SYSROOT="/path/to/riscv-gcc-install-path/riscv32-unknown-elf" \
-DGCC_INSTALL_PREFIX="/path/to/riscv-gcc-install-path" \
-DLLVM_DEFAULT_TARGET_TRIPLE="riscv32-unknown-elf" \
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="RISCV" ../
cmake --build .
You may then want to run tests:
./bin/llvm-lit -s -i -v test/MC/RISCV # RISC-V MC-layer tests
./bin/llvm-lit -s -i -v test/CodeGen/RISCV # RISC-V CodeGen tests
./bin/llvm-lit -s -i -v test # All tests
Credits
This work has been led by Alex Bradbury at lowRISC CIC, a not for profit company. If your employer would like to see my work on RISC-V LLVM to be sustained or to accelerate, contributing sponsorship and/or development time is the best way to do that. Please contact [email protected] if you would like to discuss sponsorship, or have questions about code contributions that you can't discuss on the LLVM mailing list.
Thank you to everyone who has contributed review comments, suggestions, or code to this patchset and related support patches: Sameer Abu Asal, Chandler Carruth, Ahmed Charles, Shiva Chen, Chih-Mao Chen, Kito Cheng, David Chisnall, Simon Cook, David Craven, Hal Finkel, Eli Friedman, Ondrej Glasnak, Mandeep Singh Grang, Ben Horgan, David Kipping, James Y Knight, David Majnemer, Ed Maste, John McCall, Dylan McKay, Azharuddin Mohammed, Tim Northover, Krzysztof Parzyszek, Ana Pazos, Jordy Portman, Philip Reames, John Russo, Colin Schmidt, Ed Schouten, Pavel Å nobl, Ulrich Weigand, Mario Werner, Eugene Zalenko, Florian Zeitz, Leslie Zhai.