# WIP libgccjit codegen backend for rust [![Chat on IRC](https://img.shields.io/badge/irc.libera.chat-%23rustc__codegen__gcc-blue.svg)](https://web.libera.chat/#rustc_codegen_gcc) [![Chat on Matrix](https://img.shields.io/badge/matrix.org-%23rustc__codegen__gcc-blue.svg)](https://matrix.to/#/#rustc_codegen_gcc:matrix.org) This is a GCC codegen for rustc, which means it can be loaded by the existing rustc frontend, but benefits from GCC: more architectures are supported and GCC's optimizations are used. **Despite its name, libgccjit can be used for ahead-of-time compilation, as is used here.** ## Motivation The primary goal of this project is to be able to compile Rust code on platforms unsupported by LLVM. A secondary goal is to check if using the gcc backend will provide any run-time speed improvement for the programs compiled using rustc. ### Dependencies **rustup:** Follow the instructions on the official [website](https://www.rust-lang.org/tools/install) ## Building **This requires a patched libgccjit in order to work. You need to use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.** ```bash $ cp config.example.toml config.toml ``` If don't need to test GCC patches you wrote in our GCC fork, then the default configuration should be all you need. You can update the `rustc_codegen_gcc` without worrying about GCC. ### Building with your own GCC version If you wrote a patch for GCC and want to test it without this backend, you will need to do a few more things. To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue): ```bash $ git clone https://github.com/antoyo/gcc $ sudo apt install flex libmpfr-dev libgmp-dev libmpc3 libmpc-dev $ mkdir gcc-build gcc-install $ cd gcc-build $ ../gcc/configure \ --enable-host-shared \ --enable-languages=jit \ --enable-checking=release \ # it enables extra checks which allow to find bugs --disable-bootstrap \ --disable-multilib \ --prefix=$(pwd)/../gcc-install $ make -j4 # You can replace `4` with another number depending on how many cores you have. ``` If you want to run libgccjit tests, you will need to also enable the C++ language in the `configure`: ```bash --enable-languages=jit,c++ ``` Then to run libgccjit tests: ```bash $ cd gcc # from the `gcc-build` folder $ make check-jit # To run one specific test: $ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc" ``` **Put the path to your custom build of libgccjit in the file `config.toml`.** You now need to set the `gcc-path` value in `config.toml` with the result of this command: ```bash $ dirname $(readlink -f `find . -name libgccjit.so`) ``` and to comment the `download-gccjit` setting: ```toml gcc-path = "[MY PATH]" # download-gccjit = true ``` Then you can run commands like this: ```bash $ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking $ ./y.sh build --sysroot --release ``` To run the tests: ```bash $ ./y.sh test --release ``` ## Usage You have to run these commands, in the corresponding order: ```bash $ ./y.sh prepare $ ./y.sh build --sysroot ``` To check if all is working correctly, run: ```bash $ ./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml ``` ### Cargo ```bash $ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run ``` If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. ### LTO To use LTO, you need to set the variable `FAT_LTO=1` and `EMBED_LTO_BITCODE=1` in addition to setting `lto = "fat"` in the `Cargo.toml`. Don't set `FAT_LTO` when compiling the sysroot, though: only set `EMBED_LTO_BITCODE=1`. Failing to set `EMBED_LTO_BITCODE` will give you the following error: ``` error: failed to copy bitcode to object file: No such file or directory (os error 2) ``` ### Rustc If you want to run `rustc` directly, you can do so with: ```bash $ ./y.sh rustc my_crate.rs ``` You can do the same manually (although we don't recommend it): ```bash $ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs ``` ## Env vars