From ef24de24a82fe681581cc130f342363c47c0969a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 7 Jun 2024 07:48:48 +0200 Subject: Merging upstream version 1.75.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_codegen_gcc/Readme.md | 144 +++++++++++++++++++++++++++++------ 1 file changed, 120 insertions(+), 24 deletions(-) (limited to 'compiler/rustc_codegen_gcc/Readme.md') diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md index a93637d90..95fc6374c 100644 --- a/compiler/rustc_codegen_gcc/Readme.md +++ b/compiler/rustc_codegen_gcc/Readme.md @@ -1,6 +1,7 @@ # 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. @@ -14,9 +15,7 @@ A secondary goal is to check if using the gcc backend will provide any run-time ## Building **This requires a patched libgccjit in order to work. -The patches in [this repository](https://github.com/antoyo/libgccjit-patches) need to be applied. -(Those patches should work when applied on master, but in case it doesn't work, they are known to work when applied on 079c23cfe079f203d5df83fea8e92a60c7d7e878.) -You can also use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.** +You need to use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.** 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): @@ -56,18 +55,11 @@ $ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc" $ dirname $(readlink -f `find . -name libgccjit.so`) > gcc_path ``` -You also need to set RUST_COMPILER_RT_ROOT: - -```bash -$ git clone https://github.com/llvm/llvm-project llvm --depth 1 --single-branch -$ export RUST_COMPILER_RT_ROOT="$PWD/llvm/compiler-rt" -``` - Then you can run commands like this: ```bash -$ ./prepare.sh # download and patch sysroot src and install hyperfine for benchmarking -$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./build.sh --release +$ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking +$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./y.sh build --release ``` To run the tests: @@ -78,22 +70,37 @@ $ ./test.sh --release ## Usage -`$cg_gccjit_dir` is the directory you cloned this repo into in the following instructions. +`$CG_GCCJIT_DIR` is the directory you cloned this repo into in the following instructions: + +```bash +export CG_GCCJIT_DIR=[the full path to rustc_codegen_gcc] +``` ### Cargo ```bash -$ CHANNEL="release" $cg_gccjit_dir/cargo.sh run +$ CHANNEL="release" $CG_GCCJIT_DIR/cargo.sh run ``` If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./test.sh`) 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 > You should prefer using the Cargo method. ```bash -$ rustc +$(cat $cg_gccjit_dir/rust-toolchain) -Cpanic=abort -Zcodegen-backend=$cg_gccjit_dir/target/release/librustc_codegen_gcc.so --sysroot $cg_gccjit_dir/build_sysroot/sysroot my_crate.rs +$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) 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 @@ -105,8 +112,18 @@ $ rustc +$(cat $cg_gccjit_dir/rust-toolchain) -Cpanic=abort -Zcodegen-backend=$c object files when their content should have been changed by a change to cg_gccjit.
CG_GCCJIT_DISPLAY_CG_TIME
Display the time it took to perform codegen for a crate
+
CG_RUSTFLAGS
+
Send additional flags to rustc. Can be used to build the sysroot without unwinding by setting `CG_RUSTFLAGS=-Cpanic=abort`.
+
CG_GCCJIT_DUMP_TO_FILE
+
Dump a C-like representation to /tmp/gccjit_dumps and enable debug info in order to debug this C-like representation.
+## Licensing + +While this crate is licensed under a dual Apache/MIT license, it links to `libgccjit` which is under the GPLv3+ and thus, the resulting toolchain (rustc + GCC codegen) will need to be released under the GPL license. + +However, programs compiled with `rustc_codegen_gcc` do not need to be released under a GPL license. + ## Debugging Sometimes, libgccjit will crash and output an error like this: @@ -182,6 +199,61 @@ set substitute-path /usr/src/debug/gcc /path/to/gcc-repo/gcc TODO(antoyo): but that's not what I remember I was doing. +### `failed to build archive` error + +When you get this error: + +``` +error: failed to build archive: failed to open object file: No such file or directory (os error 2) +``` + +That can be caused by the fact that you try to compile with `lto = "fat"`, but you didn't compile the sysroot with LTO. +(Not sure if that's the reason since I cannot reproduce anymore. Maybe it happened when forgetting setting `FAT_LTO`.) + +### ld: cannot find crtbegin.o + +When compiling an executable with libgccijt, if setting the `*LIBRARY_PATH` variables to the install directory, you will get the following errors: + +``` +ld: cannot find crtbegin.o: No such file or directory +ld: cannot find -lgcc: No such file or directory +ld: cannot find -lgcc: No such file or directory +libgccjit.so: error: error invoking gcc driver +``` + +To fix this, set the variables to `gcc-build/build/gcc`. + +### How to debug GCC LTO + +Run do the command with `-v -save-temps` and then extract the `lto1` line from the output and run that under the debugger. + +### How to send arguments to the GCC linker + +``` +CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../cargo.sh build +``` + +### How to see the personality functions in the asm dump + +``` +CG_RUSTFLAGS="-Clink-arg=-save-temps -v -Clink-arg=-dA" ../cargo.sh build +``` + +### How to see the LLVM IR for a sysroot crate + +``` +cargo build -v --target x86_64-unknown-linux-gnu -Zbuild-std +# Take the command from the output and add --emit=llvm-ir +``` + +### To prevent the linker from unmangling symbols + +Run with: + +``` +COLLECT_NO_DEMANGLE=1 +``` + ### How to use a custom-build rustc * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). @@ -215,6 +287,16 @@ git checkout sync_branch_name git merge master ``` +To send the changes to the rust repo: + +```bash +cd ../rust +git pull origin master +git checkout -b subtree-update_cg_gcc_YYYY-MM-DD +PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master +git push +``` + TODO: write a script that does the above. https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725 @@ -223,20 +305,34 @@ https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.2 `rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`. +### How to generate GIMPLE + +If you need to check what gccjit is generating (GIMPLE), then take a look at how to +generate it in [gimple.md](./doc/gimple.md). + ### How to build a cross-compiling libgccjit #### Building libgccjit - * Follow these instructions: https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ with the following changes: - * Configure gcc with `../gcc/configure --enable-host-shared --disable-multilib --enable-languages=c,jit,c++ --disable-bootstrap --enable-checking=release --prefix=/opt/m68k-gcc/ --target=m68k-linux --without-headers`. - * Some shells, like fish, don't define the environment variable `$MACHTYPE`. - * Add `CFLAGS="-Wno-error=attributes -g -O2"` at the end of the configure command for building glibc (`CFLAGS="-Wno-error=attributes -Wno-error=array-parameter -Wno-error=stringop-overflow -Wno-error=array-bounds -g -O2"` for glibc 2.31, which is useful for Debian). + * Follow the instructions on [this repo](https://github.com/cross-cg-gcc-tools/cross-gcc). #### Configuring rustc_codegen_gcc - * Set `TARGET_TRIPLE="m68k-unknown-linux-gnu"` in config.sh. - * Since rustc doesn't support this architecture yet, set it back to `TARGET_TRIPLE="mips-unknown-linux-gnu"` (or another target having the same attributes). Alternatively, create a [target specification file](https://book.avr-rust.com/005.1-the-target-specification-json-file.html) (note that the `arch` specified in this file must be supported by the rust compiler). - * Set `linker='-Clinker=m68k-linux-gcc'`. + * Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case. * Set the path to the cross-compiling libgccjit in `gcc_path`. - * Comment the line: `context.add_command_line_option("-masm=intel");` in src/base.rs. - * (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?). + * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`. + * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target m68k-unknown-linux-gnu`. + +If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler). +Then, you can use it the following way: + + * Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json` + * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target path/to/m68k-unknown-linux-gnu.json`. + +If you get the following error: + +``` +/usr/bin/ld: unrecognised emulation mode: m68kelf +``` + +Make sure you set `gcc_path` to the install directory. -- cgit v1.2.3