rust-lang / compiler-builtins

Porting `compiler-rt` intrinsics to Rust
https://github.com/rust-lang/rust/issues/35437
Other
372 stars 211 forks source link

How to deal with missing intrinsics #387

Closed jiayihu closed 4 years ago

jiayihu commented 4 years ago

I'm trying to build wasm3-rs to target thumbv7em-none-eabi and the last days have been really daunting. I think I've almost managed to do it, but I have some errors like rust-lld: error: undefined symbol: truncf left. The full list of missing symbols is:

So my question is how should I dealt with these intrinsics. ceil, ceilf, floor, floorf, trunc, truncf are already available in compiler-builtins (https://github.com/rust-lang/compiler-builtins/blob/master/src/math.rs#L82), just not enabled for my target.

I've also cloned compiler-rt and tried to compile from C, but it gives the following error:

running: "/usr/local/opt/llvm@9/bin/clang" "-O0" "-ffunction-sections" "-fdata-sections" "-g" "-fno-omit-frame-pointer" "--target=thumbv7em-none-eabi" "-fno-builtin" "-fvisibility=hidden" "-ffreestanding" "-DVISIBILITY_HIDDEN" "-o" "/Users/jiayihu/Desktop/Repo/fedra-thesis/fedra/target/thumbv7em-none-eabi/debug/build/compiler_builtins-589f534204883930/out/int_util.o" "-c" "/Users/jiayihu/Desktop/Repo/llvm-project/compiler-rt/lib/builtins/int_util.c"
  cargo:warning=/Users/jiayihu/Desktop/Repo/llvm-project/compiler-rt/lib/builtins/int_util.c:57:10: fatal error: 'stdlib.h' file not found
  cargo:warning=#include <stdlib.h>
  cargo:warning=         ^~~~~~~~~~
  cargo:warning=1 error generated.
  exit code: 1

  --- stderr

  error occurred: Command "/usr/local/opt/llvm@9/bin/clang" "-O0" "-ffunction-sections" "-fdata-sections" "-g" "-fno-omit-frame-pointer" "--target=thumbv7em-none-eabi" "-fno-builtin" "-fvisibility=hidden" "-ffreestanding" "-DVISIBILITY_HIDDEN" "-o" "/Users/jiayihu/Desktop/Repo/fedra-thesis/fedra/target/thumbv7em-none-eabi/debug/build/compiler_builtins-589f534204883930/out/int_util.o" "-c" "/Users/jiayihu/Desktop/Repo/llvm-project/compiler-rt/lib/builtins/int_util.c" with args "clang" did not execute successfully (status code exit code: 1).

I guess it's because I have to pass the flag --sysroot=/usr/local/opt/gcc-arm-none-eabi/arm-none-eabi to the compiler but build.rs doesn't support any way to do it AFAIK. I had a similar issue with bindgen, solved by using the env variable BINDGEN_EXTRA_CLANG_ARGS. Nevertheless, I didn't went further with compiler-rt because it seemed to miss several intrinsics anyway. I checked in compiler-rt/lib/builtins looking for files with the same name of the missing symbols.

The other option was compiling libc provided by gcc-arm-none-eabi, as documented here: https://github.com/rust-embedded/book/issues/255. This in turns requires providing some lib stubs and some symbols like rintf are still missing, although almost all math intrinsics are provided and optimized for the hardware, taking advantage of the FPU or SIMD for instance. Memory functions calloc/free/realloc are also implemented, although I wonder how they work since I'm currently using alloc-cortex-m and the heap is currently only needed to run wasm3-rs wrapper and not by design. I'd like to go back heapless in future.

My favourite choice so far is to cargo patch this repo and enable ceil, ceilf, floor, floorf, trunc, truncf for my target. Then I implement myself the other functions, depending also on whether I actually need them for my case and calloc, realloc, free on alloc-cortex-m.

This is my first real-world project with Rust and embedded, everything like clang, bindgen, cross-compilation is new to me and I've been learning a lot these last days "thanks" to the compile errors. I hope my ideas make sense. What would be the best direction to fix the missing symbols and hopefully end this journey?

alexcrichton commented 4 years ago

Currently math symbols are gated by target, not by feature, although that could change!

Otherwise symbols like free/calloc are not to be implemented by this crate but must be implemented by your runtime. Symbols like fpclassifyf may be coming from C code? In general if you're compiling for a *-none-* target you're largely on your own. Everyone's use case there is a little different so things generally don't work by default.

jiayihu commented 4 years ago

Yes, in the end I implemented most of the floating point operations using libm directly, free/alloc based on the heap used in alloc-cortex-m and so on. __fpclassifyf, __fpclassifyd, __aeabi_d2f came from clang however, whereas the rest were in the C code. Thanks for the help!