Building and testing compiler-rt builtins for riscv64-unknown-elf

Hi, I’m trying to build and test the builtins part of compiler-rt for RISC-V using the following cmake cmake options:

export BUILD_C_FLAGS="--target=riscv64-unknown-elf -march=rv64gc --gcc-toolchain=$RISCV_GCC_TOOLCHAIN --sysroot=$RISCV_SYSROOT"
export TEST_C_FLAGS="$BUILD_C_FLAGS"

cmake $LLVM_SRC/compiler-rt \
  -G "Ninja" \
  -DCOMPILER_RT_OS_DIR="baremetal" \
  -DCOMPILER_RT_BUILD_BUILTINS=ON \
  -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
  -DCOMPILER_RT_BUILD_MEMPROF=OFF \
  -DCOMPILER_RT_BUILD_PROFILE=OFF \
  -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
  -DCOMPILER_RT_BUILD_XRAY=OFF \
  -DCMAKE_C_COMPILER=$LLVM_BUILD/bin/clang \
  -DCMAKE_C_COMPILER_TARGET="riscv64-unknown-elf" \
  -DCMAKE_ASM_COMPILER_TARGET="riscv64-unknown-elf" \
  -DCMAKE_AR=$LLVM_BUILD/bin/llvm-ar \
  -DCMAKE_NM=$LLVM_BUILD/bin/llvm-nm \
  -DCMAKE_RANLIB=$LLVM_BUILD/bin/llvm-ranlib \
  -DCOMPILER_RT_BAREMETAL_BUILD=ON \
  -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
  -DLLVM_CONFIG_PATH=$LLVM_BUILD/bin/llvm-config \
  -DCMAKE_C_FLAGS="$BUILD_C_FLAGS" \
  -DCMAKE_ASM_FLAGS="$BUILD_C_FLAGS" \
  -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" \
  -DCOMPILER_RT_INCLUDE_TESTS=ON \
  -DCOMPILER_RT_EMULATOR="qemu-riscv64 -L $RISCV_SYSROOT" \
  -DCOMPILER_RT_TEST_COMPILER=$LLVM_BUILD/bin/clang \
  -DCOMPILER_RT_TEST_COMPILER_CFLAGS="$TEST_C_FLAGS"

ninja builtin
ninja check-builtin

The builtin library libclang_rt.builtins-riscv64.a is successfuly built, but the tests are failed to built.

Use the test udivmodti4_test.c as an example, the command used for building and testing udivmodti4_test.c is:

clang -gline-tables-only  --target=riscv64-unknown-elf -march=rv64gc --gcc-toolchain=/path/to/gcc-toolchain/ --sysroot=/path/to/sysroot/riscv64-unknown-elf/ -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta -fno-builtin -I $LLVM_SRC/compiler-rt/lib/builtins -nodefaultlibs $LLVM_SRC/compiler-rt/test/builtins/Unit/udivmodti4_test.c /path/to/libclang_rt.builtins-riscv64.a -lc -lm -o udivmodti4_test.c.tmp && qemu-riscv64 -L $RISCV_SYSROOT udivmodti4_test.c.tmp

udivmodti4_test.c is failed to build because lots of undefined references, e.g. undefined reference to __multf3, _write …

  • riscv64-unknown-elf-ld: riscv64-unknown-elf/lib/libc.a(lib_a-svfprintf.o): in function .L244:
    vfprintf.c:(.text._svfprintf_r+0x1664): undefined reference to __multf3
  • riscv64-unknown-elf-ld: riscv64-unknown-elf/lib/libc.a(lib_a-writer.o): in function _write_r:
    writer.c:(.text._write_r+0x16): undefined reference to `_write’

libclang_rt.builtins-riscv64.a has the definition of __multf3

readelf -sW libclang_rt.builtins-riscv64.a | grep __multf3 shows:
    85: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __multf3
    40: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __multf3
    82: 0000000000000002    56 FUNC    GLOBAL HIDDEN     2 __multf3
    12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __multf3

I saw libgloss.a locates in riscv64-unknown-elf/lib/ has the symbol _write:

readelf -sW ~/opt/riscv/riscv64-unknown-elf/lib/libgloss.a | grep _write
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS sys_write.c
    11: 0000000000000000    48 FUNC    GLOBAL DEFAULT    4 _write

If I manually add -lgloss /path/to/libclang_rt.builtins-riscv64.a after -lc -lm, then udivmodti4_test.c succeeds to build:

clang -gline-tables-only  --target=riscv64-unknown-elf -march=rv64gc --gcc-toolchain=/path/to/gcc-toolchain/ --sysroot=/path/to/sysroot/riscv64-unknown-elf/ -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta -fno-builtin -I $LLVM_SRC/compiler-rt/lib/builtins -nodefaultlibs $LLVM_SRC/compiler-rt/test/builtins/Unit/udivmodti4_test.c /path/to/libclang_rt.builtins-riscv64.a -lc -lm -o udivmodti4_test.c.tmp && qemu-riscv64 -L $RISCV_SYSROOT udivmodti4_test.c.tmp

My question: is there something wrong with the above cmake options, how to solve the builtin tests build failure?
Thanks!

1 Like

I believe this is due to input ordering since you’re using GNU ld. You either need to reorder the linker inputs, wrap them in --start-group and --end-group, or use LLD.

Thanks @petrhosek for your suggestions!

-lc -lm is added by compiler-rt/test/builtins/Unit/lit.cfg.py when building udivmodti4_test.c.

So I try use lld by adding -fuse-ld=lld -lgloss to COMPILER_RT_TEST_COMPILER_CFLAGS, and most of tests passed, with 5 failed tests.

I want to known is manually adding -lgloss to COMPILER_RT_TEST_COMPILER_CFLAGS the right way to fix the undefined reference to `_write’ error ?