-
Notifications
You must be signed in to change notification settings - Fork 0
LLVM FAQ
This document briefly describes issues that may occur during LLVM/Clang development for RISC-V target.
To build a binary for RISC-V with linux using Clang, you need to pass it the option --target=riscv64-unknown-linux. If after that you see errors, see this section.
Example for vmerge instruction
- Generate the benchmark itself using llvm-exegesis:
./build/Release/bin/llvm-exegesis --mode=latency --mtriple=riscv64 --opcode-name=PseudoVMERGE_VVM_M1 --mcpu=sifive-p670 --benchmark-phase=assemble-measured-code -mattr="+d" --dump-object-to-disk=PseudoVMERGE_VVM_M1.o- One can disable the
-mattrflag, but then it'll require-mabi=lp64flag on the build stage
- One can disable the
- Take the following two files:
wrapper-PseudoVMERGE_VVM_M1.c:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <riscv_vector.h>
#include "arch.h"
extern void foo(void *); // PLEASE MIND THE NAME OF THIS FUNCTION
void testPseudoVMERGE_VVM_M1() {
// Storage space for generated instructions to read/write to.
char arr[128] = {0};
char *arr_addr = arr;
// Special hack, used for ld a0, 0(a0) sequences.
memcpy(arr, &arr_addr, sizeof(arr_addr));
size_t vl = __riscv_vsetvl_e8m1(16); // Required for RVV set up and can be adjusted
unsigned long start = arch_cycle(), fin;
foo(arr);
fin = arch_cycle();
#if defined(DETAILED)
printf("start: %lx\n", start);
printf("fin: %lx\n", fin);
#endif
printf("PseudoVMERGE_VVM_M1: cycles elapsed: %ld\n", fin - start);
}common1.c:
extern void testPseudoVMERGE_VVM_M1();
int main() {
testPseudoVMERGE_VVM_M1();
}- Next, compile the binary:
clang -I <paths containing arch.h and some other required headers> --target=riscv64-unknown-elf -march=rv64gcv -mabi=lp64 common1.c PseudoVMERGE_VVM_M1.o wrapper-PseudoVMERGE_VVM_M1.c -o benchmark-VMERGE.elf-
arch.hand supporting files can be found in HAL, for example, in this toolkit - If no function
foowas found inPseudoVMERGE_VVM_M1.o, disassemble it (using thellvm-objdumpfor example), and rename the function called inwrapper-PseudoVMERGE_VVM_M1.caccordingly
-
Please refer to this document. For example:
./build/Release/bin/clang --target=riscv32-unknown-linux ./test.c -O2 --gcc-toolchain=<path to gcc toolchain> --sysroot=<path to gcc toolchain>/sysroot -mcpu=syntacore-scr1-max -S -o - | ./build/Release/bin/llvm-mca -march=riscv32 -mcpu=syntacore-scr1-max
Basic pipeline is:
gdb clang++
<set breakpoint>
set follow-fork-mode child
r <additional flags> test.cppOR it is also possible to use -fintegrated-cc1 option:
gdb clang++
<set breakpoint>
r -fintegrated-cc1 <additional flags> test.cppTips:
- almost everything in LLVM has
dump()method, so it should be used as much as you can to understand what's going on - utilize the Text User Interface from GDB. To use it, simply type the
tui enable. To exit, usetui disableorCtrl+XandA(subsequently) - utilize useful LLVM/Clang command-line options:
-print-changed,-stop-after,-debug-only, etc.
Useful links:
Usually we use Ninja for speed and faster incremental rebuilds. For example:
cmake -S llvm -G Ninja -B build/Release \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_PROJECTS=clang \
cmake --build build/Release -j$(nproc)
One may encounter error for standard library headers missing when cross-compiling:
fatal error: 'iostream' file not found
1 | #include <iostream>
| ^~~~~~~~~~
1 error generated.The error means that the system doesn't see GCC cross-compiler from x86 to RISC-V (yes, even if you're using clang the GCC dependency is still there). You should either:
- Somehow install cross-compiler GCC in your system: set it in your
$PATH, OR - Download or build GCC cross-compiler from x86 to RISC-V and pass two options for clang:
-
--gcc-toolchain=<path to GCC folder>, and --sysroot=<path to GCC folder>/sysroot
So your build command will look like: ./build/bin/clang++ --target=riscv64-unknown-linux --gcc-toolchain=/home/<gcc path>/ --sysroot=<gcc path>/sysroot/ ./test.cpp
GCC folder should contain sysroot and riscv64-unknown-linux-gnu -- precompiled system libraries (for example libstdc++.so)
One may need to use llc to trigger certain pass, and then compile it to ELF format. To do so the following actions should be performed:
- Emit bitcode with clang:
./build/bin/clang --target=riscv64-unknown-linux-gnu -march=rv64g -emit-llvm -c ~/test.cpp - Use llc, but with some additional options:
./build/bin/llc -march=riscv64 -mcpu=generic-rv64 -mattr=+d -filetype=asm test.bc. Note that it is not always necessary to add these attributes. - Use clang again:
./build/bin/clang --target=riscv64-unknown-linux-gnu test.s
Note: it is possible you'll need to specify the --gcc-toolchain and --sysroot for clang in steps 1 and 3 above
GCC 13 introduced new GLIBC, which may work poorly on some of the systems. In case of such an error, try to compile with different (previous) GCC toolchain.