From 9176f51a9b67be197c5b8c9da3f5bf6eaf114f03 Mon Sep 17 00:00:00 2001 From: DonoughLiu Date: Sat, 10 Jun 2023 03:21:39 +0800 Subject: [PATCH 001/103] Support 128-bit enum variant in debuginfo codegen --- src/common.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/common.rs b/src/common.rs index bad87db4732..b62f4676f70 100644 --- a/src/common.rs +++ b/src/common.rs @@ -108,6 +108,10 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { self.const_uint(self.type_u64(), i) } + fn const_u128(&self, i: u128) -> RValue<'gcc> { + self.const_uint_big(self.type_u128(), i) + } + fn const_usize(&self, i: u64) -> RValue<'gcc> { let bit_size = self.data_layout().pointer_size.bits(); if bit_size < 64 { @@ -254,7 +258,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // SIMD builtins require a constant value. self.bitcast_if_needed(value, typ) } - + fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value { self.context.new_array_access(None, base_addr, self.const_usize(offset.bytes())).get_address(None) } From ec100514f892bcdd02780c7a2181ecc8b3cb3cd9 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Mon, 1 Aug 2022 13:51:58 -0700 Subject: [PATCH 002/103] remove box_free and replace with drop impl --- example/mini_core.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 637b8dc53fe..c27b610f2ab 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -490,7 +490,8 @@ impl, U: ?Sized, A: Allocator> CoerceUnsized> fo impl Drop for Box { fn drop(&mut self) { - // drop is currently performed by compiler. + // inner value is dropped by compiler + libc::free(self.pointer.0 as *mut u8); } } @@ -507,11 +508,6 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { libc::malloc(size) } -#[lang = "box_free"] -unsafe fn box_free(ptr: Unique, _alloc: ()) { - libc::free(ptr.pointer.0 as *mut u8); -} - #[lang = "drop"] pub trait Drop { fn drop(&mut self); From 42ecb50d56c8cbd6a3e1b1036e018bf347a9bc36 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 10 Jun 2023 12:06:17 -0400 Subject: [PATCH 003/103] Apply changes to fix python linting errors --- tools/generate_intrinsics.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 6188924b0d5..83abe145e64 100644 --- a/tools/generate_intrinsics.py +++ b/tools/generate_intrinsics.py @@ -3,7 +3,6 @@ import os import re import sys import subprocess -from os import walk def run_command(command, cwd=None): @@ -180,7 +179,7 @@ def update_intrinsics(llvm_path, llvmint, llvmint2): intrinsics[arch].sort(key=lambda x: (x[0], x[2])) out.write(' // {}\n'.format(arch)) for entry in intrinsics[arch]: - if entry[2] == True: # if it is a duplicate + if entry[2] is True: # if it is a duplicate out.write(' // [DUPLICATE]: "{}" => "{}",\n'.format(entry[0], entry[1])) elif "_round_mask" in entry[1]: out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(entry[0], entry[1])) From 38c16e9862951e3f7235c960abe0539338606e48 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 19 Jun 2023 18:51:02 -0400 Subject: [PATCH 004/103] Merge commit '1bbee3e217d75e7bc3bfe5d8c1b35e776fce96e6' into sync-cg_gcc-2023-06-19 --- .github/workflows/stdarch.yml | 32 +++- .gitignore | 2 + Readme.md | 17 +- build_sysroot/Cargo.toml | 1 + build_sysroot/prepare_sysroot_src.sh | 8 +- example/mini_core.rs | 20 ++- example/mini_core_hello_world.rs | 3 + example/std_example.rs | 1 + failing-ui-tests.txt | 6 +- patches/0023-core-Ignore-failing-tests.patch | 49 ------ rust-toolchain | 2 +- src/asm.rs | 1 - src/attributes.rs | 39 +++++ src/builder.rs | 72 ++++++--- src/consts.rs | 5 +- src/declare.rs | 2 +- src/intrinsic/archs.rs | 46 +----- src/intrinsic/llvm.rs | 7 + src/intrinsic/mod.rs | 161 +++++-------------- src/intrinsic/simd.rs | 18 ++- src/lib.rs | 2 + src/type_of.rs | 6 +- test.sh | 8 +- 23 files changed, 244 insertions(+), 264 deletions(-) delete mode 100644 patches/0023-core-Ignore-failing-tests.patch diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 42fb35e738f..556c6444833 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -20,9 +20,9 @@ jobs: matrix: libgccjit_version: - { gcc: "libgccjit.so", artifacts_branch: "master" } - commands: [ - "--test-successful-rustc --nb-parts 2 --current-part 0", - "--test-successful-rustc --nb-parts 2 --current-part 1", + cargo_runner: [ + "sde -future -rtm_mode full --", + "", ] steps: @@ -36,6 +36,20 @@ jobs: - name: Install packages run: sudo apt-get install ninja-build ripgrep + - name: Install Intel Software Development Emulator + if: ${{ matrix.cargo_runner }} + run: | + mkdir intel-sde + cd intel-sde + dir=sde-external-9.14.0-2022-10-25-lin + file=$dir.tar.xz + wget https://downloadmirror.intel.com/751535/$file + tar xvf $file + sudo mkdir /usr/share/intel-sde + sudo cp -r $dir/* /usr/share/intel-sde + sudo ln -s /usr/share/intel-sde/sde /usr/bin/sde + sudo ln -s /usr/share/intel-sde/sde64 /usr/bin/sde64 + - name: Download artifact uses: dawidd6/action-download-artifact@v2 with: @@ -91,6 +105,10 @@ jobs: ./prepare_build.sh ./build.sh --release --release-sysroot cargo test + + - name: Clean + if: ${{ !matrix.cargo_runner }} + run: | ./clean_all.sh - name: Prepare dependencies @@ -107,10 +125,18 @@ jobs: args: --release - name: Run tests + if: ${{ !matrix.cargo_runner }} run: | ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore - name: Run stdarch tests + if: ${{ !matrix.cargo_runner }} run: | cd build_sysroot/sysroot_src/library/stdarch/ CHANNEL=release TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test + + - name: Run stdarch tests + if: ${{ matrix.cargo_runner }} + run: | + cd build_sysroot/sysroot_src/library/stdarch/ + STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a diff --git a/.gitignore b/.gitignore index 12ed5667563..c5ed7de200c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ benchmarks tools/llvm-project tools/llvmint tools/llvmint-2 +# The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics. +llvm diff --git a/Readme.md b/Readme.md index bb741943892..a93637d9038 100644 --- a/Readme.md +++ b/Readme.md @@ -193,7 +193,7 @@ Using git-subtree with `rustc` requires a patched git to make it work. The PR that is needed is [here](https://github.com/gitgitgadget/git/pull/493). Use the following instructions to install it: -``` +```bash git clone git@github.com:tqc/git.git cd git git checkout tqc/subtree @@ -204,6 +204,21 @@ make cp git-subtree ~/bin ``` +Then, do a sync with this command: + +```bash +PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name +cd ../rustc_codegen_gcc +git checkout master +git pull +git checkout sync_branch_name +git merge master +``` + +TODO: write a script that does the above. + +https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725 + ### How to use [mem-trace](https://github.com/antoyo/mem-trace) `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`. diff --git a/build_sysroot/Cargo.toml b/build_sysroot/Cargo.toml index cfadf47cc3f..a84f86a8218 100644 --- a/build_sysroot/Cargo.toml +++ b/build_sysroot/Cargo.toml @@ -9,6 +9,7 @@ compiler_builtins = "0.1" alloc = { path = "./sysroot_src/library/alloc" } std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] } test = { path = "./sysroot_src/library/test" } +proc_macro = { path = "./sysroot_src/library/proc_macro" } [patch.crates-io] rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" } diff --git a/build_sysroot/prepare_sysroot_src.sh b/build_sysroot/prepare_sysroot_src.sh index 56768bbf1d0..71b3876bac2 100755 --- a/build_sysroot/prepare_sysroot_src.sh +++ b/build_sysroot/prepare_sysroot_src.sh @@ -29,10 +29,10 @@ git config user.name || git config user.name "None" git commit -m "Initial commit" -q for file in $(ls ../../patches/ | grep -v patcha); do -echo "[GIT] apply" $file -git apply ../../patches/$file -git add -A -git commit --no-gpg-sign -m "Patch $file" + echo "[GIT] apply" $file + git apply ../../patches/$file + git add -A + git commit --no-gpg-sign -m "Patch $file" done popd diff --git a/example/mini_core.rs b/example/mini_core.rs index c27b610f2ab..0cd7e6047c2 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -451,6 +451,9 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { drop_in_place(to_drop); } +#[lang = "unpin"] +pub auto trait Unpin {} + #[lang = "deref"] pub trait Deref { type Target: ?Sized; @@ -488,10 +491,23 @@ pub struct Box(Unique, A); impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} +impl Box { + pub fn new(val: T) -> Box { + unsafe { + let size = intrinsics::size_of::(); + let ptr = libc::malloc(size); + intrinsics::copy(&val as *const T as *const u8, ptr, size); + Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global) + } + } +} + impl Drop for Box { fn drop(&mut self) { - // inner value is dropped by compiler - libc::free(self.pointer.0 as *mut u8); + // inner value is dropped by compiler. + unsafe { + libc::free(self.0.pointer.0 as *mut u8); + } } } diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index cff26077740..b93d6859706 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -168,6 +168,9 @@ fn main() { world as Box; assert_eq!(intrinsics::bitreverse(0b10101000u8), 0b00010101u8); + assert_eq!(intrinsics::bitreverse(0xddccu16), 0x33bbu16); + assert_eq!(intrinsics::bitreverse(0xffee_ddccu32), 0x33bb77ffu32); + assert_eq!(intrinsics::bitreverse(0x1234_5678_ffee_ddccu64), 0x33bb77ff1e6a2c48u64); assert_eq!(intrinsics::bswap(0xabu8), 0xabu8); assert_eq!(intrinsics::bswap(0xddccu16), 0xccddu16); diff --git a/example/std_example.rs b/example/std_example.rs index 5c171c49fd1..18f2ddcde12 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -58,6 +58,7 @@ fn main() { assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26); assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7); + assert_eq!(0x1234_5678_ffee_ddcc_1234_5678_ffee_ddccu128.reverse_bits(), 0x33bb77ff1e6a2c4833bb77ff1e6a2c48u128); let _d = 0i128.checked_div(2i128); let _d = 0u128.checked_div(2u128); diff --git a/failing-ui-tests.txt b/failing-ui-tests.txt index 8539e27ea6a..801464daae9 100644 --- a/failing-ui-tests.txt +++ b/failing-ui-tests.txt @@ -54,8 +54,8 @@ tests/ui/issues/issue-40883.rs tests/ui/issues/issue-43853.rs tests/ui/issues/issue-47364.rs tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs -tests/ui/rfc-2091-track-caller/std-panic-locations.rs -tests/ui/rfcs/rfc1857-drop-order.rs +tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs +tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs tests/ui/simd/issue-89193.rs @@ -66,3 +66,5 @@ tests/ui/generator/panic-safe.rs tests/ui/issues/issue-14875.rs tests/ui/issues/issue-29948.rs tests/ui/panic-while-printing.rs +tests/ui/enum-discriminant/get_discr.rs +tests/ui/panics/nested_panic_caught.rs diff --git a/patches/0023-core-Ignore-failing-tests.patch b/patches/0023-core-Ignore-failing-tests.patch deleted file mode 100644 index ee5ba449fb8..00000000000 --- a/patches/0023-core-Ignore-failing-tests.patch +++ /dev/null @@ -1,49 +0,0 @@ -From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001 -From: bjorn3 -Date: Sun, 24 Nov 2019 15:34:06 +0100 -Subject: [PATCH] [core] Ignore failing tests - ---- - library/core/tests/iter.rs | 4 ++++ - library/core/tests/num/bignum.rs | 10 ++++++++++ - library/core/tests/num/mod.rs | 5 +++-- - library/core/tests/time.rs | 1 + - 4 files changed, 18 insertions(+), 2 deletions(-) - -diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs -index 4bc44e9..8e3c7a4 100644 ---- a/library/core/tests/array.rs -+++ b/library/core/tests/array.rs -@@ -242,6 +242,7 @@ fn iterator_drops() { - assert_eq!(i.get(), 5); - } - -+/* - // This test does not work on targets without panic=unwind support. - // To work around this problem, test is marked is should_panic, so it will - // be automagically skipped on unsuitable targets, such as -@@ -283,6 +284,7 @@ fn array_default_impl_avoids_leaks_on_panic() { - assert_eq!(COUNTER.load(Relaxed), 0); - panic!("test succeeded") - } -+*/ - - #[test] - fn empty_array_is_always_default() { -@@ -304,6 +304,7 @@ fn array_map() { - assert_eq!(b, [1, 2, 3]); - } - -+/* - // See note on above test for why `should_panic` is used. - #[test] - #[should_panic(expected = "test succeeded")] -@@ -332,6 +333,7 @@ fn array_map_drop_safety() { - assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create); - panic!("test succeeded") - } -+*/ - - #[test] - fn cell_allows_array_cycle() { --- 2.21.0 (Apple Git-122) diff --git a/rust-toolchain b/rust-toolchain index 933ecd45baa..ebb04d0069c 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-03-02" +channel = "nightly-2023-06-19" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/asm.rs b/src/asm.rs index 250aa79f8d6..4c3b7f5036c 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -518,7 +518,6 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place); } } - } } diff --git a/src/attributes.rs b/src/attributes.rs index db841b1b524..eb0cce19b85 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -2,9 +2,13 @@ use gccjit::FnAttribute; use gccjit::Function; use rustc_attr::InstructionSetAttr; +#[cfg(feature="master")] +use rustc_attr::InlineAttr; use rustc_codegen_ssa::target_features::tied_target_features; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty; +#[cfg(feature="master")] +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_session::Session; use rustc_span::symbol::sym; use smallvec::{smallvec, SmallVec}; @@ -67,6 +71,24 @@ fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { } } +/// Get GCC attribute for the provided inline heuristic. +#[cfg(feature="master")] +#[inline] +fn inline_attr<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, inline: InlineAttr) -> Option> { + match inline { + InlineAttr::Hint => Some(FnAttribute::Inline), + InlineAttr::Always => Some(FnAttribute::AlwaysInline), + InlineAttr::Never => { + if cx.sess().target.arch != "amdgpu" { + Some(FnAttribute::NoInline) + } else { + None + } + } + InlineAttr::None => None, + } +} + /// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`) /// attributes. pub fn from_fn_attrs<'gcc, 'tcx>( @@ -77,6 +99,23 @@ pub fn from_fn_attrs<'gcc, 'tcx>( ) { let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); + #[cfg(feature="master")] + { + let inline = + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) { + InlineAttr::Never + } + else if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) { + InlineAttr::Hint + } + else { + codegen_fn_attrs.inline + }; + if let Some(attr) = inline_attr(cx, inline) { + func.add_attribute(attr); + } + } + let function_features = codegen_fn_attrs.target_features.iter().map(|features| features.as_str()).collect::>(); diff --git a/src/builder.rs b/src/builder.rs index f9ea0f00456..43d0aafbd50 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -181,6 +181,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { }) .collect(); + debug_assert_eq!(casted_args.len(), args.len()); + Cow::Owned(casted_args) } @@ -207,7 +209,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let func_name = format!("{:?}", func_ptr); - let casted_args: Vec<_> = param_types + let mut casted_args: Vec<_> = param_types .into_iter() .zip(args.iter()) .enumerate() @@ -237,6 +239,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { }) .collect(); + // NOTE: to take into account variadic functions. + for i in casted_args.len()..args.len() { + casted_args.push(args[i]); + } + Cow::Owned(casted_args) } @@ -280,8 +287,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } } - fn function_ptr_call(&mut self, func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> { - let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr"); + fn function_ptr_call(&mut self, typ: Type<'gcc>, mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> { + let gcc_func = + match func_ptr.get_type().dyncast_function_ptr_type() { + Some(func) => func, + None => { + // NOTE: due to opaque pointers now being used, we need to cast here. + let new_func_type = typ.dyncast_function_ptr_type().expect("function ptr"); + func_ptr = self.context.new_cast(None, func_ptr, typ); + new_func_type + }, + }; let func_name = format!("{:?}", func_ptr); let previous_arg_count = args.len(); let orig_args = args; @@ -424,16 +440,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.llbb().end_with_void_return(None) } - fn ret(&mut self, value: RValue<'gcc>) { - let value = - if self.structs_as_pointer.borrow().contains(&value) { - // NOTE: hack to workaround a limitation of the rustc API: see comment on - // CodegenCx.structs_as_pointer - value.dereference(None).to_rvalue() - } - else { - value - }; + fn ret(&mut self, mut value: RValue<'gcc>) { + if self.structs_as_pointer.borrow().contains(&value) { + // NOTE: hack to workaround a limitation of the rustc API: see comment on + // CodegenCx.structs_as_pointer + value = value.dereference(None).to_rvalue(); + } + let expected_return_type = self.current_func().get_return_type(); + if !expected_return_type.is_compatible_with(value.get_type()) { + // NOTE: due to opaque pointers now being used, we need to cast here. + value = self.context.new_cast(None, value, expected_return_type); + } self.llbb().end_with_return(None, value); } @@ -719,17 +736,25 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { unimplemented!(); } - fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, _align: Align) -> RValue<'gcc> { + fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> { let block = self.llbb(); let function = block.get_function(); // NOTE: instead of returning the dereference here, we have to assign it to a variable in // the current basic block. Otherwise, it could be used in another basic block, causing a // dereference after a drop, for instance. - // TODO(antoyo): handle align of the load instruction. - let ptr = self.context.new_cast(None, ptr, pointee_ty.make_pointer()); + // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type. + // Ideally, we shouldn't need to do this check. + let aligned_type = + if pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type { + pointee_ty + } + else { + pointee_ty.get_aligned(align.bytes()) + }; + let ptr = self.context.new_cast(None, ptr, aligned_type.make_pointer()); let deref = ptr.dereference(None).to_rvalue(); unsafe { RETURN_VALUE_COUNT += 1 }; - let loaded_value = function.new_local(None, pointee_ty, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT })); + let loaded_value = function.new_local(None, aligned_type, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT })); block.add_assignment(None, loaded_value, deref); loaded_value.to_rvalue() } @@ -909,7 +934,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.context.new_bitcast(None, result, ptr_type) } - fn inbounds_gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> { + fn inbounds_gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> { + // NOTE: due to opaque pointers now being used, we need to cast here. + let ptr = self.context.new_cast(None, ptr, typ.make_pointer()); // NOTE: array indexing is always considered in bounds in GCC (TODO(antoyo): to be verified). let mut indices = indices.into_iter(); let index = indices.next().expect("first index in inbounds_gep"); @@ -938,6 +965,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { element.get_address(None) } else if let Some(struct_type) = value_type.is_struct() { + // NOTE: due to opaque pointers now being used, we need to bitcast here. + let ptr = self.bitcast_if_needed(ptr, value_type.make_pointer()); ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None) } else { @@ -1356,7 +1385,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn call( &mut self, - _typ: Type<'gcc>, + typ: Type<'gcc>, _fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, @@ -1370,7 +1399,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } else { // If it's a not function that was defined, it's a function pointer. - self.function_ptr_call(func, args, funclet) + self.function_ptr_call(typ, func, args, funclet) }; if let Some(_fn_abi) = fn_abi { // TODO(bjorn3): Apply function attributes @@ -1843,7 +1872,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { #[cfg(feature="master")] let (cond, element_type) = { - let then_val_vector_type = then_val.get_type().dyncast_vector().expect("vector type"); + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let then_val_vector_type = then_val.get_type().unqualified().dyncast_vector().expect("vector type"); let then_val_element_type = then_val_vector_type.get_element_type(); let then_val_element_size = then_val_element_type.get_size(); diff --git a/src/consts.rs b/src/consts.rs index 33e3b0baa92..d8a1fd315c0 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,5 +1,5 @@ #[cfg(feature = "master")] -use gccjit::FnAttribute; +use gccjit::{FnAttribute, VarAttribute, Visibility}; use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue}; use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods}; use rustc_middle::span_bug; @@ -234,7 +234,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { ); if !self.tcx.is_reachable_non_generic(def_id) { - // TODO(antoyo): set visibility. + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Visibility(Visibility::Hidden)); } global diff --git a/src/declare.rs b/src/declare.rs index 4748e7e4be2..493626c3cf5 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -132,7 +132,7 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll pub fn mangle_name(name: &str) -> String { name.replace(|char: char| { if !char.is_alphanumeric() && char != '_' { - debug_assert!("$.".contains(char), "Unsupported char in function name: {}", char); + debug_assert!("$.*".contains(char), "Unsupported char in function name {}: {}", name, char); true } else { diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 8a4559355ea..438eab78943 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -2967,10 +2967,6 @@ match name { "llvm.nvvm.clz.ll" => "__nvvm_clz_ll", "llvm.nvvm.cos.approx.f" => "__nvvm_cos_approx_f", "llvm.nvvm.cos.approx.ftz.f" => "__nvvm_cos_approx_ftz_f", - "llvm.nvvm.cp.async.ca.shared.global.16" => "__nvvm_cp_async_ca_shared_global_16", - "llvm.nvvm.cp.async.ca.shared.global.4" => "__nvvm_cp_async_ca_shared_global_4", - "llvm.nvvm.cp.async.ca.shared.global.8" => "__nvvm_cp_async_ca_shared_global_8", - "llvm.nvvm.cp.async.cg.shared.global.16" => "__nvvm_cp_async_cg_shared_global_16", "llvm.nvvm.cp.async.commit.group" => "__nvvm_cp_async_commit_group", "llvm.nvvm.cp.async.mbarrier.arrive" => "__nvvm_cp_async_mbarrier_arrive", "llvm.nvvm.cp.async.mbarrier.arrive.noinc" => "__nvvm_cp_async_mbarrier_arrive_noinc", @@ -3086,18 +3082,8 @@ match name { "llvm.nvvm.fma.rn.f16" => "__nvvm_fma_rn_f16", "llvm.nvvm.fma.rn.f16x2" => "__nvvm_fma_rn_f16x2", "llvm.nvvm.fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f", - "llvm.nvvm.fma.rn.ftz.f16" => "__nvvm_fma_rn_ftz_f16", - "llvm.nvvm.fma.rn.ftz.f16x2" => "__nvvm_fma_rn_ftz_f16x2", - "llvm.nvvm.fma.rn.ftz.relu.f16" => "__nvvm_fma_rn_ftz_relu_f16", - "llvm.nvvm.fma.rn.ftz.relu.f16x2" => "__nvvm_fma_rn_ftz_relu_f16x2", - "llvm.nvvm.fma.rn.ftz.sat.f16" => "__nvvm_fma_rn_ftz_sat_f16", - "llvm.nvvm.fma.rn.ftz.sat.f16x2" => "__nvvm_fma_rn_ftz_sat_f16x2", "llvm.nvvm.fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16", "llvm.nvvm.fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2", - "llvm.nvvm.fma.rn.relu.f16" => "__nvvm_fma_rn_relu_f16", - "llvm.nvvm.fma.rn.relu.f16x2" => "__nvvm_fma_rn_relu_f16x2", - "llvm.nvvm.fma.rn.sat.f16" => "__nvvm_fma_rn_sat_f16", - "llvm.nvvm.fma.rn.sat.f16x2" => "__nvvm_fma_rn_sat_f16x2", "llvm.nvvm.fma.rp.d" => "__nvvm_fma_rp_d", "llvm.nvvm.fma.rp.f" => "__nvvm_fma_rp_f", "llvm.nvvm.fma.rp.ftz.f" => "__nvvm_fma_rp_ftz_f", @@ -3111,32 +3097,18 @@ match name { "llvm.nvvm.fmax.f16" => "__nvvm_fmax_f16", "llvm.nvvm.fmax.f16x2" => "__nvvm_fmax_f16x2", "llvm.nvvm.fmax.ftz.f" => "__nvvm_fmax_ftz_f", - "llvm.nvvm.fmax.ftz.f16" => "__nvvm_fmax_ftz_f16", - "llvm.nvvm.fmax.ftz.f16x2" => "__nvvm_fmax_ftz_f16x2", "llvm.nvvm.fmax.ftz.nan.f" => "__nvvm_fmax_ftz_nan_f", - "llvm.nvvm.fmax.ftz.nan.f16" => "__nvvm_fmax_ftz_nan_f16", - "llvm.nvvm.fmax.ftz.nan.f16x2" => "__nvvm_fmax_ftz_nan_f16x2", "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f" => "__nvvm_fmax_ftz_nan_xorsign_abs_f", - "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16" => "__nvvm_fmax_ftz_nan_xorsign_abs_f16", - "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16x2" => "__nvvm_fmax_ftz_nan_xorsign_abs_f16x2", "llvm.nvvm.fmax.ftz.xorsign.abs.f" => "__nvvm_fmax_ftz_xorsign_abs_f", - "llvm.nvvm.fmax.ftz.xorsign.abs.f16" => "__nvvm_fmax_ftz_xorsign_abs_f16", - "llvm.nvvm.fmax.ftz.xorsign.abs.f16x2" => "__nvvm_fmax_ftz_xorsign_abs_f16x2", "llvm.nvvm.fmax.nan.bf16" => "__nvvm_fmax_nan_bf16", "llvm.nvvm.fmax.nan.bf16x2" => "__nvvm_fmax_nan_bf16x2", "llvm.nvvm.fmax.nan.f" => "__nvvm_fmax_nan_f", - "llvm.nvvm.fmax.nan.f16" => "__nvvm_fmax_nan_f16", - "llvm.nvvm.fmax.nan.f16x2" => "__nvvm_fmax_nan_f16x2", "llvm.nvvm.fmax.nan.xorsign.abs.bf16" => "__nvvm_fmax_nan_xorsign_abs_bf16", "llvm.nvvm.fmax.nan.xorsign.abs.bf16x2" => "__nvvm_fmax_nan_xorsign_abs_bf16x2", "llvm.nvvm.fmax.nan.xorsign.abs.f" => "__nvvm_fmax_nan_xorsign_abs_f", - "llvm.nvvm.fmax.nan.xorsign.abs.f16" => "__nvvm_fmax_nan_xorsign_abs_f16", - "llvm.nvvm.fmax.nan.xorsign.abs.f16x2" => "__nvvm_fmax_nan_xorsign_abs_f16x2", "llvm.nvvm.fmax.xorsign.abs.bf16" => "__nvvm_fmax_xorsign_abs_bf16", "llvm.nvvm.fmax.xorsign.abs.bf16x2" => "__nvvm_fmax_xorsign_abs_bf16x2", "llvm.nvvm.fmax.xorsign.abs.f" => "__nvvm_fmax_xorsign_abs_f", - "llvm.nvvm.fmax.xorsign.abs.f16" => "__nvvm_fmax_xorsign_abs_f16", - "llvm.nvvm.fmax.xorsign.abs.f16x2" => "__nvvm_fmax_xorsign_abs_f16x2", "llvm.nvvm.fmin.bf16" => "__nvvm_fmin_bf16", "llvm.nvvm.fmin.bf16x2" => "__nvvm_fmin_bf16x2", "llvm.nvvm.fmin.d" => "__nvvm_fmin_d", @@ -3144,32 +3116,18 @@ match name { "llvm.nvvm.fmin.f16" => "__nvvm_fmin_f16", "llvm.nvvm.fmin.f16x2" => "__nvvm_fmin_f16x2", "llvm.nvvm.fmin.ftz.f" => "__nvvm_fmin_ftz_f", - "llvm.nvvm.fmin.ftz.f16" => "__nvvm_fmin_ftz_f16", - "llvm.nvvm.fmin.ftz.f16x2" => "__nvvm_fmin_ftz_f16x2", "llvm.nvvm.fmin.ftz.nan.f" => "__nvvm_fmin_ftz_nan_f", - "llvm.nvvm.fmin.ftz.nan.f16" => "__nvvm_fmin_ftz_nan_f16", - "llvm.nvvm.fmin.ftz.nan.f16x2" => "__nvvm_fmin_ftz_nan_f16x2", "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f" => "__nvvm_fmin_ftz_nan_xorsign_abs_f", - "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16" => "__nvvm_fmin_ftz_nan_xorsign_abs_f16", - "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16x2" => "__nvvm_fmin_ftz_nan_xorsign_abs_f16x2", "llvm.nvvm.fmin.ftz.xorsign.abs.f" => "__nvvm_fmin_ftz_xorsign_abs_f", - "llvm.nvvm.fmin.ftz.xorsign.abs.f16" => "__nvvm_fmin_ftz_xorsign_abs_f16", - "llvm.nvvm.fmin.ftz.xorsign.abs.f16x2" => "__nvvm_fmin_ftz_xorsign_abs_f16x2", "llvm.nvvm.fmin.nan.bf16" => "__nvvm_fmin_nan_bf16", "llvm.nvvm.fmin.nan.bf16x2" => "__nvvm_fmin_nan_bf16x2", "llvm.nvvm.fmin.nan.f" => "__nvvm_fmin_nan_f", - "llvm.nvvm.fmin.nan.f16" => "__nvvm_fmin_nan_f16", - "llvm.nvvm.fmin.nan.f16x2" => "__nvvm_fmin_nan_f16x2", "llvm.nvvm.fmin.nan.xorsign.abs.bf16" => "__nvvm_fmin_nan_xorsign_abs_bf16", "llvm.nvvm.fmin.nan.xorsign.abs.bf16x2" => "__nvvm_fmin_nan_xorsign_abs_bf16x2", "llvm.nvvm.fmin.nan.xorsign.abs.f" => "__nvvm_fmin_nan_xorsign_abs_f", - "llvm.nvvm.fmin.nan.xorsign.abs.f16" => "__nvvm_fmin_nan_xorsign_abs_f16", - "llvm.nvvm.fmin.nan.xorsign.abs.f16x2" => "__nvvm_fmin_nan_xorsign_abs_f16x2", "llvm.nvvm.fmin.xorsign.abs.bf16" => "__nvvm_fmin_xorsign_abs_bf16", "llvm.nvvm.fmin.xorsign.abs.bf16x2" => "__nvvm_fmin_xorsign_abs_bf16x2", "llvm.nvvm.fmin.xorsign.abs.f" => "__nvvm_fmin_xorsign_abs_f", - "llvm.nvvm.fmin.xorsign.abs.f16" => "__nvvm_fmin_xorsign_abs_f16", - "llvm.nvvm.fmin.xorsign.abs.f16x2" => "__nvvm_fmin_xorsign_abs_f16x2", "llvm.nvvm.fns" => "__nvvm_fns", "llvm.nvvm.h2f" => "__nvvm_h2f", "llvm.nvvm.i2d.rm" => "__nvvm_i2d_rm", @@ -7895,6 +7853,10 @@ match name { "llvm.x86.subborrow.u64" => "__builtin_ia32_subborrow_u64", "llvm.x86.tbm.bextri.u32" => "__builtin_ia32_bextri_u32", "llvm.x86.tbm.bextri.u64" => "__builtin_ia32_bextri_u64", + "llvm.x86.tcmmimfp16ps" => "__builtin_ia32_tcmmimfp16ps", + "llvm.x86.tcmmimfp16ps.internal" => "__builtin_ia32_tcmmimfp16ps_internal", + "llvm.x86.tcmmrlfp16ps" => "__builtin_ia32_tcmmrlfp16ps", + "llvm.x86.tcmmrlfp16ps.internal" => "__builtin_ia32_tcmmrlfp16ps_internal", "llvm.x86.tdpbf16ps" => "__builtin_ia32_tdpbf16ps", "llvm.x86.tdpbf16ps.internal" => "__builtin_ia32_tdpbf16ps_internal", "llvm.x86.tdpbssd" => "__builtin_ia32_tdpbssd", diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 0edec566be3..f28348380d7 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -313,6 +313,13 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc let new_args = args.to_vec(); args = vec![new_args[1], new_args[0], new_args[2], new_args[3], new_args[4]].into(); }, + "__builtin_ia32_vpshrdv_v8di" | "__builtin_ia32_vpshrdv_v4di" | "__builtin_ia32_vpshrdv_v2di" | + "__builtin_ia32_vpshrdv_v16si" | "__builtin_ia32_vpshrdv_v8si" | "__builtin_ia32_vpshrdv_v4si" | + "__builtin_ia32_vpshrdv_v32hi" | "__builtin_ia32_vpshrdv_v16hi" | "__builtin_ia32_vpshrdv_v8hi" => { + // The first two arguments are reversed, compared to LLVM. + let new_args = args.to_vec(); + args = vec![new_args[1], new_args[0], new_args[2]].into(); + }, _ => (), } } diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 60176874747..a31fee39918 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -551,141 +551,52 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let context = &self.cx.context; let result = match width { - 8 => { + 8 | 16 | 32 | 64 => { + let mask = ((1u128 << width) - 1) as u64; + let (m0, m1, m2) = if width > 16 { + ( + context.new_rvalue_from_long(typ, (0x5555555555555555u64 & mask) as i64), + context.new_rvalue_from_long(typ, (0x3333333333333333u64 & mask) as i64), + context.new_rvalue_from_long(typ, (0x0f0f0f0f0f0f0f0fu64 & mask) as i64), + ) + } else { + ( + context.new_rvalue_from_int(typ, (0x5555u64 & mask) as i32), + context.new_rvalue_from_int(typ, (0x3333u64 & mask) as i32), + context.new_rvalue_from_int(typ, (0x0f0fu64 & mask) as i32), + ) + }; + let one = context.new_rvalue_from_int(typ, 1); + let two = context.new_rvalue_from_int(typ, 2); + let four = context.new_rvalue_from_int(typ, 4); + // First step. - let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0)); - let left = self.lshr(left, context.new_rvalue_from_int(typ, 4)); - let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F)); - let right = self.shl(right, context.new_rvalue_from_int(typ, 4)); + let left = self.lshr(value, one); + let left = self.and(left, m0); + let right = self.and(value, m0); + let right = self.shl(right, one); let step1 = self.or(left, right); // Second step. - let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC)); - let left = self.lshr(left, context.new_rvalue_from_int(typ, 2)); - let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33)); - let right = self.shl(right, context.new_rvalue_from_int(typ, 2)); + let left = self.lshr(step1, two); + let left = self.and(left, m1); + let right = self.and(step1, m1); + let right = self.shl(right, two); let step2 = self.or(left, right); // Third step. - let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA)); - let left = self.lshr(left, context.new_rvalue_from_int(typ, 1)); - let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55)); - let right = self.shl(right, context.new_rvalue_from_int(typ, 1)); - let step3 = self.or(left, right); - - step3 - }, - 16 => { - // First step. - let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 1)); - let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 1)); - let step1 = self.or(left, right); - - // Second step. - let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 2)); - let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 2)); - let step2 = self.or(left, right); - - // Third step. - let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 4)); - let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 4)); + let left = self.lshr(step2, four); + let left = self.and(left, m2); + let right = self.and(step2, m2); + let right = self.shl(right, four); let step3 = self.or(left, right); // Fourth step. - let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 8)); - let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 8)); - let step4 = self.or(left, right); - - step4 - }, - 32 => { - // TODO(antoyo): Refactor with other implementations. - // First step. - let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 1)); - let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 1)); - let step1 = self.or(left, right); - - // Second step. - let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 2)); - let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 2)); - let step2 = self.or(left, right); - - // Third step. - let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 4)); - let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 4)); - let step3 = self.or(left, right); - - // Fourth step. - let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 8)); - let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 8)); - let step4 = self.or(left, right); - - // Fifth step. - let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 16)); - let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 16)); - let step5 = self.or(left, right); - - step5 - }, - 64 => { - // First step. - let left = self.shl(value, context.new_rvalue_from_long(typ, 32)); - let right = self.lshr(value, context.new_rvalue_from_long(typ, 32)); - let step1 = self.or(left, right); - - // Second step. - let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 15)); - let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead? - let right = self.lshr(right, context.new_rvalue_from_long(typ, 17)); - let step2 = self.or(left, right); - - // Third step. - let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10)); - let left = self.xor(step2, left); - let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F)); - - let left = self.shl(temp, context.new_rvalue_from_long(typ, 10)); - let left = self.or(temp, left); - let step3 = self.xor(left, step2); - - // Fourth step. - let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4)); - let left = self.xor(step3, left); - let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421)); - - let left = self.shl(temp, context.new_rvalue_from_long(typ, 4)); - let left = self.or(temp, left); - let step4 = self.xor(left, step3); - - // Fifth step. - let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2)); - let left = self.xor(step4, left); - let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842)); - - let left = self.shl(temp, context.new_rvalue_from_long(typ, 2)); - let left = self.or(temp, left); - let step5 = self.xor(left, step4); - - step5 + if width == 8 { + step3 + } else { + self.gcc_bswap(step3, width) + } }, 128 => { // TODO(antoyo): find a more efficient implementation? diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index b59c3a64f57..9115cf97119 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -165,10 +165,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty } ); + let arg1 = args[0].immediate(); + // NOTE: we get different vector types for the same vector type and libgccjit doesn't + // compare them as equal, so bitcast. + // FIXME(antoyo): allow comparing vector types as equal in libgccjit. + let arg2 = bx.context.new_bitcast(None, args[1].immediate(), arg1.get_type()); return Ok(compare_simd_types( bx, - args[0].immediate(), - args[1].immediate(), + arg1, + arg2, in_elem, llret_ty, cmp_op, @@ -341,7 +346,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // endian and MSB-first for big endian. let vector = args[0].immediate(); - let vector_type = vector.get_type().dyncast_vector().expect("vector type"); + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let vector_type = vector.get_type().unqualified().dyncast_vector().expect("vector type"); let elem_type = vector_type.get_element_type(); let expected_int_bits = in_len.max(8); @@ -848,7 +854,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( (true, true) => { // Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition // TODO(antoyo): improve using conditional operators if possible. - let arg_type = lhs.get_type(); + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let arg_type = lhs.get_type().unqualified(); // TODO(antoyo): convert lhs and rhs to unsigned. let sum = lhs + rhs; let vector_type = arg_type.dyncast_vector().expect("vector type"); @@ -878,7 +885,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( res & cmp }, (true, false) => { - let arg_type = lhs.get_type(); + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let arg_type = lhs.get_type().unqualified(); // TODO(antoyo): this uses the same algorithm from saturating add, but add the // negative of the right operand. Find a proper subtraction algorithm. let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); diff --git a/src/lib.rs b/src/lib.rs index ea013c4428c..2a6b642782d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,6 +111,8 @@ impl CodegenBackend for GccCodegenBackend { } fn init(&self, sess: &Session) { + #[cfg(feature="master")] + gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); if sess.lto() != Lto::No { sess.emit_warning(LTONotSupported {}); } diff --git a/src/type_of.rs b/src/type_of.rs index 30a3fe67b85..74f016cf90a 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -383,8 +383,8 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { unimplemented!(); } - fn fn_decl_backend_type(&self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> { - // FIXME(antoyo): return correct type. - self.type_void() + fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> { + let (return_type, param_types, variadic, _) = fn_abi.gcc_type(self); + self.context.new_function_pointer_type(None, return_type, ¶m_types, variadic) } } diff --git a/test.sh b/test.sh index 6139892aefc..592997b8ab9 100755 --- a/test.sh +++ b/test.sh @@ -214,12 +214,14 @@ function setup_rustc() { rm config.toml || true cat > config.toml < Date: Mon, 19 Jun 2023 20:44:01 -0400 Subject: [PATCH 005/103] Update Cargo.lock --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f2e152f8ce..1c8754bf675 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,7 +35,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3" +source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984" dependencies = [ "gccjit_sys", ] @@ -43,7 +43,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3" +source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984" dependencies = [ "libc", ] From afc6489394abd238fcfbe2c39ca35c4ce3e84234 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 30 Jun 2023 17:11:09 +0200 Subject: [PATCH 006/103] Add support for cold attribute --- src/attributes.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/attributes.rs b/src/attributes.rs index eb0cce19b85..fbafc981f66 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -114,6 +114,10 @@ pub fn from_fn_attrs<'gcc, 'tcx>( if let Some(attr) = inline_attr(cx, inline) { func.add_attribute(attr); } + + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { + func.add_attribute(FnAttribute::Cold); + } } let function_features = From 5920bad104dd842a8b036a7f32c0ae5cf7737496 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 3 Jul 2023 16:56:34 +0200 Subject: [PATCH 007/103] Update dependencies --- Cargo.lock | 272 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 172 insertions(+), 100 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c5357eec10..92cb25b7d0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,25 +4,67 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.18" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fm" version = "0.1.4" @@ -35,7 +77,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984" +source = "git+https://github.com/antoyo/gccjit.rs#2f6b60543d0f72003a2d19430d446dae27b06753" dependencies = [ "gccjit_sys", ] @@ -43,7 +85,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984" +source = "git+https://github.com/antoyo/gccjit.rs#2f6b60543d0f72003a2d19430d446dae27b06753" dependencies = [ "libc", ] @@ -58,23 +100,29 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.2.3" +name = "hermit-abi" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", - "libc", - "wasi", ] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "io-lifetimes" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ + "hermit-abi", "libc", + "windows-sys", ] [[package]] @@ -95,86 +143,46 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.112" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] -[[package]] -name = "ppv-lite86" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" - -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "aho-corasick", "memchr", @@ -183,18 +191,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "rustc_codegen_gcc" @@ -206,6 +205,20 @@ dependencies = [ "tempfile", ] +[[package]] +name = "rustix" +version = "0.37.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8818fa822adcc98b18fedbb3632a6a33213c070556b5aa7c4c8cc21cff565c4c" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "same-file" version = "1.0.6" @@ -217,29 +230,29 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "tempfile" -version = "3.2.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ + "autocfg", "cfg-if", - "libc", - "rand", + "fastrand", "redox_syscall", - "remove_dir_all", - "winapi", + "rustix", + "windows-sys", ] [[package]] name = "termcolor" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -255,9 +268,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "wait-timeout" @@ -270,21 +283,14 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", - "winapi", "winapi-util", ] -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - [[package]] name = "winapi" version = "0.3.9" @@ -315,3 +321,69 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" From d710bee436e72ce3f4a5800b81e2b259f5f2098e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 5 Jul 2023 17:39:40 +1000 Subject: [PATCH 008/103] Narrow trait `CoverageInfoBuilderMethods` down to just one method This effectively inlines most of `FunctionCx::codegen_coverage` into the LLVM implementation of `CoverageInfoBuilderMethods`. --- src/coverageinfo.rs | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/src/coverageinfo.rs b/src/coverageinfo.rs index 872fc2472e2..41fc096131b 100644 --- a/src/coverageinfo.rs +++ b/src/coverageinfo.rs @@ -1,40 +1,15 @@ use gccjit::RValue; use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods}; use rustc_hir::def_id::DefId; -use rustc_middle::mir::coverage::{ - CodeRegion, - CounterValueReference, - ExpressionOperandId, - InjectedExpressionId, - Op, -}; +use rustc_middle::mir::Coverage; use rustc_middle::ty::Instance; use crate::builder::Builder; use crate::context::CodegenCx; impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { - fn set_function_source_hash( - &mut self, - _instance: Instance<'tcx>, - _function_source_hash: u64, - ) -> bool { - unimplemented!(); - } - - fn add_coverage_counter(&mut self, _instance: Instance<'tcx>, _id: CounterValueReference, _region: CodeRegion) -> bool { + fn add_coverage(&mut self, _instance: Instance<'tcx>, _coverage: &Coverage) { // TODO(antoyo) - false - } - - fn add_coverage_counter_expression(&mut self, _instance: Instance<'tcx>, _id: InjectedExpressionId, _lhs: ExpressionOperandId, _op: Op, _rhs: ExpressionOperandId, _region: Option) -> bool { - // TODO(antoyo) - false - } - - fn add_coverage_unreachable(&mut self, _instance: Instance<'tcx>, _region: CodeRegion) -> bool { - // TODO(antoyo) - false } } From 744d05ccb6dc7a9531bce5fb33ed9952f3032ec4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 5 Jul 2023 17:56:10 +1000 Subject: [PATCH 009/103] Remove trait `CoverageInfoMethods`, since non-LLVM backends don't need it These methods are only ever called from within `rustc_codegen_llvm`, so they can just be declared there as well. --- src/coverageinfo.rs | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/src/coverageinfo.rs b/src/coverageinfo.rs index 41fc096131b..849e9886ef3 100644 --- a/src/coverageinfo.rs +++ b/src/coverageinfo.rs @@ -1,44 +1,11 @@ -use gccjit::RValue; -use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods}; -use rustc_hir::def_id::DefId; +use rustc_codegen_ssa::traits::CoverageInfoBuilderMethods; use rustc_middle::mir::Coverage; use rustc_middle::ty::Instance; use crate::builder::Builder; -use crate::context::CodegenCx; impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { fn add_coverage(&mut self, _instance: Instance<'tcx>, _coverage: &Coverage) { // TODO(antoyo) } } - -impl<'gcc, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { - fn coverageinfo_finalize(&self) { - // TODO(antoyo) - } - - fn get_pgo_func_name_var(&self, _instance: Instance<'tcx>) -> RValue<'gcc> { - unimplemented!(); - } - - /// Functions with MIR-based coverage are normally codegenned _only_ if - /// called. LLVM coverage tools typically expect every function to be - /// defined (even if unused), with at least one call to LLVM intrinsic - /// `instrprof.increment`. - /// - /// Codegen a small function that will never be called, with one counter - /// that will never be incremented. - /// - /// For used/called functions, the coverageinfo was already added to the - /// `function_coverage_map` (keyed by function `Instance`) during codegen. - /// But in this case, since the unused function was _not_ previously - /// codegenned, collect the coverage `CodeRegion`s from the MIR and add - /// them. The first `CodeRegion` is used to add a single counter, with the - /// same counter ID used in the injected `instrprof.increment` intrinsic - /// call. Since the function is never called, all other `CodeRegion`s can be - /// added as `unreachable_region`s. - fn define_unused_fn(&self, _def_id: DefId) { - unimplemented!(); - } -} From 91e04000eab437a791d0b7e1fe19c2a2b2234281 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 4 Jul 2023 21:04:15 -0400 Subject: [PATCH 010/103] Add support for detecting CPU features --- Cargo.lock | 4 ++-- Readme.md | 4 +--- failing-ui-tests.txt | 1 - src/base.rs | 51 ++++++++++++++++++++++++++------------------ src/lib.rs | 42 +++++++++++++++--------------------- 5 files changed, 50 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92cb25b7d0b..2800dc6ccd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,7 +77,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#2f6b60543d0f72003a2d19430d446dae27b06753" +source = "git+https://github.com/antoyo/gccjit.rs#79c8bb49ff09b7f40a04055203a5f3894a266210" dependencies = [ "gccjit_sys", ] @@ -85,7 +85,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#2f6b60543d0f72003a2d19430d446dae27b06753" +source = "git+https://github.com/antoyo/gccjit.rs#79c8bb49ff09b7f40a04055203a5f3894a266210" dependencies = [ "libc", ] diff --git a/Readme.md b/Readme.md index a93637d9038..c58662b9ce5 100644 --- a/Readme.md +++ b/Readme.md @@ -14,9 +14,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): diff --git a/failing-ui-tests.txt b/failing-ui-tests.txt index 801464daae9..69f57036b01 100644 --- a/failing-ui-tests.txt +++ b/failing-ui-tests.txt @@ -21,7 +21,6 @@ tests/ui/sepcomp/sepcomp-fns-backwards.rs tests/ui/sepcomp/sepcomp-fns.rs tests/ui/sepcomp/sepcomp-statics.rs tests/ui/simd/intrinsic/generic-arithmetic-pass.rs -tests/ui/sse2.rs tests/ui/target-feature/missing-plusminus.rs tests/ui/asm/x86_64/may_unwind.rs tests/ui/backtrace.rs diff --git a/src/base.rs b/src/base.rs index dcd560b3dcd..82669aa99cf 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,10 +1,12 @@ +use std::collections::HashSet; use std::env; +use std::sync::Arc; use std::time::Instant; use gccjit::{ Context, FunctionType, - GlobalKind, + GlobalKind, TargetInfo, }; use rustc_middle::dep_graph; use rustc_middle::ty::TyCtxt; @@ -63,7 +65,7 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { } } -pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_integers: bool) -> (ModuleCodegen, u64) { +pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc) -> (ModuleCodegen, u64) { let prof_timer = tcx.prof.generic_activity("codegen_module"); let start_time = Instant::now(); @@ -71,7 +73,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i let (module, _) = tcx.dep_graph.with_task( dep_node, tcx, - (cgu_name, supports_128bit_integers), + (cgu_name, target_info), module_codegen, Some(dep_graph::hash_result), ); @@ -82,7 +84,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i // the time we needed for codegenning it. let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64; - fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, supports_128bit_integers): (Symbol, bool)) -> ModuleCodegen { + fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, Arc)) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... //let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str()); @@ -91,29 +93,36 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i context.add_command_line_option("-fexceptions"); context.add_driver_option("-fexceptions"); + let disabled_features: HashSet<_> = tcx.sess.opts.cg.target_feature.split(',') + .filter(|feature| feature.starts_with('-')) + .map(|string| &string[1..]) + .collect(); + + let add_cpu_feature_flag = |feature: &str| { + // FIXME(antoyo): some tests cause a segfault in GCC when not enabling all these + // features. + if (true || target_info.cpu_supports(feature)) && !disabled_features.contains(feature) { + context.add_command_line_option(&format!("-m{}", feature)); + } + }; + // TODO(antoyo): only set on x86 platforms. context.add_command_line_option("-masm=intel"); - // TODO(antoyo): only add the following cli argument if the feature is supported. - context.add_command_line_option("-msse2"); - context.add_command_line_option("-mavx2"); - // FIXME(antoyo): the following causes an illegal instruction on vmovdqu64 in std_example on my CPU. - // Only add if the CPU supports it. - context.add_command_line_option("-msha"); + + let features = ["sse2", "avx", "avx2", "sha", "fma", "gfni", "f16c", "aes", "bmi2", "rtm", + "vaes", "vpclmulqdq", "xsavec", + ]; + + for feature in &features { + add_cpu_feature_flag(feature); + } + + // TODO(antoyo): only add the following cli arguments if the feature is supported. context.add_command_line_option("-mpclmul"); - context.add_command_line_option("-mfma"); context.add_command_line_option("-mfma4"); context.add_command_line_option("-m64"); context.add_command_line_option("-mbmi"); - context.add_command_line_option("-mgfni"); //context.add_command_line_option("-mavxvnni"); // The CI doesn't support this option. - context.add_command_line_option("-mf16c"); - context.add_command_line_option("-maes"); - context.add_command_line_option("-mxsavec"); - context.add_command_line_option("-mbmi2"); - context.add_command_line_option("-mrtm"); - context.add_command_line_option("-mvaes"); - context.add_command_line_option("-mvpclmulqdq"); - context.add_command_line_option("-mavx"); for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); @@ -156,7 +165,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i context.set_allow_unreachable_blocks(true); { - let cx = CodegenCx::new(&context, cgu, tcx, supports_128bit_integers); + let cx = CodegenCx::new(&context, cgu, tcx, target_info.supports_128bit_int()); let mono_items = cgu.items_in_deterministic_order(tcx); for &(mono_item, (linkage, visibility)) in &mono_items { diff --git a/src/lib.rs b/src/lib.rs index 2a6b642782d..4e9c2f91be5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,7 +35,6 @@ extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; -extern crate tempfile; // This prevents duplicating functions and statics that are already part of the host rustc process. #[allow(unused_extern_crates)] @@ -64,10 +63,10 @@ mod type_; mod type_of; use std::any::Any; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use crate::errors::LTONotSupported; -use gccjit::{Context, OptimizationLevel, CType}; +use gccjit::{Context, OptimizationLevel, TargetInfo}; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; use rustc_codegen_ssa::base::codegen_crate; @@ -86,7 +85,6 @@ use rustc_session::config::{Lto, OptLevel, OutputFilenames}; use rustc_session::Session; use rustc_span::Symbol; use rustc_span::fatal_error::FatalError; -use tempfile::TempDir; fluent_messages! { "../messages.ftl" } @@ -102,7 +100,7 @@ impl String> Drop for PrintOnPanic { #[derive(Clone)] pub struct GccCodegenBackend { - supports_128bit_integers: Arc>, + target_info: Arc, } impl CodegenBackend for GccCodegenBackend { @@ -116,15 +114,6 @@ impl CodegenBackend for GccCodegenBackend { if sess.lto() != Lto::No { sess.emit_warning(LTONotSupported {}); } - - let temp_dir = TempDir::new().expect("cannot create temporary directory"); - let temp_file = temp_dir.into_path().join("result.asm"); - let check_context = Context::default(); - check_context.set_print_errors_to_stderr(false); - let _int128_ty = check_context.new_c_type(CType::UInt128t); - // NOTE: we cannot just call compile() as this would require other files than libgccjit.so. - check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str")); - *self.supports_128bit_integers.lock().expect("lock") = check_context.get_last_error() == Ok(None); } fn provide(&self, providers: &mut Providers) { @@ -160,7 +149,7 @@ impl CodegenBackend for GccCodegenBackend { } fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec { - target_features(sess, allow_unstable) + target_features(sess, allow_unstable, &self.target_info) } } @@ -174,7 +163,7 @@ impl ExtraBackendMethods for GccCodegenBackend { } fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen, u64) { - base::compile_codegen_unit(tcx, cgu_name, *self.supports_128bit_integers.lock().expect("lock")) + base::compile_codegen_unit(tcx, cgu_name, Arc::clone(&self.target_info)) } fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel, _features: &[String]) -> TargetMachineFactoryFn { @@ -273,8 +262,17 @@ impl WriteBackendMethods for GccCodegenBackend { /// This is the entrypoint for a hot plugged rustc_codegen_gccjit #[no_mangle] pub fn __rustc_codegen_backend() -> Box { + // Get the native arch and check whether the target supports 128-bit integers. + let context = Context::default(); + let arch = context.get_target_info().arch().unwrap(); + + // Get the second TargetInfo with the correct CPU features by setting the arch. + let context = Context::default(); + context.add_driver_option(&format!("-march={}", arch.to_str().unwrap())); + let target_info = Arc::new(context.get_target_info()); + Box::new(GccCodegenBackend { - supports_128bit_integers: Arc::new(Mutex::new(false)), + target_info, }) } @@ -308,7 +306,7 @@ pub fn target_cpu(sess: &Session) -> &str { } } -pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { +pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &Arc) -> Vec { supported_target_features(sess) .iter() .filter_map( @@ -317,14 +315,9 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { }, ) .filter(|_feature| { - // TODO(antoyo): implement a way to get enabled feature in libgccjit. - // Probably using the equivalent of __builtin_cpu_supports. - // TODO(antoyo): maybe use whatever outputs the following command: - // gcc -march=native -Q --help=target #[cfg(feature="master")] { - // NOTE: the CPU in the CI doesn't support sse4a, so disable it to make the stdarch tests pass in the CI. - (_feature.contains("sse") || _feature.contains("avx")) && !_feature.contains("avx512") && !_feature.contains("sse4a") + target_info.cpu_supports(_feature) } #[cfg(not(feature="master"))] { @@ -336,7 +329,6 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves */ - //false }) .map(|feature| Symbol::intern(feature)) .collect() From 761324d1df55c2a046cc0e3e0f3adeb96dac1238 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 5 Jul 2023 20:13:26 +0100 Subject: [PATCH 011/103] Move `TyCtxt::mk_x` to `Ty::new_x` where applicable --- src/intrinsic/mod.rs | 10 +++++----- src/type_of.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index a31fee39918..0b208be4e62 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -1147,19 +1147,19 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut // Define the type up front for the signature of the rust_try function. let tcx = cx.tcx; - let i8p = tcx.mk_mut_ptr(tcx.types.i8); + let i8p = Ty::new_mut_ptr(tcx,tcx.types.i8); // `unsafe fn(*mut i8) -> ()` - let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( + let try_fn_ty = Ty::new_fn_ptr(tcx,ty::Binder::dummy(tcx.mk_fn_sig( iter::once(i8p), - tcx.mk_unit(), + Ty::new_unit(tcx,), false, rustc_hir::Unsafety::Unsafe, Abi::Rust, ))); // `unsafe fn(*mut i8, *mut i8) -> ()` - let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( + let catch_fn_ty = Ty::new_fn_ptr(tcx,ty::Binder::dummy(tcx.mk_fn_sig( [i8p, i8p].iter().cloned(), - tcx.mk_unit(), + Ty::new_unit(tcx,), false, rustc_hir::Unsafety::Unsafe, Abi::Rust, diff --git a/src/type_of.rs b/src/type_of.rs index 74f016cf90a..e0823888f67 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -283,7 +283,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // only wide pointer boxes are handled as pointers // thin pointer boxes with scalar allocators are handled by the general logic below ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => { - let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty()); + let ptr_ty = Ty::new_mut_ptr(cx.tcx,self.ty.boxed_ty()); return cx.layout_of(ptr_ty).scalar_pair_element_gcc_type(cx, index, immediate); } _ => {} From e1092eb4d123f568f2f51c8ff4da54d7be89dc0c Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 6 Jul 2023 17:44:15 -0400 Subject: [PATCH 012/103] Add license explanations --- Readme.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Readme.md b/Readme.md index c58662b9ce5..e05f8dae1c6 100644 --- a/Readme.md +++ b/Readme.md @@ -105,6 +105,12 @@ $ rustc +$(cat $cg_gccjit_dir/rust-toolchain) -Cpanic=abort -Zcodegen-backend=$c
Display the time it took to perform codegen for a crate
+## 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: From 97a0d35a8c21b8aeed474a5fa856e89c1feeb5fb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 6 Jul 2023 16:54:50 +0200 Subject: [PATCH 013/103] Add support for "returns_twice" function attribute --- src/attributes.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/attributes.rs b/src/attributes.rs index fbafc981f66..0fda9e7ae50 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -118,6 +118,9 @@ pub fn from_fn_attrs<'gcc, 'tcx>( if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { func.add_attribute(FnAttribute::Cold); } + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) { + func.add_attribute(FnAttribute::ReturnsTwice); + } } let function_features = From a6d1aa28101ca14c07aaf367b41cc4a13aaad82e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 12 Jul 2023 16:46:16 +0200 Subject: [PATCH 014/103] Update gccjit dependency --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2800dc6ccd1..3062b191f35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,7 +77,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#79c8bb49ff09b7f40a04055203a5f3894a266210" +source = "git+https://github.com/antoyo/gccjit.rs#78ed1a380eb276e7443645a41b0e87222f291e82" dependencies = [ "gccjit_sys", ] @@ -85,7 +85,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#79c8bb49ff09b7f40a04055203a5f3894a266210" +source = "git+https://github.com/antoyo/gccjit.rs#78ed1a380eb276e7443645a41b0e87222f291e82" dependencies = [ "libc", ] From c04a631ea651c76504f281994984f75971353735 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 13 Jul 2023 21:43:12 +0200 Subject: [PATCH 015/103] Add support for "pure" function attribute --- src/attributes.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/attributes.rs b/src/attributes.rs index 0fda9e7ae50..6195de912d2 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -121,6 +121,9 @@ pub fn from_fn_attrs<'gcc, 'tcx>( if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) { func.add_attribute(FnAttribute::ReturnsTwice); } + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { + func.add_attribute(FnAttribute::Pure); + } } let function_features = From d873fa73828c2b97f5bc432bedbcf55a65dccf4f Mon Sep 17 00:00:00 2001 From: Mahdi Dibaiee Date: Tue, 11 Jul 2023 22:35:29 +0100 Subject: [PATCH 016/103] refactor(rustc_middle): Substs -> GenericArg --- src/callee.rs | 6 +++--- src/intrinsic/mod.rs | 8 ++++---- src/mono_item.rs | 2 +- src/type_of.rs | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/callee.rs b/src/callee.rs index 433b2585f82..a96bd66ba79 100644 --- a/src/callee.rs +++ b/src/callee.rs @@ -17,8 +17,8 @@ use crate::context::CodegenCx; pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> Function<'gcc> { let tcx = cx.tcx(); - assert!(!instance.substs.has_infer()); - assert!(!instance.substs.has_escaping_bound_vars()); + assert!(!instance.args.has_infer()); + assert!(!instance.args.has_escaping_bound_vars()); let sym = tcx.symbol_name(instance).name; @@ -100,7 +100,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) // whether we are sharing generics or not. The important thing here is // that the visibility we apply to the declaration is the same one that // has been applied to the definition (wherever that definition may be). - let is_generic = instance.substs.non_erasable_generics().next().is_some(); + let is_generic = instance.args.non_erasable_generics().next().is_some(); if is_generic { // This is a monomorphization. Its expected visibility depends diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 0b208be4e62..fe604be33b6 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -92,8 +92,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let tcx = self.tcx; let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); - let (def_id, substs) = match *callee_ty.kind() { - ty::FnDef(def_id, substs) => (def_id, substs), + let (def_id, fn_args) = match *callee_ty.kind() { + ty::FnDef(def_id, fn_args) => (def_id, fn_args), _ => bug!("expected fn item type, found {}", callee_ty), }; @@ -142,7 +142,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } sym::volatile_load | sym::unaligned_volatile_load => { - let tp_ty = substs.type_at(0); + let tp_ty = fn_args.type_at(0); let mut ptr = args[0].immediate(); if let PassMode::Cast(ty, _) = &fn_abi.ret.mode { ptr = self.pointercast(ptr, self.type_ptr_to(ty.gcc_type(self))); @@ -264,7 +264,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { sym::raw_eq => { use rustc_target::abi::Abi::*; - let tp_ty = substs.type_at(0); + let tp_ty = fn_args.type_at(0); let layout = self.layout_of(tp_ty).layout; let _use_integer_compare = match layout.abi() { Scalar(_) | ScalarPair(_, _) => true, diff --git a/src/mono_item.rs b/src/mono_item.rs index 342b830cedb..3322d56513b 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -31,7 +31,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { #[cfg_attr(not(feature="master"), allow(unused_variables))] fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, visibility: Visibility, symbol_name: &str) { - assert!(!instance.substs.has_infer()); + assert!(!instance.args.has_infer()); let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(base::linkage_to_gcc(linkage)); diff --git a/src/type_of.rs b/src/type_of.rs index e0823888f67..84d57838512 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -101,7 +101,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout if let (&ty::Generator(_, _, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { - write!(&mut name, "::{}", ty::GeneratorSubsts::variant_name(index)).unwrap(); + write!(&mut name, "::{}", ty::GeneratorArgs::variant_name(index)).unwrap(); } Some(name) } @@ -282,7 +282,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { } // only wide pointer boxes are handled as pointers // thin pointer boxes with scalar allocators are handled by the general logic below - ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => { + ty::Adt(def, args) if def.is_box() && cx.layout_of(args.type_at(1)).is_zst() => { let ptr_ty = Ty::new_mut_ptr(cx.tcx,self.ty.boxed_ty()); return cx.layout_of(ptr_ty).scalar_pair_element_gcc_type(cx, index, immediate); } From 7ba60ecb538249a7ba23d3a4bcc96e468de03a50 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 15 Jul 2023 12:37:47 +0000 Subject: [PATCH 017/103] Extract a create_wrapper_function for use in allocator shim writing This deduplicates some logic and makes it easier to follow what wrappers are produced. In the future it may allow moving the code to determine which wrappers to create to cg_ssa. --- src/allocator.rs | 135 ++++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 72 deletions(-) diff --git a/src/allocator.rs b/src/allocator.rs index 13f88192bbc..38309fa0153 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -1,6 +1,6 @@ #[cfg(feature="master")] use gccjit::FnAttribute; -use gccjit::{FunctionType, GlobalKind, ToRValue}; +use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type}; use rustc_ast::expand::allocator::{ alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, @@ -22,7 +22,6 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam }; let i8 = context.new_type::(); let i8p = i8.make_pointer(); - let void = context.new_type::<()>(); if kind == AllocatorKind::Default { for method in ALLOCATOR_METHODS { @@ -47,80 +46,22 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam panic!("invalid allocator output") } }; - let name = global_fn_name(method.name); + let from_name = global_fn_name(method.name); + let to_name = default_fn_name(method.name); - let args: Vec<_> = types.iter().enumerate() - .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) - .collect(); - let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false); - - if tcx.sess.target.options.default_hidden_visibility { - #[cfg(feature="master")] - func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); - } - if tcx.sess.must_emit_unwind_tables() { - // TODO(antoyo): emit unwind tables. - } - - let callee = default_fn_name(method.name); - let args: Vec<_> = types.iter().enumerate() - .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) - .collect(); - let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false); - #[cfg(feature="master")] - callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); - - let block = func.new_block("entry"); - - let args = args - .iter() - .enumerate() - .map(|(i, _)| func.get_param(i as i32).to_rvalue()) - .collect::>(); - let ret = context.new_call(None, callee, &args); - //llvm::LLVMSetTailCall(ret, True); - if output.is_some() { - block.end_with_return(None, ret); - } - else { - block.end_with_void_return(None); - } - - // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances - // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643 + create_wrapper_function(tcx, context, &from_name, &to_name, &types, output); } } - let types = [usize, usize]; - let name = "__rust_alloc_error_handler".to_string(); - let args: Vec<_> = types.iter().enumerate() - .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) - .collect(); - let func = context.new_function(None, FunctionType::Exported, void, &args, name, false); - - if tcx.sess.target.default_hidden_visibility { - #[cfg(feature="master")] - func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); - } - - let callee = alloc_error_handler_name(alloc_error_handler_kind); - let args: Vec<_> = types.iter().enumerate() - .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) - .collect(); - let callee = context.new_function(None, FunctionType::Extern, void, &args, callee, false); - #[cfg(feature="master")] - callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); - - let block = func.new_block("entry"); - - let args = args - .iter() - .enumerate() - .map(|(i, _)| func.get_param(i as i32).to_rvalue()) - .collect::>(); - let _ret = context.new_call(None, callee, &args); - //llvm::LLVMSetTailCall(ret, True); - block.end_with_void_return(None); + // FIXME(bjorn3): Add noreturn attribute + create_wrapper_function( + tcx, + context, + "__rust_alloc_error_handler", + &alloc_error_handler_name(alloc_error_handler_kind), + &[usize, usize], + None, + ); let name = OomStrategy::SYMBOL.to_string(); let global = context.new_global(None, GlobalKind::Exported, i8, name); @@ -133,3 +74,53 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam let value = context.new_rvalue_from_int(i8, 0); global.global_set_initializer_rvalue(value); } + +fn create_wrapper_function( + tcx: TyCtxt<'_>, + context: &Context<'_>, + from_name: &str, + to_name: &str, + types: &[Type<'_>], + output: Option>, +) { + let void = context.new_type::<()>(); + + let args: Vec<_> = types.iter().enumerate() + .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) + .collect(); + let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, from_name, false); + + if tcx.sess.target.options.default_hidden_visibility { + #[cfg(feature="master")] + func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); + } + if tcx.sess.must_emit_unwind_tables() { + // TODO(antoyo): emit unwind tables. + } + + let args: Vec<_> = types.iter().enumerate() + .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) + .collect(); + let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, to_name, false); + #[cfg(feature="master")] + callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); + + let block = func.new_block("entry"); + + let args = args + .iter() + .enumerate() + .map(|(i, _)| func.get_param(i as i32).to_rvalue()) + .collect::>(); + let ret = context.new_call(None, callee, &args); + //llvm::LLVMSetTailCall(ret, True); + if output.is_some() { + block.end_with_return(None, ret); + } + else { + block.end_with_void_return(None); + } + + // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances + // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643 +} From 2c0c87d9592d68b0cad47af9882f8bb6363187fa Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Sat, 5 Nov 2022 01:08:57 -0700 Subject: [PATCH 018/103] rustc_llvm: Add a `-Z print-llvm-stats` option to expose LLVM statistics. LLVM has a neat [statistics] feature that tracks how often optimizations kick in. It's very handy for optimization work. Since we expose the LLVM pass timings, I thought it made sense to expose the LLVM statistics too. [statistics]: https://llvm.org/docs/ProgrammersManual.html#the-statistic-class-stats-option --- src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 2a6b642782d..04ac0254a81 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -239,6 +239,10 @@ impl WriteBackendMethods for GccCodegenBackend { unimplemented!(); } + fn print_statistics(&self) { + unimplemented!() + } + unsafe fn optimize(_cgcx: &CodegenContext, _diag_handler: &Handler, module: &ModuleCodegen, config: &ModuleConfig) -> Result<(), FatalError> { module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level)); Ok(()) From 4bebfae44a40817df8b99a81b80bbb501c4d90c4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 14 Jul 2023 16:32:10 +1000 Subject: [PATCH 019/103] Introduce `MonoItemData`. It replaces `(Linkage, Visibility)`, making the code nicer. Plus the next commit will add another field. --- src/base.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base.rs b/src/base.rs index dcd560b3dcd..9e614ca4ace 100644 --- a/src/base.rs +++ b/src/base.rs @@ -159,8 +159,8 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i let cx = CodegenCx::new(&context, cgu, tcx, supports_128bit_integers); let mono_items = cgu.items_in_deterministic_order(tcx); - for &(mono_item, (linkage, visibility)) in &mono_items { - mono_item.predefine::>(&cx, linkage, visibility); + for &(mono_item, data) in &mono_items { + mono_item.predefine::>(&cx, data.linkage, data.visibility); } // ... and now that we have everything pre-defined, fill out those definitions. From 34922fc3ce1bd25fa2701c419a455d4dd4fe960e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 17 Jul 2023 23:22:45 +0200 Subject: [PATCH 020/103] Update gccjit-rs version --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3062b191f35..488b51c9366 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,7 +77,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#78ed1a380eb276e7443645a41b0e87222f291e82" +source = "git+https://github.com/antoyo/gccjit.rs#de70a3bdc1908098ae4b10efc530bd695971a67c" dependencies = [ "gccjit_sys", ] @@ -85,7 +85,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#78ed1a380eb276e7443645a41b0e87222f291e82" +source = "git+https://github.com/antoyo/gccjit.rs#de70a3bdc1908098ae4b10efc530bd695971a67c" dependencies = [ "libc", ] From 5277ea10b53373912582a3a3a5eaab94ff46ed5f Mon Sep 17 00:00:00 2001 From: chenx97 Date: Fri, 2 Jun 2023 11:18:26 +0800 Subject: [PATCH 021/103] support for mips64r6 as a target_arch value --- example/alloc_system.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/example/alloc_system.rs b/example/alloc_system.rs index 046903fe5ac..c13980d2c06 100644 --- a/example/alloc_system.rs +++ b/example/alloc_system.rs @@ -17,6 +17,7 @@ const MIN_ALIGN: usize = 8; target_arch = "aarch64", target_arch = "loongarch64", target_arch = "mips64", + target_arch = "mips64r6", target_arch = "s390x", target_arch = "sparc64"))] const MIN_ALIGN: usize = 16; From f2dded27f828ba02f76b1b714b3ab2361d4e003e Mon Sep 17 00:00:00 2001 From: chenx97 Date: Wed, 28 Jun 2023 13:35:39 +0800 Subject: [PATCH 022/103] support for mips32r6 as a target_arch value --- example/alloc_system.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/example/alloc_system.rs b/example/alloc_system.rs index c13980d2c06..e756b347e89 100644 --- a/example/alloc_system.rs +++ b/example/alloc_system.rs @@ -10,6 +10,7 @@ #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "mips", + target_arch = "mips32r6", target_arch = "powerpc", target_arch = "powerpc64"))] const MIN_ALIGN: usize = 8; From 5f56f49946e1d23845ac7e35b60bd8edb533664d Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Wed, 19 Jul 2023 23:40:08 -0400 Subject: [PATCH 023/103] UPDATE - replace gcc monomorphization errors with ssa ones Reduces error duplication and makes it more consistent across backends --- messages.ftl | 54 ------------ src/errors.rs | 185 ------------------------------------------ src/intrinsic/mod.rs | 4 +- src/intrinsic/simd.rs | 79 +++++++++--------- 4 files changed, 42 insertions(+), 280 deletions(-) diff --git a/messages.ftl b/messages.ftl index 97bc8ef9d1b..6dc8fdf9818 100644 --- a/messages.ftl +++ b/messages.ftl @@ -1,63 +1,9 @@ codegen_gcc_invalid_minimum_alignment = invalid minimum global alignment: {$err} -codegen_gcc_invalid_monomorphization_basic_integer = - invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}` - -codegen_gcc_invalid_monomorphization_expected_signed_unsigned = - invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type - codegen_gcc_invalid_monomorphization_expected_simd = invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}` -codegen_gcc_invalid_monomorphization_inserted_type = - invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}` - -codegen_gcc_invalid_monomorphization_invalid_bitmask = - invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` - -codegen_gcc_invalid_monomorphization_invalid_float_vector = - invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}` - -codegen_gcc_invalid_monomorphization_mask_type = - invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_` - -codegen_gcc_invalid_monomorphization_mismatched_lengths = - invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}` - -codegen_gcc_invalid_monomorphization_not_float = - invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type - -codegen_gcc_invalid_monomorphization_return_element = - invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}` - -codegen_gcc_invalid_monomorphization_return_integer_type = - invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}` - -codegen_gcc_invalid_monomorphization_return_length = - invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len} - -codegen_gcc_invalid_monomorphization_return_length_input_type = - invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len} - -codegen_gcc_invalid_monomorphization_return_type = - invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` - -codegen_gcc_invalid_monomorphization_simd_shuffle = - invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}` - -codegen_gcc_invalid_monomorphization_unrecognized = - invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` - -codegen_gcc_invalid_monomorphization_unsupported_cast = - invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}` - -codegen_gcc_invalid_monomorphization_unsupported_element = - invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}` - -codegen_gcc_invalid_monomorphization_unsupported_operation = - invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` - codegen_gcc_lto_not_supported = LTO is not supported. You may get a linker error. diff --git a/src/errors.rs b/src/errors.rs index 9305bd1e043..0cffdcfaa31 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -16,83 +16,6 @@ impl IntoDiagnosticArg for ExitCode { } } -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_basic_integer, code = "E0511")] -pub(crate) struct InvalidMonomorphizationBasicInteger<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_invalid_float_vector, code = "E0511")] -pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub elem_ty: &'a str, - pub vec_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_not_float, code = "E0511")] -pub(crate) struct InvalidMonomorphizationNotFloat<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_unrecognized, code = "E0511")] -pub(crate) struct InvalidMonomorphizationUnrecognized { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_expected_signed_unsigned, code = "E0511")] -pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub elem_ty: Ty<'a>, - pub vec_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_unsupported_element, code = "E0511")] -pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_ty: Ty<'a>, - pub elem_ty: Ty<'a>, - pub ret_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_invalid_bitmask, code = "E0511")] -pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ty: Ty<'a>, - pub expected_int_bits: u64, - pub expected_bytes: u64, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_simd_shuffle, code = "E0511")] -pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ty: Ty<'a>, -} - #[derive(Diagnostic)] #[diag(codegen_gcc_invalid_monomorphization_expected_simd, code = "E0511")] pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> { @@ -103,114 +26,6 @@ pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> { pub found_ty: Ty<'a>, } -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_mask_type, code = "E0511")] -pub(crate) struct InvalidMonomorphizationMaskType<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_return_length, code = "E0511")] -pub(crate) struct InvalidMonomorphizationReturnLength<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_len: u64, - pub ret_ty: Ty<'a>, - pub out_len: u64, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_return_length_input_type, code = "E0511")] -pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_len: u64, - pub in_ty: Ty<'a>, - pub ret_ty: Ty<'a>, - pub out_len: u64, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_return_element, code = "E0511")] -pub(crate) struct InvalidMonomorphizationReturnElement<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_elem: Ty<'a>, - pub in_ty: Ty<'a>, - pub ret_ty: Ty<'a>, - pub out_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_return_type, code = "E0511")] -pub(crate) struct InvalidMonomorphizationReturnType<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_elem: Ty<'a>, - pub in_ty: Ty<'a>, - pub ret_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_inserted_type, code = "E0511")] -pub(crate) struct InvalidMonomorphizationInsertedType<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_elem: Ty<'a>, - pub in_ty: Ty<'a>, - pub out_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_return_integer_type, code = "E0511")] -pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ret_ty: Ty<'a>, - pub out_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_mismatched_lengths, code = "E0511")] -pub(crate) struct InvalidMonomorphizationMismatchedLengths { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub m_len: u64, - pub v_len: u64, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_unsupported_cast, code = "E0511")] -pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_ty: Ty<'a>, - pub in_elem: Ty<'a>, - pub ret_ty: Ty<'a>, - pub out_elem: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_unsupported_operation, code = "E0511")] -pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_ty: Ty<'a>, - pub in_elem: Ty<'a>, -} - #[derive(Diagnostic)] #[diag(codegen_gcc_lto_not_supported)] pub(crate) struct LTONotSupported; diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index fe604be33b6..b75546447e3 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -13,6 +13,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods}; #[cfg(feature="master")] use rustc_codegen_ssa::traits::{DerivedTypeMethods, MiscMethods}; +use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_middle::bug; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::ty::layout::LayoutOf; @@ -31,7 +32,6 @@ use crate::abi::FnAbiGccExt; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; -use crate::errors::InvalidMonomorphizationBasicInteger; use crate::type_of::LayoutGccExt; use crate::intrinsic::simd::generic_simd_intrinsic; @@ -256,7 +256,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { _ => bug!(), }, None => { - tcx.sess.emit_err(InvalidMonomorphizationBasicInteger { span, name, ty }); + tcx.sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty }); return; } } diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 9115cf97119..2e780d290ac 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -22,17 +22,8 @@ use crate::builder::Builder; #[cfg(feature="master")] use crate::context::CodegenCx; #[cfg(feature="master")] -use crate::errors::{InvalidMonomorphizationExpectedSignedUnsigned, InvalidMonomorphizationInsertedType}; use crate::errors::{ InvalidMonomorphizationExpectedSimd, - InvalidMonomorphizationInvalidBitmask, - InvalidMonomorphizationInvalidFloatVector, InvalidMonomorphizationMaskType, - InvalidMonomorphizationMismatchedLengths, InvalidMonomorphizationNotFloat, - InvalidMonomorphizationReturnElement, InvalidMonomorphizationReturnIntegerType, - InvalidMonomorphizationReturnLength, InvalidMonomorphizationReturnLengthInputType, - InvalidMonomorphizationReturnType, InvalidMonomorphizationSimdShuffle, - InvalidMonomorphizationUnrecognized, InvalidMonomorphizationUnsupportedElement, - InvalidMonomorphizationUnsupportedOperation, }; pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( @@ -99,10 +90,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty)); bx.load(int_ty, ptr, Align::ONE) } - _ => return_error!(InvalidMonomorphizationInvalidBitmask { + _ => return_error!(InvalidMonomorphization::InvalidBitmask { span, name, - ty: mask_ty, + mask_ty, expected_int_bits, expected_bytes }), @@ -151,7 +142,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - InvalidMonomorphizationReturnLengthInputType { + InvalidMonomorphization::ReturnLengthInputType { span, name, in_len, @@ -162,7 +153,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ); require!( bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, - InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty } + InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty } ); let arg1 = args[0].immediate(); @@ -190,7 +181,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( || span_bug!(span, "could not evaluate shuffle index array length"), ) } - _ => return_error!(InvalidMonomorphizationSimdShuffle { + _ => return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: args[2].layout.ty @@ -207,11 +198,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( out_len == n, - InvalidMonomorphizationReturnLength { span, name, in_len: n, ret_ty, out_len } + InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len } ); require!( in_elem == out_ty, - InvalidMonomorphizationReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } + InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } ); let vector = args[2].immediate(); @@ -223,7 +214,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_insert { require!( in_elem == arg_tys[2], - InvalidMonomorphizationInsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] } + InvalidMonomorphization::InsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] } ); let vector = args[0].immediate(); let index = args[1].immediate(); @@ -240,7 +231,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_extract { require!( ret_ty == in_elem, - InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); let vector = args[0].immediate(); return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue()); @@ -253,11 +244,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( m_len == v_len, - InvalidMonomorphizationMismatchedLengths { span, name, m_len, v_len } + InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len } ); match m_elem_ty.kind() { ty::Int(_) => {} - _ => return_error!(InvalidMonomorphizationMaskType { span, name, ty: m_elem_ty }), + _ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }), } return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate())); } @@ -268,7 +259,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - InvalidMonomorphizationReturnLengthInputType { + InvalidMonomorphization::ReturnLengthInputType { span, name, in_len, @@ -329,7 +320,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( })* _ => {}, } - return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem }) + return_error!(InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }) })* } } @@ -422,12 +413,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( 32 => ("f", elem_ty), 64 => ("", elem_ty), _ => { - return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty }); + return_error!(InvalidMonomorphization::FloatingPointVector { span, name, f_ty: *f, in_ty }); } } } else { - return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty }); + return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); }; let vec_ty = bx.cx.type_vector(elem_ty, in_len); @@ -450,7 +441,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( sym::simd_fsqrt => "sqrt", sym::simd_round => "round", sym::simd_trunc => "trunc", - _ => return_error!(InvalidMonomorphizationUnrecognized { span, name }) + _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }) }; let builtin_name = format!("{}{}", intr_name, elem_ty_str); let funcs = bx.cx.functions.borrow(); @@ -815,7 +806,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( })* _ => {}, } - return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem }) + return_error!(InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }) })* } } @@ -835,11 +826,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)), _ => { - return_error!(InvalidMonomorphizationExpectedSignedUnsigned { + return_error!(InvalidMonomorphization::ExpectedVectorElementType { span, name, - elem_ty: arg_tys[0].simd_size_and_type(bx.tcx()).1, - vec_ty: arg_tys[0], + expected_element: arg_tys[0].simd_size_and_type(bx.tcx()).1, + vector_type: arg_tys[0], }); } }; @@ -925,7 +916,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::$name { require!( ret_ty == in_elem, - InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => { @@ -947,11 +938,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op)) } } - _ => return_error!(InvalidMonomorphizationUnsupportedElement { + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, name, + symbol: sym::$name, in_ty, - elem_ty: in_elem, + in_elem, ret_ty }), }; @@ -994,12 +986,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::$name { require!( ret_ty == in_elem, - InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())), ty::Float(_) => Ok(bx.$float_red(args[0].immediate())), - _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }), + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, + name, + symbol: sym::$name, + in_ty, + in_elem, + ret_ty + }), }; } }; @@ -1017,17 +1016,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let input = if !$boolean { require!( ret_ty == in_elem, - InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); args[0].immediate() } else { match in_elem.kind() { ty::Int(_) | ty::Uint(_) => {} - _ => return_error!(InvalidMonomorphizationUnsupportedElement { + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, name, + symbol: sym::$name, in_ty, - elem_ty: in_elem, + in_elem, ret_ty }), } @@ -1039,11 +1039,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let r = bx.vector_reduce_op(input, $op); Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) }) } - _ => return_error!(InvalidMonomorphizationUnsupportedElement { + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, name, + symbol: sym::$name, in_ty, - elem_ty: in_elem, + in_elem, ret_ty }), }; From f746fe1e6c11478491573cc25fad31bbc6633f02 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Thu, 20 Jul 2023 00:20:00 -0400 Subject: [PATCH 024/103] UPDATE - replace expected_simd error with one from codegen_ssa Here I am assuming we want to treat these parameters (input, first, second, third, return) as translatable --- messages.ftl | 3 --- src/errors.rs | 13 +------------ src/intrinsic/simd.rs | 42 +++++++++++++++--------------------------- 3 files changed, 16 insertions(+), 42 deletions(-) diff --git a/messages.ftl b/messages.ftl index 6dc8fdf9818..2fd0daee3e7 100644 --- a/messages.ftl +++ b/messages.ftl @@ -1,9 +1,6 @@ codegen_gcc_invalid_minimum_alignment = invalid minimum global alignment: {$err} -codegen_gcc_invalid_monomorphization_expected_simd = - invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}` - codegen_gcc_lto_not_supported = LTO is not supported. You may get a linker error. diff --git a/src/errors.rs b/src/errors.rs index 0cffdcfaa31..693367192b1 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,7 +1,6 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_macros::Diagnostic; -use rustc_middle::ty::Ty; -use rustc_span::{Span, Symbol}; +use rustc_span::Span; use std::borrow::Cow; struct ExitCode(Option); @@ -16,16 +15,6 @@ impl IntoDiagnosticArg for ExitCode { } } -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_expected_simd, code = "E0511")] -pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub position: &'a str, - pub found_ty: Ty<'a>, -} - #[derive(Diagnostic)] #[diag(codegen_gcc_lto_not_supported)] pub(crate) struct LTONotSupported; diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 2e780d290ac..f27de867d36 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -21,10 +21,6 @@ use rustc_target::abi::Align; use crate::builder::Builder; #[cfg(feature="master")] use crate::context::CodegenCx; -#[cfg(feature="master")] -use crate::errors::{ - InvalidMonomorphizationExpectedSimd, -}; pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( bx: &mut Builder<'a, 'gcc, 'tcx>, @@ -50,16 +46,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( }; } macro_rules! require_simd { - ($ty: expr, $position: expr) => { - require!( - $ty.is_simd(), - InvalidMonomorphizationExpectedSimd { - span, - name, - position: $position, - found_ty: $ty - } - ) + ($ty: expr, $diag: expr) => { + require!($ty.is_simd(), $diag) }; } @@ -69,7 +57,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { - require_simd!(arg_tys[1], "argument"); + require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }); let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let expected_int_bits = (len.max(8) - 1).next_power_of_two(); @@ -122,7 +110,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } // every intrinsic below takes a SIMD vector as its first argument - require_simd!(arg_tys[0], "input"); + require_simd!(arg_tys[0], InvalidMonomorphization::SimdInput { span, name, ty: arg_tys[0] }); let in_ty = arg_tys[0]; let comparison = match name { @@ -137,7 +125,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx()); if let Some(cmp_op) = comparison { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( @@ -193,7 +181,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( }) }; - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( @@ -240,7 +228,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_select { let m_elem_ty = in_elem; let m_len = in_len; - require_simd!(arg_tys[1], "argument"); + require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }); let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( m_len == v_len, @@ -255,7 +243,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( #[cfg(feature="master")] if name == sym::simd_cast || name == sym::simd_as { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, @@ -557,10 +545,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // * M: any integer width is supported, will be truncated to i1 // All types must be simd vector types - require_simd!(in_ty, "first"); - require_simd!(arg_tys[1], "second"); - require_simd!(arg_tys[2], "third"); - require_simd!(ret_ty, "return"); + require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); + require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }); + require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); // Of the same length: let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); @@ -665,9 +653,9 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // * M: any integer width is supported, will be truncated to i1 // All types must be simd vector types - require_simd!(in_ty, "first"); - require_simd!(arg_tys[1], "second"); - require_simd!(arg_tys[2], "third"); + require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); + require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }); + require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }); // Of the same length: let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx()); From 1984e208e06f320d62306e19940b86156460f98e Mon Sep 17 00:00:00 2001 From: Moulins Date: Tue, 27 Jun 2023 00:47:27 +0200 Subject: [PATCH 025/103] Don't treat ref. fields with non-null niches as `dereferenceable_or_null` --- src/type_of.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/type_of.rs b/src/type_of.rs index 84d57838512..a30bce0a313 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -339,7 +339,8 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { return pointee; } - let result = Ty::ty_and_layout_pointee_info_at(*self, cx, offset); + let assume_valid_ptr = true; + let result = Ty::ty_and_layout_pointee_info_at(*self, cx, offset, assume_valid_ptr); cx.pointee_infos.borrow_mut().insert((self.ty, offset), result); result From 918332bea228e103fd2e81dc719a53e4c3122bac Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 21 Jul 2023 11:23:41 +0200 Subject: [PATCH 026/103] Add support for "ffi_const" function attribute --- src/attributes.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/attributes.rs b/src/attributes.rs index 6195de912d2..35682db9c78 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -124,6 +124,9 @@ pub fn from_fn_attrs<'gcc, 'tcx>( if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { func.add_attribute(FnAttribute::Pure); } + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_CONST) { + func.add_attribute(FnAttribute::Const); + } } let function_features = From e2a847460def381a2d947e2c9ed6d517ff55d985 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 21 Jul 2023 22:35:57 -0700 Subject: [PATCH 027/103] Revert "Auto merge of #113166 - moulins:ref-niches-initial, r=oli-obk" This reverts commit 557359f92512ca88b62a602ebda291f17a953002, reversing changes made to 1e6c09a803fd543a98bfbe1624d697a55300a786. --- src/type_of.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/type_of.rs b/src/type_of.rs index a30bce0a313..84d57838512 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -339,8 +339,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { return pointee; } - let assume_valid_ptr = true; - let result = Ty::ty_and_layout_pointee_info_at(*self, cx, offset, assume_valid_ptr); + let result = Ty::ty_and_layout_pointee_info_at(*self, cx, offset); cx.pointee_infos.borrow_mut().insert((self.ty, offset), result); result From 136548d3fe9d2c8ac993d7d1b0d2e20256f02750 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 22 Jul 2023 14:44:20 +0200 Subject: [PATCH 028/103] Update gccjit dependency --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 488b51c9366..60df0e60988 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,7 +77,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#de70a3bdc1908098ae4b10efc530bd695971a67c" +source = "git+https://github.com/antoyo/gccjit.rs#61d8d55c894bd462ee66c096cc31157a44a9f869" dependencies = [ "gccjit_sys", ] @@ -85,7 +85,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#de70a3bdc1908098ae4b10efc530bd695971a67c" +source = "git+https://github.com/antoyo/gccjit.rs#61d8d55c894bd462ee66c096cc31157a44a9f869" dependencies = [ "libc", ] From cd57c6ea1c13db57a6ebd4423ddbf2ca8e28e765 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 21 Jul 2023 15:14:15 +0200 Subject: [PATCH 029/103] Add instructions on how to generate GIMPLE format --- Readme.md | 5 ++++ doc/gimple.md | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 doc/gimple.md diff --git a/Readme.md b/Readme.md index e05f8dae1c6..b9a78b0277b 100644 --- a/Readme.md +++ b/Readme.md @@ -227,6 +227,11 @@ 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 diff --git a/doc/gimple.md b/doc/gimple.md new file mode 100644 index 00000000000..589cf3db7a6 --- /dev/null +++ b/doc/gimple.md @@ -0,0 +1,80 @@ +# GIMPLE + +You can see the full documentation about what GIMPLE is [here](https://gcc.gnu.org/onlinedocs/gccint/GIMPLE.html). In this document we will explain how to generate it. + +First, we'll copy the content from `gcc/gcc/testsuite/jit.dg/test-const-attribute.c` into a +file named `local.c` and remove the content we're not interested into: + +```diff +- /* { dg-do compile { target x86_64-*-* } } */ +... +- /* We don't want set_options() in harness.h to set -O3 to see that the const +- attribute affects the optimizations. */ +- #define TEST_ESCHEWS_SET_OPTIONS +- static void set_options (gcc_jit_context *ctxt, const char *argv0) +- { +- // Set "-O3". +- gcc_jit_context_set_int_option(ctxt, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); +- } +- +- #define TEST_COMPILING_TO_FILE +- #define OUTPUT_KIND GCC_JIT_OUTPUT_KIND_ASSEMBLER +- #define OUTPUT_FILENAME "output-of-test-const-attribute.c.s" +- #include "harness.h" +... +- /* { dg-final { jit-verify-output-file-was-created "" } } */ +- /* Check that the loop was optimized away */ +- /* { dg-final { jit-verify-assembler-output-not "jne" } } */ +``` + +Then we'll add a `main` function which will call the `create_code` function but +also add the calls we need to generate the GIMPLE: + +```C +int main() { + gcc_jit_context *ctxt = gcc_jit_context_acquire(); + create_code(ctxt, NULL); + gcc_jit_context_compile_to_file(ctxt, GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY, "tmp"); + return 0; +} +``` + +Then we can compile it by using: + +```console +gcc const.c -I `pwd`/gcc/gcc/jit/ -L `pwd`/gcc-build/gcc -lgccjit -o out +``` + +And finally when you run it: + +```console +LD_LIBRARY_PATH=`pwd`/gcc-build/gcc ./out +``` + +It should display: + +```c +__attribute__((const)) +int xxx () +{ + int D.3394; + int sum; + int x; + + : + x = 45; + sum = 0; + goto loop_cond; + loop_cond: + x = x >> 1; + if (x != 0) goto after_loop; else goto loop_body; + loop_body: + _1 = foo (x); + _2 = _1 * 2; + x = x + _2; + goto loop_cond; + after_loop: + D.3394 = sum; + return D.3394; +} +``` From 14964ed2f6c8f19a444afe886d0c2ac68a831e45 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 24 Jul 2023 13:49:35 -0400 Subject: [PATCH 030/103] Update the IRC link to the link of the Matrix channel --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index b9a78b0277b..fbe1a407733 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,6 @@ # 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 IRC](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. From 52716d237cf00dab0d51b253bc080810570f47ef Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 27 Jul 2023 19:21:00 -0400 Subject: [PATCH 031/103] Add back link to IRC --- Readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index fbe1a407733..55daad6dcd0 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,7 @@ # WIP libgccjit codegen backend for rust -[![Chat on IRC](https://img.shields.io/badge/matrix.org-%23rustc__codegen__gcc-blue.svg)](https://matrix.to/#/#rustc_codegen_gcc:matrix.org) +[![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. From bc4a65d47f8be22df4e72080b256844964ab295d Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Fri, 28 Jul 2023 20:24:33 -0400 Subject: [PATCH 032/103] cg_ssa: remove pointee types and pointercast/bitcast-of-ptr --- src/builder.rs | 1 - src/common.rs | 8 ++++---- src/intrinsic/mod.rs | 2 +- src/type_.rs | 26 +++++++++++++++++++++----- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 43d0aafbd50..0b1f2fe6a87 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -27,7 +27,6 @@ use rustc_codegen_ssa::traits::{ BaseTypeMethods, BuilderMethods, ConstMethods, - DerivedTypeMethods, LayoutTypeMethods, HasCodegen, OverflowOp, diff --git a/src/common.rs b/src/common.rs index b62f4676f70..5f54cb16d8e 100644 --- a/src/common.rs +++ b/src/common.rs @@ -16,6 +16,10 @@ use crate::context::CodegenCx; use crate::type_of::LayoutGccExt; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + pub fn const_ptrcast(&self, val: RValue<'gcc>, ty: Type<'gcc>) -> RValue<'gcc> { + self.context.new_cast(None, val, ty) + } + pub fn const_bytes(&self, bytes: &[u8]) -> RValue<'gcc> { bytes_in_context(self, bytes) } @@ -242,10 +246,6 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { const_alloc_to_gcc(self, alloc) } - fn const_ptrcast(&self, val: RValue<'gcc>, ty: Type<'gcc>) -> RValue<'gcc> { - self.context.new_cast(None, val, ty) - } - fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> { if value.get_type() == self.bool_type.make_pointer() { if let Some(pointee) = typ.get_pointee() { diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index b75546447e3..68edde13829 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -12,7 +12,7 @@ use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods}; #[cfg(feature="master")] -use rustc_codegen_ssa::traits::{DerivedTypeMethods, MiscMethods}; +use rustc_codegen_ssa::traits::MiscMethods; use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_middle::bug; use rustc_middle::ty::{self, Instance, Ty}; diff --git a/src/type_.rs b/src/type_.rs index 521b64ad34d..31899740514 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -54,6 +54,23 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.u128_type } + pub fn type_ptr_to(&self, ty: Type<'gcc>) -> Type<'gcc> { + ty.make_pointer() + } + + pub fn type_ptr_to_ext(&self, ty: Type<'gcc>, _address_space: AddressSpace) -> Type<'gcc> { + // TODO(antoyo): use address_space, perhaps with TYPE_ADDR_SPACE? + ty.make_pointer() + } + + pub fn type_i8p(&self) -> Type<'gcc> { + self.type_ptr_to(self.type_i8()) + } + + pub fn type_i8p_ext(&self, address_space: AddressSpace) -> Type<'gcc> { + self.type_ptr_to_ext(self.type_i8(), address_space) + } + pub fn type_pointee_for_align(&self, align: Align) -> Type<'gcc> { // FIXME(eddyb) We could find a better approximation if ity.align < align. let ity = Integer::approximate_align(self, align); @@ -149,13 +166,12 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } } - fn type_ptr_to(&self, ty: Type<'gcc>) -> Type<'gcc> { - ty.make_pointer() + fn type_ptr(&self) -> Type<'gcc> { + self.type_ptr_to(self.type_void()) } - fn type_ptr_to_ext(&self, ty: Type<'gcc>, _address_space: AddressSpace) -> Type<'gcc> { - // TODO(antoyo): use address_space, perhaps with TYPE_ADDR_SPACE? - ty.make_pointer() + fn type_ptr_ext(&self, address_space: AddressSpace) -> Type<'gcc> { + self.type_ptr_to_ext(self.type_void(), address_space) } fn element_type(&self, ty: Type<'gcc>) -> Type<'gcc> { From e94abcdf3ddf72af54e90285c4dff3127dacc93b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Jul 2023 11:18:25 +1000 Subject: [PATCH 033/103] Use standard Rust capitalization rules for names containing "LTO". --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 04ac0254a81..697ae015fed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,7 +71,7 @@ use gccjit::{Context, OptimizationLevel, CType}; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; use rustc_codegen_ssa::base::codegen_crate; -use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig, TargetMachineFactoryFn}; +use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn}; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; use rustc_codegen_ssa::target_features::supported_target_features; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods}; @@ -217,14 +217,14 @@ impl WriteBackendMethods for GccCodegenBackend { type ThinData = (); type ThinBuffer = ThinBuffer; - fn run_fat_lto(_cgcx: &CodegenContext, mut modules: Vec>, _cached_modules: Vec<(SerializedModule, WorkProduct)>) -> Result, FatalError> { + fn run_fat_lto(_cgcx: &CodegenContext, mut modules: Vec>, _cached_modules: Vec<(SerializedModule, WorkProduct)>) -> Result, FatalError> { // TODO(antoyo): implement LTO by sending -flto to libgccjit and adding the appropriate gcc linker plugins. // NOTE: implemented elsewhere. // TODO(antoyo): what is implemented elsewhere ^ ? let module = match modules.remove(0) { - FatLTOInput::InMemory(module) => module, - FatLTOInput::Serialized { .. } => { + FatLtoInput::InMemory(module) => module, + FatLtoInput::Serialized { .. } => { unimplemented!(); } }; From de69c67ffa064c4446cfd1d228b507883c64ee3f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 10 Jul 2023 13:03:48 +0000 Subject: [PATCH 034/103] Forbid old-style `simd_shuffleN` intrinsics --- src/intrinsic/simd.rs | 427 ++++++++++++++++++++++++------------------ 1 file changed, 241 insertions(+), 186 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index f27de867d36..85d3e7234a0 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -1,11 +1,11 @@ -#[cfg(feature="master")] -use gccjit::{ComparisonOp, UnaryOp}; use gccjit::ToRValue; use gccjit::{BinaryOp, RValue, Type}; +#[cfg(feature = "master")] +use gccjit::{ComparisonOp, UnaryOp}; use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; -#[cfg(feature="master")] +#[cfg(feature = "master")] use rustc_codegen_ssa::errors::ExpectedPointerMutability; use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_codegen_ssa::mir::operand::OperandRef; @@ -19,7 +19,7 @@ use rustc_span::{sym, Span, Symbol}; use rustc_target::abi::Align; use crate::builder::Builder; -#[cfg(feature="master")] +#[cfg(feature = "master")] use crate::context::CodegenCx; pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( @@ -57,7 +57,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { - require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let expected_int_bits = (len.max(8) - 1).next_power_of_two(); @@ -95,7 +98,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // NOTE: since the arguments can be vectors of floats, make sure the mask is a vector of // integer. let mask_element_type = bx.type_ix(arg1_element_type.get_size() as u64 * 8); - let vector_mask_type = bx.context.new_vector_type(mask_element_type, arg1_vector_type.get_num_units() as u64); + let vector_mask_type = + bx.context.new_vector_type(mask_element_type, arg1_vector_type.get_num_units() as u64); let mut elements = vec![]; let one = bx.context.new_rvalue_one(mask.get_type()); @@ -149,38 +153,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // compare them as equal, so bitcast. // FIXME(antoyo): allow comparing vector types as equal in libgccjit. let arg2 = bx.context.new_bitcast(None, args[1].immediate(), arg1.get_type()); - return Ok(compare_simd_types( - bx, - arg1, - arg2, - in_elem, - llret_ty, - cmp_op, - )); + return Ok(compare_simd_types(bx, arg1, arg2, in_elem, llret_ty, cmp_op)); } - if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") { - let n: u64 = if stripped.is_empty() { - // Make sure this is actually an array, since typeck only checks the length-suffixed - // version of this intrinsic. - match args[2].layout.ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { - len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( - || span_bug!(span, "could not evaluate shuffle index array length"), - ) - } - _ => return_error!(InvalidMonomorphization::SimdShuffle { - span, - name, - ty: args[2].layout.ty - }), + if name == sym::simd_shuffle { + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + let n: u64 = match args[2].layout.ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( + || span_bug!(span, "could not evaluate shuffle index array length"), + ) } - } else { - stripped.parse().unwrap_or_else(|_| { - span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") - }) + _ => return_error!(InvalidMonomorphization::SimdShuffle { + span, + name, + ty: args[2].layout.ty + }), }; - require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); @@ -202,7 +192,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_insert { require!( in_elem == arg_tys[2], - InvalidMonomorphization::InsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] } + InvalidMonomorphization::InsertedType { + span, + name, + in_elem, + in_ty, + out_ty: arg_tys[2] + } ); let vector = args[0].immediate(); let index = args[1].immediate(); @@ -228,7 +224,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_select { let m_elem_ty = in_elem; let m_len = in_len; - require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( m_len == v_len, @@ -241,7 +240,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate())); } - #[cfg(feature="master")] + #[cfg(feature = "master")] if name == sym::simd_cast || name == sym::simd_as { require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); @@ -267,19 +266,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( Unsupported, } - let in_style = - match in_elem.kind() { - ty::Int(_) | ty::Uint(_) => Style::Int, - ty::Float(_) => Style::Float, - _ => Style::Unsupported, - }; + let in_style = match in_elem.kind() { + ty::Int(_) | ty::Uint(_) => Style::Int, + ty::Float(_) => Style::Float, + _ => Style::Unsupported, + }; - let out_style = - match out_elem.kind() { - ty::Int(_) | ty::Uint(_) => Style::Int, - ty::Float(_) => Style::Float, - _ => Style::Unsupported, - }; + let out_style = match out_elem.kind() { + ty::Int(_) | ty::Uint(_) => Style::Int, + ty::Float(_) => Style::Float, + _ => Style::Unsupported, + }; match (in_style, out_style) { (Style::Unsupported, Style::Unsupported) => { @@ -294,7 +291,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( out_elem } ); - }, + } _ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)), } } @@ -342,10 +339,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let mut shift = 0; for i in 0..in_len { - let elem = bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32)); + let elem = + bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32)); let shifted = elem >> sign_shift; let masked = shifted & one; - result = result | (bx.context.new_cast(None, masked, result_type) << bx.context.new_rvalue_from_int(result_type, shift)); + result = result + | (bx.context.new_cast(None, masked, result_type) + << bx.context.new_rvalue_from_int(result_type, shift)); shift += 1; } @@ -394,46 +394,50 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Err(()); }}; } - let (elem_ty_str, elem_ty) = - if let ty::Float(f) = in_elem.kind() { - let elem_ty = bx.cx.type_float_from_ty(*f); - match f.bit_width() { - 32 => ("f", elem_ty), - 64 => ("", elem_ty), - _ => { - return_error!(InvalidMonomorphization::FloatingPointVector { span, name, f_ty: *f, in_ty }); - } + let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() { + let elem_ty = bx.cx.type_float_from_ty(*f); + match f.bit_width() { + 32 => ("f", elem_ty), + 64 => ("", elem_ty), + _ => { + return_error!(InvalidMonomorphization::FloatingPointVector { + span, + name, + f_ty: *f, + in_ty + }); } } - else { - return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); - }; + } else { + return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); + }; let vec_ty = bx.cx.type_vector(elem_ty, in_len); - let intr_name = - match name { - sym::simd_ceil => "ceil", - sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103 - sym::simd_fcos => "cos", - sym::simd_fexp2 => "exp2", - sym::simd_fexp => "exp", - sym::simd_flog10 => "log10", - sym::simd_flog2 => "log2", - sym::simd_flog => "log", - sym::simd_floor => "floor", - sym::simd_fma => "fma", - sym::simd_fpowi => "__builtin_powi", - sym::simd_fpow => "pow", - sym::simd_fsin => "sin", - sym::simd_fsqrt => "sqrt", - sym::simd_round => "round", - sym::simd_trunc => "trunc", - _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }) - }; + let intr_name = match name { + sym::simd_ceil => "ceil", + sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103 + sym::simd_fcos => "cos", + sym::simd_fexp2 => "exp2", + sym::simd_fexp => "exp", + sym::simd_flog10 => "log10", + sym::simd_flog2 => "log2", + sym::simd_flog => "log", + sym::simd_floor => "floor", + sym::simd_fma => "fma", + sym::simd_fpowi => "__builtin_powi", + sym::simd_fpow => "pow", + sym::simd_fsin => "sin", + sym::simd_fsqrt => "sqrt", + sym::simd_round => "round", + sym::simd_trunc => "trunc", + _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }), + }; let builtin_name = format!("{}{}", intr_name, elem_ty_str); let funcs = bx.cx.functions.borrow(); - let function = funcs.get(&builtin_name).unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name)); + let function = funcs + .get(&builtin_name) + .unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name)); // TODO(antoyo): add platform-specific behavior here for architectures that have these // intrinsics as instructions (for instance, gpus) @@ -479,8 +483,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args); } - #[cfg(feature="master")] - fn vector_ty<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, elem_ty: Ty<'tcx>, vec_len: u64) -> Type<'gcc> { + #[cfg(feature = "master")] + fn vector_ty<'gcc, 'tcx>( + cx: &CodegenCx<'gcc, 'tcx>, + elem_ty: Ty<'tcx>, + vec_len: u64, + ) -> Type<'gcc> { // FIXME: use cx.layout_of(ty).llvm_type() ? let elem_ty = match *elem_ty.kind() { ty::Int(v) => cx.type_int_from_ty(v), @@ -491,15 +499,22 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( cx.type_vector(elem_ty, vec_len) } - #[cfg(feature="master")] - fn gather<'a, 'gcc, 'tcx>(default: RValue<'gcc>, pointers: RValue<'gcc>, mask: RValue<'gcc>, pointer_count: usize, bx: &mut Builder<'a, 'gcc, 'tcx>, in_len: u64, underlying_ty: Ty<'tcx>, invert: bool) -> RValue<'gcc> { - let vector_type = - if pointer_count > 1 { - bx.context.new_vector_type(bx.usize_type, in_len) - } - else { - vector_ty(bx, underlying_ty, in_len) - }; + #[cfg(feature = "master")] + fn gather<'a, 'gcc, 'tcx>( + default: RValue<'gcc>, + pointers: RValue<'gcc>, + mask: RValue<'gcc>, + pointer_count: usize, + bx: &mut Builder<'a, 'gcc, 'tcx>, + in_len: u64, + underlying_ty: Ty<'tcx>, + invert: bool, + ) -> RValue<'gcc> { + let vector_type = if pointer_count > 1 { + bx.context.new_vector_type(bx.usize_type, in_len) + } else { + vector_ty(bx, underlying_ty, in_len) + }; let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type(); let mut values = vec![]; @@ -530,13 +545,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if invert { bx.shuffle_vector(vector, default, mask) - } - else { + } else { bx.shuffle_vector(default, vector, mask) } } - #[cfg(feature="master")] + #[cfg(feature = "master")] if name == sym::simd_gather { // simd_gather(values: , pointers: , // mask: ) -> @@ -546,8 +560,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // All types must be simd vector types require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); - require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }); - require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); // Of the same length: @@ -641,10 +661,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } } - return Ok(gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), pointer_count, bx, in_len, underlying_ty, false)); + return Ok(gather( + args[0].immediate(), + args[1].immediate(), + args[2].immediate(), + pointer_count, + bx, + in_len, + underlying_ty, + false, + )); } - #[cfg(feature="master")] + #[cfg(feature = "master")] if name == sym::simd_scatter { // simd_scatter(values: , pointers: , // mask: ) -> () @@ -654,8 +683,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // All types must be simd vector types require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); - require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }); - require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); // Of the same length: let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx()); @@ -744,17 +779,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } } - let result = gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), pointer_count, bx, in_len, underlying_ty, true); + let result = gather( + args[0].immediate(), + args[1].immediate(), + args[2].immediate(), + pointer_count, + bx, + in_len, + underlying_ty, + true, + ); let pointers = args[1].immediate(); - let vector_type = - if pointer_count > 1 { - bx.context.new_vector_type(bx.usize_type, in_len) - } - else { - vector_ty(bx, underlying_ty, in_len) - }; + let vector_type = if pointer_count > 1 { + bx.context.new_vector_type(bx.usize_type, in_len) + } else { + vector_ty(bx, underlying_ty, in_len) + }; let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type(); for i in 0..in_len { @@ -809,11 +851,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let rhs = args[1].immediate(); let is_add = name == sym::simd_saturating_add; let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _; - let (signed, elem_width, elem_ty) = - match *in_elem.kind() { - ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), - ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)), - _ => { + let (signed, elem_width, elem_ty) = match *in_elem.kind() { + ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), + ty::Uint(i) => { + (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)) + } + _ => { return_error!(InvalidMonomorphization::ExpectedVectorElementType { span, name, @@ -823,77 +866,82 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } }; - let result = - match (signed, is_add) { - (false, true) => { - let res = lhs + rhs; - let cmp = bx.context.new_comparison(None, ComparisonOp::LessThan, res, lhs); - res | cmp - }, - (true, true) => { - // Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition - // TODO(antoyo): improve using conditional operators if possible. - // TODO(antoyo): dyncast_vector should not require a call to unqualified. - let arg_type = lhs.get_type().unqualified(); - // TODO(antoyo): convert lhs and rhs to unsigned. - let sum = lhs + rhs; - let vector_type = arg_type.dyncast_vector().expect("vector type"); - let unit = vector_type.get_num_units(); - let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); - let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); + let result = match (signed, is_add) { + (false, true) => { + let res = lhs + rhs; + let cmp = bx.context.new_comparison(None, ComparisonOp::LessThan, res, lhs); + res | cmp + } + (true, true) => { + // Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition + // TODO(antoyo): improve using conditional operators if possible. + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let arg_type = lhs.get_type().unqualified(); + // TODO(antoyo): convert lhs and rhs to unsigned. + let sum = lhs + rhs; + let vector_type = arg_type.dyncast_vector().expect("vector type"); + let unit = vector_type.get_num_units(); + let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); + let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); - let xor1 = lhs ^ rhs; - let xor2 = lhs ^ sum; - let and = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; - let mask = and >> width; + let xor1 = lhs ^ rhs; + let xor2 = lhs ^ sum; + let and = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; + let mask = and >> width; - let one = bx.context.new_rvalue_one(elem_ty); - let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); - let shift1 = ones << width; - let shift2 = sum >> width; - let mask_min = shift1 ^ shift2; + let one = bx.context.new_rvalue_one(elem_ty); + let ones = + bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); + let shift1 = ones << width; + let shift2 = sum >> width; + let mask_min = shift1 ^ shift2; - let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; - let and2 = mask & mask_min; + let and1 = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; + let and2 = mask & mask_min; - and1 + and2 - }, - (false, false) => { - let res = lhs - rhs; - let cmp = bx.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs); - res & cmp - }, - (true, false) => { - // TODO(antoyo): dyncast_vector should not require a call to unqualified. - let arg_type = lhs.get_type().unqualified(); - // TODO(antoyo): this uses the same algorithm from saturating add, but add the - // negative of the right operand. Find a proper subtraction algorithm. - let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); + and1 + and2 + } + (false, false) => { + let res = lhs - rhs; + let cmp = bx.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs); + res & cmp + } + (true, false) => { + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let arg_type = lhs.get_type().unqualified(); + // TODO(antoyo): this uses the same algorithm from saturating add, but add the + // negative of the right operand. Find a proper subtraction algorithm. + let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); - // TODO(antoyo): convert lhs and rhs to unsigned. - let sum = lhs + rhs; - let vector_type = arg_type.dyncast_vector().expect("vector type"); - let unit = vector_type.get_num_units(); - let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); - let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); + // TODO(antoyo): convert lhs and rhs to unsigned. + let sum = lhs + rhs; + let vector_type = arg_type.dyncast_vector().expect("vector type"); + let unit = vector_type.get_num_units(); + let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); + let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); - let xor1 = lhs ^ rhs; - let xor2 = lhs ^ sum; - let and = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; - let mask = and >> width; + let xor1 = lhs ^ rhs; + let xor2 = lhs ^ sum; + let and = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; + let mask = and >> width; - let one = bx.context.new_rvalue_one(elem_ty); - let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); - let shift1 = ones << width; - let shift2 = sum >> width; - let mask_min = shift1 ^ shift2; + let one = bx.context.new_rvalue_one(elem_ty); + let ones = + bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); + let shift1 = ones << width; + let shift2 = sum >> width; + let mask_min = shift1 ^ shift2; - let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; - let and2 = mask & mask_min; + let and1 = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; + let and2 = mask & mask_min; - and1 + and2 - } - }; + and1 + and2 + } + }; return Ok(result); } @@ -968,7 +1016,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( 1.0 ); - macro_rules! minmax_red { ($name:ident: $int_red:ident, $float_red:ident) => { if name == sym::$name { @@ -979,13 +1026,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())), ty::Float(_) => Ok(bx.$float_red(args[0].immediate())), - _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { - span, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, name, symbol: sym::$name, in_ty, - in_elem, - ret_ty + in_elem, + ret_ty }), }; } @@ -1025,7 +1072,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => { let r = bx.vector_reduce_op(input, $op); - Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) }) + Ok(if !$boolean { + r + } else { + bx.icmp( + IntPredicate::IntNE, + r, + bx.context.new_rvalue_zero(r.get_type()), + ) + }) } _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, From 913fcf50ee2c4bb43b5ce7d71984be08eff3831e Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 4 Aug 2023 16:09:54 +0100 Subject: [PATCH 035/103] Use `unstable_target_features` when checking inline assembly This is necessary to properly validate register classes even when the relevant target feature name is still unstable. --- src/asm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 4c3b7f5036c..73908558cee 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -107,7 +107,7 @@ enum ConstraintOrRegister { impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { - fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], _instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) { + fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) { if options.contains(InlineAsmOptions::MAY_UNWIND) { self.sess() .create_err(UnwindingInlineAsm { span: span[0] }) @@ -173,7 +173,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let is_target_supported = reg.reg_class().supported_types(asm_arch).iter() .any(|&(_, feature)| { if let Some(feature) = feature { - self.tcx.sess.target_features.contains(&feature) + self.tcx.asm_target_features(instance.def_id()).contains(&feature) } else { true // Register class is unconditionally supported } From 46062cd68daa0f08368023c5dc29ec7cefc03370 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 4 Aug 2023 13:28:04 +0800 Subject: [PATCH 036/103] Fix ICE failed to get layout for ReferencesError --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 08507e19652..88dcafa7370 100644 --- a/src/context.rs +++ b/src/context.rs @@ -476,7 +476,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { #[inline] fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { - if let LayoutError::SizeOverflow(_) = err { + if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err { self.sess().emit_fatal(respan(span, err.into_diagnostic())) } else { span_bug!(span, "failed to get layout for `{}`: {}", ty, err) From fe6a4773a1e4848309203506977701292710f457 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 6 Aug 2023 07:20:31 -0700 Subject: [PATCH 037/103] Generate better function argument names in global_allocator expansion --- src/allocator.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/allocator.rs b/src/allocator.rs index 13f88192bbc..edd7ab722f6 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -27,8 +27,8 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam if kind == AllocatorKind::Default { for method in ALLOCATOR_METHODS { let mut types = Vec::with_capacity(method.inputs.len()); - for ty in method.inputs.iter() { - match *ty { + for input in method.inputs.iter() { + match input.ty { AllocatorTy::Layout => { types.push(usize); types.push(usize); From 9c8ae2f1536a68823bdae6304896cad2233e854d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 2 Aug 2023 12:45:52 -0700 Subject: [PATCH 038/103] Add a new `compare_bytes` intrinsic instead of calling `memcmp` directly --- src/intrinsic/mod.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 68edde13829..eca2abf2775 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -302,6 +302,20 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } } + sym::compare_bytes => { + let a = args[0].immediate(); + let b = args[1].immediate(); + let n = args[2].immediate(); + + let void_ptr_type = self.context.new_type::<*const ()>(); + let a_ptr = self.bitcast(a, void_ptr_type); + let b_ptr = self.bitcast(b, void_ptr_type); + + let builtin = self.context.get_builtin_function("memcmp"); + let cmp = self.context.new_call(None, builtin, &[a_ptr, b_ptr, n]); + self.sext(cmp, self.type_ix(32)) + } + sym::black_box => { args[0].val.store(self, result); From b132a7e6d4fb9ebf27c467a42d203a6056f22662 Mon Sep 17 00:00:00 2001 From: scottmcm Date: Fri, 4 Aug 2023 06:22:50 +0000 Subject: [PATCH 039/103] Apply suggestions from code review Co-authored-by: Ralf Jung --- src/intrinsic/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index eca2abf2775..f8c32c6dbbb 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -311,6 +311,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let a_ptr = self.bitcast(a, void_ptr_type); let b_ptr = self.bitcast(b, void_ptr_type); + // Here we assume that the `memcmp` provided by the target is a NOP for size 0. let builtin = self.context.get_builtin_function("memcmp"); let cmp = self.context.new_call(None, builtin, &[a_ptr, b_ptr, n]); self.sext(cmp, self.type_ix(32)) From fb6ec5e510e16466f6dbf93ca5f8901bf210c61e Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Mon, 7 Aug 2023 14:24:41 -0700 Subject: [PATCH 040/103] Use the same DISubprogram for each instance of the same inlined function within the caller --- src/debuginfo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index a81585d4128..d1bfd833cd8 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -55,7 +55,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _llfn: RValue<'gcc>, _mir: &mir::Body<'tcx>, - ) -> Option> { + ) -> Option> { // TODO(antoyo) None } From 43431e4db4d7e85f36dd7832a521b7b4d73e53ff Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 13 Aug 2023 09:37:32 -0400 Subject: [PATCH 041/103] Update to nightly-2023-08-12 --- Cargo.lock | 4 ++-- build_sysroot/Cargo.toml | 1 + example/alloc_example.rs | 1 + .../arbitrary_self_types_pointers_and_wrappers.rs | 1 + example/mini_core.rs | 2 +- example/mini_core_hello_world.rs | 2 +- example/mod_bench.rs | 1 + rust-toolchain | 2 +- src/builder.rs | 13 ++++--------- 9 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c8754bf675..f537ab37266 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,7 +35,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984" +source = "git+https://github.com/antoyo/gccjit.rs#814eea1a0a098d08a113794225cad301622fd7b4" dependencies = [ "gccjit_sys", ] @@ -43,7 +43,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984" +source = "git+https://github.com/antoyo/gccjit.rs#814eea1a0a098d08a113794225cad301622fd7b4" dependencies = [ "libc", ] diff --git a/build_sysroot/Cargo.toml b/build_sysroot/Cargo.toml index a84f86a8218..dca2ffdc24b 100644 --- a/build_sysroot/Cargo.toml +++ b/build_sysroot/Cargo.toml @@ -2,6 +2,7 @@ authors = ["bjorn3 "] name = "sysroot" version = "0.0.0" +resolver = "2" [dependencies] core = { path = "./sysroot_src/library/core" } diff --git a/example/alloc_example.rs b/example/alloc_example.rs index 754e7931412..f1954a30cf8 100644 --- a/example/alloc_example.rs +++ b/example/alloc_example.rs @@ -1,5 +1,6 @@ #![feature(start, core_intrinsics, alloc_error_handler, lang_items)] #![no_std] +#![allow(internal_features)] extern crate alloc; extern crate alloc_system; diff --git a/example/arbitrary_self_types_pointers_and_wrappers.rs b/example/arbitrary_self_types_pointers_and_wrappers.rs index 3af0ba09e0b..b299aa87974 100644 --- a/example/arbitrary_self_types_pointers_and_wrappers.rs +++ b/example/arbitrary_self_types_pointers_and_wrappers.rs @@ -2,6 +2,7 @@ #![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)] #![feature(rustc_attrs)] +#![allow(internal_features)] use std::{ ops::{Deref, CoerceUnsized, DispatchFromDyn}, diff --git a/example/mini_core.rs b/example/mini_core.rs index 0cd7e6047c2..58df29bb625 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -4,7 +4,7 @@ thread_local )] #![no_core] -#![allow(dead_code)] +#![allow(dead_code, internal_features)] #[no_mangle] unsafe extern "C" fn _Unwind_Resume() { diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index b93d6859706..c3aea571815 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -5,7 +5,7 @@ extern_types, thread_local )] #![no_core] -#![allow(dead_code, non_camel_case_types)] +#![allow(dead_code, internal_features, non_camel_case_types)] extern crate mini_core; diff --git a/example/mod_bench.rs b/example/mod_bench.rs index 5e2e7f25a2c..c60bc7fb724 100644 --- a/example/mod_bench.rs +++ b/example/mod_bench.rs @@ -1,5 +1,6 @@ #![feature(start, core_intrinsics, lang_items)] #![no_std] +#![allow(internal_features)] #[link(name = "c")] extern {} diff --git a/rust-toolchain b/rust-toolchain index ebb04d0069c..1b60d708007 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-06-19" +channel = "nightly-2023-08-12" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/builder.rs b/src/builder.rs index 0b1f2fe6a87..05318be3e1b 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -247,16 +247,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } fn check_store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> { - let dest_ptr_ty = self.cx.val_ty(ptr).make_pointer(); // TODO(antoyo): make sure make_pointer() is okay here. let stored_ty = self.cx.val_ty(val); let stored_ptr_ty = self.cx.type_ptr_to(stored_ty); - - if dest_ptr_ty == stored_ptr_ty { - ptr - } - else { - self.bitcast(ptr, stored_ptr_ty) - } + self.bitcast(ptr, stored_ptr_ty) } pub fn current_func(&self) -> Function<'gcc> { @@ -916,7 +909,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { .add_eval(None, self.context.new_call(None, atomic_store, &[ptr, value, ordering])); } - fn gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> { + fn gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> { + // NOTE: due to opaque pointers now being used, we need to cast here. + let ptr = self.context.new_cast(None, ptr, typ.make_pointer()); let ptr_type = ptr.get_type(); let mut pointee_type = ptr.get_type(); // NOTE: we cannot use array indexing here like in inbounds_gep because array indexing is From 814c2e2ceae0fe4d061c2ae9a772c7633549f76b Mon Sep 17 00:00:00 2001 From: Dirreke Date: Thu, 13 Jul 2023 22:19:59 +0800 Subject: [PATCH 042/103] add a csky-unknown-linux-gnuabiv2 target --- example/alloc_system.rs | 1 + src/asm.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/example/alloc_system.rs b/example/alloc_system.rs index e756b347e89..3deef419f42 100644 --- a/example/alloc_system.rs +++ b/example/alloc_system.rs @@ -12,6 +12,7 @@ target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc", + target_arch = "csky" target_arch = "powerpc64"))] const MIN_ALIGN: usize = 8; #[cfg(any(target_arch = "x86_64", diff --git a/src/asm.rs b/src/asm.rs index 4c3b7f5036c..0482a85f5f3 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -597,6 +597,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r" InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r", @@ -673,6 +675,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Msp430(_) => unimplemented!(), @@ -860,6 +864,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option InlineAsmRegClass::S390x(_) => None, InlineAsmRegClass::Msp430(_) => None, InlineAsmRegClass::M68k(_) => None, + InlineAsmRegClass::CSKY(_) => None, InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } From e3deac5c710b56846539635c4d986fd1875d7a9d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 13 Aug 2023 15:34:21 -0400 Subject: [PATCH 043/103] Fix tests --- src/base.rs | 3 +++ src/int.rs | 8 +++++++- tests/run/abort1.rs | 1 + tests/run/abort2.rs | 1 + tests/run/array.rs | 1 + tests/run/assign.rs | 2 +- tests/run/closure.rs | 1 + tests/run/condition.rs | 1 + tests/run/empty_main.rs | 1 + tests/run/exit.rs | 1 + tests/run/exit_code.rs | 1 + tests/run/fun_ptr.rs | 1 + tests/run/int_overflow.rs | 2 +- tests/run/mut_ref.rs | 2 +- tests/run/operations.rs | 2 +- tests/run/ptr_cast.rs | 1 + tests/run/return-tuple.rs | 1 + tests/run/slice.rs | 1 + tests/run/static.rs | 1 + tests/run/structs.rs | 1 + tests/run/tuple.rs | 1 + 21 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/base.rs b/src/base.rs index ac17d23555d..17a08a636ea 100644 --- a/src/base.rs +++ b/src/base.rs @@ -144,6 +144,9 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") { context.add_command_line_option("-fdump-rtl-vregs"); } + if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-rtl-all"); + } if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") { context.add_command_line_option("-fdump-tree-all"); } diff --git a/src/int.rs b/src/int.rs index 0cf1204791d..2a6b1d17a3e 100644 --- a/src/int.rs +++ b/src/int.rs @@ -546,7 +546,12 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } pub fn gcc_uint(&self, typ: Type<'gcc>, int: u64) -> RValue<'gcc> { - if self.is_native_int_type_or_bool(typ) { + if typ.is_u128(self) { + // FIXME(antoyo): libgccjit cannot create 128-bit values yet. + let num = self.context.new_rvalue_from_long(self.u64_type, int as i64); + self.gcc_int_cast(num, typ) + } + else if self.is_native_int_type_or_bool(typ) { self.context.new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64) } else { @@ -572,6 +577,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } } else if typ.is_i128(self) { + // FIXME(antoyo): libgccjit cannot create 128-bit values yet. let num = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64); self.gcc_int_cast(num, typ) } diff --git a/tests/run/abort1.rs b/tests/run/abort1.rs index 25041d93e74..6cb3dd90203 100644 --- a/tests/run/abort1.rs +++ b/tests/run/abort1.rs @@ -4,6 +4,7 @@ // status: signal #![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/abort2.rs b/tests/run/abort2.rs index e7443c8dbe5..b7a928166b8 100644 --- a/tests/run/abort2.rs +++ b/tests/run/abort2.rs @@ -4,6 +4,7 @@ // status: signal #![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/array.rs b/tests/run/array.rs index 49b28d98f2f..d2d60b75e63 100644 --- a/tests/run/array.rs +++ b/tests/run/array.rs @@ -8,6 +8,7 @@ // 10 #![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/assign.rs b/tests/run/assign.rs index 427c1a25033..241acea5e49 100644 --- a/tests/run/assign.rs +++ b/tests/run/assign.rs @@ -5,7 +5,7 @@ // 7 8 // 10 -#![allow(unused_attributes)] +#![allow(internal_features, unused_attributes)] #![feature(auto_traits, lang_items, no_core, start, intrinsics, track_caller)] #![no_std] diff --git a/tests/run/closure.rs b/tests/run/closure.rs index 8daa681abf7..764c5b34426 100644 --- a/tests/run/closure.rs +++ b/tests/run/closure.rs @@ -10,6 +10,7 @@ #![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, unboxed_closures)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/condition.rs b/tests/run/condition.rs index b7a13081dea..ed17c19409e 100644 --- a/tests/run/condition.rs +++ b/tests/run/condition.rs @@ -6,6 +6,7 @@ // 1 #![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/empty_main.rs b/tests/run/empty_main.rs index c02cfd2a85f..2d78ef12aa7 100644 --- a/tests/run/empty_main.rs +++ b/tests/run/empty_main.rs @@ -4,6 +4,7 @@ // status: 0 #![feature(auto_traits, lang_items, no_core, start)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/exit.rs b/tests/run/exit.rs index 956e53dd4aa..bf1cbeef302 100644 --- a/tests/run/exit.rs +++ b/tests/run/exit.rs @@ -4,6 +4,7 @@ // status: 2 #![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/exit_code.rs b/tests/run/exit_code.rs index eeab3520951..be7a233efda 100644 --- a/tests/run/exit_code.rs +++ b/tests/run/exit_code.rs @@ -4,6 +4,7 @@ // status: 1 #![feature(auto_traits, lang_items, no_core, start)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/fun_ptr.rs b/tests/run/fun_ptr.rs index 8a196f774c8..e0c30cada6b 100644 --- a/tests/run/fun_ptr.rs +++ b/tests/run/fun_ptr.rs @@ -5,6 +5,7 @@ // stdout: 1 #![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/int_overflow.rs b/tests/run/int_overflow.rs index c3fcb3c0a2a..badcc0f7699 100644 --- a/tests/run/int_overflow.rs +++ b/tests/run/int_overflow.rs @@ -4,7 +4,7 @@ // stdout: Success // status: signal -#![allow(unused_attributes)] +#![allow(internal_features, unused_attributes)] #![feature(auto_traits, lang_items, no_core, start, intrinsics)] #![no_std] diff --git a/tests/run/mut_ref.rs b/tests/run/mut_ref.rs index 2a2ea8b8bf0..e843e298537 100644 --- a/tests/run/mut_ref.rs +++ b/tests/run/mut_ref.rs @@ -7,7 +7,7 @@ // 6 // 11 -#![allow(unused_attributes)] +#![allow(internal_features, unused_attributes)] #![feature(auto_traits, lang_items, no_core, start, intrinsics, track_caller)] #![no_std] diff --git a/tests/run/operations.rs b/tests/run/operations.rs index 67b9f241dbb..cac6fdfca4a 100644 --- a/tests/run/operations.rs +++ b/tests/run/operations.rs @@ -5,7 +5,7 @@ // 39 // 10 -#![allow(unused_attributes)] +#![allow(internal_features, unused_attributes)] #![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types)] #![no_std] diff --git a/tests/run/ptr_cast.rs b/tests/run/ptr_cast.rs index da8a8295d56..41866179828 100644 --- a/tests/run/ptr_cast.rs +++ b/tests/run/ptr_cast.rs @@ -5,6 +5,7 @@ // stdout: 1 #![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/return-tuple.rs b/tests/run/return-tuple.rs index 6fa10dca06f..8d40deb8c85 100644 --- a/tests/run/return-tuple.rs +++ b/tests/run/return-tuple.rs @@ -7,6 +7,7 @@ // 42 #![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/slice.rs b/tests/run/slice.rs index 96f1c4792e5..25ff72549d4 100644 --- a/tests/run/slice.rs +++ b/tests/run/slice.rs @@ -5,6 +5,7 @@ // stdout: 5 #![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/static.rs b/tests/run/static.rs index 19201f1df26..2457bb1f443 100644 --- a/tests/run/static.rs +++ b/tests/run/static.rs @@ -10,6 +10,7 @@ // 1 #![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/structs.rs b/tests/run/structs.rs index 6c8884855ac..d6455667400 100644 --- a/tests/run/structs.rs +++ b/tests/run/structs.rs @@ -6,6 +6,7 @@ // 2 #![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] diff --git a/tests/run/tuple.rs b/tests/run/tuple.rs index 0b670bf2674..8a7d85ae867 100644 --- a/tests/run/tuple.rs +++ b/tests/run/tuple.rs @@ -5,6 +5,7 @@ // stdout: 3 #![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![allow(internal_features)] #![no_std] #![no_core] From 542c82ec37593a63eec9f8f25559f6fee641c833 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 15 Aug 2023 11:25:38 -0400 Subject: [PATCH 044/103] Fix for libgccjit 12 --- Cargo.lock | 57 ++++++++++-------------------------- Cargo.toml | 2 ++ src/base.rs | 6 +++- src/builder.rs | 2 +- src/intrinsic/mod.rs | 4 +-- src/lib.rs | 69 ++++++++++++++++++++++++++++++++++---------- 6 files changed, 79 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9f007c569da..7fcb124927a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,18 +11,18 @@ dependencies = [ "memchr", ] -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "cc" version = "1.0.79" @@ -58,12 +58,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" [[package]] name = "fm" @@ -105,26 +102,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", -] - [[package]] name = "lang_tester" version = "0.3.13" @@ -149,9 +126,9 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "memchr" @@ -175,7 +152,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -207,13 +184,12 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.22" +version = "0.38.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8818fa822adcc98b18fedbb3632a6a33213c070556b5aa7c4c8cc21cff565c4c" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" dependencies = [ - "bitflags", + "bitflags 2.4.0", "errno", - "io-lifetimes", "libc", "linux-raw-sys", "windows-sys", @@ -236,11 +212,10 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "tempfile" -version = "3.6.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" dependencies = [ - "autocfg", "cfg-if", "fastrand", "redox_syscall", diff --git a/Cargo.toml b/Cargo.toml index 81066d9ce1f..3bf629fc662 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,8 @@ gccjit = { git = "https://github.com/antoyo/gccjit.rs" } #gccjit = { path = "../gccjit.rs" } smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } +# TODO(antoyo): make tempfile optional. +tempfile = "3.7.1" [dev-dependencies] lang_tester = "0.3.9" diff --git a/src/base.rs b/src/base.rs index 17a08a636ea..bf0309fea14 100644 --- a/src/base.rs +++ b/src/base.rs @@ -6,8 +6,10 @@ use std::time::Instant; use gccjit::{ Context, FunctionType, - GlobalKind, TargetInfo, + GlobalKind, }; +#[cfg(feature="master")] +use gccjit::TargetInfo; use rustc_middle::dep_graph; use rustc_middle::ty::TyCtxt; #[cfg(feature="master")] @@ -20,6 +22,8 @@ use rustc_codegen_ssa::traits::DebugInfoMethods; use rustc_session::config::DebugInfo; use rustc_span::Symbol; +#[cfg(not(feature="master"))] +use crate::TargetInfo; use crate::GccContext; use crate::builder::Builder; use crate::context::CodegenCx; diff --git a/src/builder.rs b/src/builder.rs index 05318be3e1b..b0feb99e3c6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -493,7 +493,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } #[cfg(not(feature="master"))] - fn invoke(&mut self, typ: Type<'gcc>, fn_attrs: &CodegenFnAttrs, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> { + fn invoke(&mut self, typ: Type<'gcc>, fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> { let call_site = self.call(typ, fn_attrs, None, func, args, None); let condition = self.context.new_rvalue_from_int(self.bool_type, 1); self.llbb().end_with_conditional(None, condition, then, catch); diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index f8c32c6dbbb..fab5cba6476 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -10,9 +10,9 @@ use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; -use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods}; +use rustc_codegen_ssa::traits::{ArgAbiMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods}; #[cfg(feature="master")] -use rustc_codegen_ssa::traits::MiscMethods; +use rustc_codegen_ssa::traits::{BaseTypeMethods, MiscMethods}; use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_middle::bug; use rustc_middle::ty::{self, Instance, Ty}; diff --git a/src/lib.rs b/src/lib.rs index a74d503d8c8..7b55a4e4082 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,9 +64,15 @@ mod type_of; use std::any::Any; use std::sync::Arc; +#[cfg(not(feature="master"))] +use std::sync::atomic::{AtomicBool, Ordering}; use crate::errors::LTONotSupported; -use gccjit::{Context, OptimizationLevel, TargetInfo}; +use gccjit::{Context, OptimizationLevel}; +#[cfg(feature="master")] +use gccjit::TargetInfo; +#[cfg(not(feature="master"))] +use gccjit::CType; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; use rustc_codegen_ssa::base::codegen_crate; @@ -85,6 +91,8 @@ use rustc_session::config::{Lto, OptLevel, OutputFilenames}; use rustc_session::Session; use rustc_span::Symbol; use rustc_span::fatal_error::FatalError; +#[cfg(not(feature="master"))] +use tempfile::TempDir; fluent_messages! { "../messages.ftl" } @@ -98,6 +106,23 @@ impl String> Drop for PrintOnPanic { } } +#[cfg(not(feature="master"))] +#[derive(Debug)] +pub struct TargetInfo { + supports_128bit_integers: AtomicBool, +} + +#[cfg(not(feature="master"))] +impl TargetInfo { + fn cpu_supports(&self, _feature: &str) -> bool { + false + } + + fn supports_128bit_int(&self) -> bool { + self.supports_128bit_integers.load(Ordering::SeqCst) + } +} + #[derive(Clone)] pub struct GccCodegenBackend { target_info: Arc, @@ -114,6 +139,18 @@ impl CodegenBackend for GccCodegenBackend { if sess.lto() != Lto::No { sess.emit_warning(LTONotSupported {}); } + + #[cfg(not(feature="master"))] + { + let temp_dir = TempDir::new().expect("cannot create temporary directory"); + let temp_file = temp_dir.into_path().join("result.asm"); + let check_context = Context::default(); + check_context.set_print_errors_to_stderr(false); + let _int128_ty = check_context.new_c_type(CType::UInt128t); + // NOTE: we cannot just call compile() as this would require other files than libgccjit.so. + check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str")); + self.target_info.supports_128bit_integers.store(check_context.get_last_error() == Ok(None), Ordering::SeqCst); + } } fn provide(&self, providers: &mut Providers) { @@ -266,14 +303,21 @@ impl WriteBackendMethods for GccCodegenBackend { /// This is the entrypoint for a hot plugged rustc_codegen_gccjit #[no_mangle] pub fn __rustc_codegen_backend() -> Box { - // Get the native arch and check whether the target supports 128-bit integers. - let context = Context::default(); - let arch = context.get_target_info().arch().unwrap(); + #[cfg(feature="master")] + let target_info = { + // Get the native arch and check whether the target supports 128-bit integers. + let context = Context::default(); + let arch = context.get_target_info().arch().unwrap(); - // Get the second TargetInfo with the correct CPU features by setting the arch. - let context = Context::default(); - context.add_driver_option(&format!("-march={}", arch.to_str().unwrap())); - let target_info = Arc::new(context.get_target_info()); + // Get the second TargetInfo with the correct CPU features by setting the arch. + let context = Context::default(); + context.add_driver_option(&format!("-march={}", arch.to_str().unwrap())); + Arc::new(context.get_target_info()) + }; + #[cfg(not(feature="master"))] + let target_info = Arc::new(TargetInfo { + supports_128bit_integers: AtomicBool::new(false), + }); Box::new(GccCodegenBackend { target_info, @@ -319,14 +363,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &Arc Date: Tue, 15 Aug 2023 12:41:35 -0400 Subject: [PATCH 045/103] Fix tests --- .github/workflows/stdarch.yml | 4 ++-- failing-ui-tests.txt | 3 +++ test.sh | 6 +++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 556c6444833..21b6a0d3a93 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -133,10 +133,10 @@ jobs: if: ${{ !matrix.cargo_runner }} run: | cd build_sysroot/sysroot_src/library/stdarch/ - CHANNEL=release TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test + CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test - name: Run stdarch tests if: ${{ matrix.cargo_runner }} run: | cd build_sysroot/sysroot_src/library/stdarch/ - STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a + STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a diff --git a/failing-ui-tests.txt b/failing-ui-tests.txt index 69f57036b01..fe0df3347bb 100644 --- a/failing-ui-tests.txt +++ b/failing-ui-tests.txt @@ -67,3 +67,6 @@ tests/ui/issues/issue-29948.rs tests/ui/panic-while-printing.rs tests/ui/enum-discriminant/get_discr.rs tests/ui/panics/nested_panic_caught.rs +tests/ui/simd/intrinsic/generic-bswap-byte.rs +tests/ui/const_prop/ice-issue-111353.rs +tests/ui/process/println-with-broken-pipe.rs diff --git a/test.sh b/test.sh index 592997b8ab9..1054fdf7ea1 100755 --- a/test.sh +++ b/test.sh @@ -346,7 +346,9 @@ function test_rustc() { git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed rm -r tests/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,borrowck/,chalkify/bugs/,test*,*lto*.rs,consts/const-float-bits-reject-conv.rs,consts/issue-miri-1910.rs} || true - rm tests/ui/mir/mir_heavy_promoted.rs # this tests is oom-killed in the CI. + rm tests/ui/mir/mir_heavy_promoted.rs # this test is oom-killed in the CI. + # Tests generating errors. + rm tests/ui/consts/const-eval/nonnull_as_ref_ub.rs tests/ui/consts/issue-94675.rs for test in $(rg --files-with-matches "thread|lto" tests/ui); do rm $test done @@ -354,6 +356,8 @@ function test_rustc() { git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs git checkout tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs + git checkout tests/ui/imports/ambiguous-1.rs + git checkout tests/ui/imports/ambiguous-4-extern.rs RUSTC_ARGS="$TEST_FLAGS -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot" From 033dc1f2080551c0f27d24550444d79d8d945ee2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 11 Aug 2023 15:39:01 +0200 Subject: [PATCH 046/103] Regenerate intrinsics --- src/intrinsic/archs.rs | 114 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 106 insertions(+), 8 deletions(-) diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 438eab78943..e01299d32fd 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -2254,6 +2254,42 @@ match name { "llvm.hexagon.prefetch" => "__builtin_HEXAGON_prefetch", "llvm.hexagon.vmemcpy" => "__builtin_hexagon_vmemcpy", "llvm.hexagon.vmemset" => "__builtin_hexagon_vmemset", + // loongarch + "llvm.loongarch.asrtgt.d" => "__builtin_loongarch_asrtgt_d", + "llvm.loongarch.asrtle.d" => "__builtin_loongarch_asrtle_d", + "llvm.loongarch.break" => "__builtin_loongarch_break", + "llvm.loongarch.cacop.d" => "__builtin_loongarch_cacop_d", + "llvm.loongarch.cacop.w" => "__builtin_loongarch_cacop_w", + "llvm.loongarch.cpucfg" => "__builtin_loongarch_cpucfg", + "llvm.loongarch.crc.w.b.w" => "__builtin_loongarch_crc_w_b_w", + "llvm.loongarch.crc.w.d.w" => "__builtin_loongarch_crc_w_d_w", + "llvm.loongarch.crc.w.h.w" => "__builtin_loongarch_crc_w_h_w", + "llvm.loongarch.crc.w.w.w" => "__builtin_loongarch_crc_w_w_w", + "llvm.loongarch.crcc.w.b.w" => "__builtin_loongarch_crcc_w_b_w", + "llvm.loongarch.crcc.w.d.w" => "__builtin_loongarch_crcc_w_d_w", + "llvm.loongarch.crcc.w.h.w" => "__builtin_loongarch_crcc_w_h_w", + "llvm.loongarch.crcc.w.w.w" => "__builtin_loongarch_crcc_w_w_w", + "llvm.loongarch.csrrd.d" => "__builtin_loongarch_csrrd_d", + "llvm.loongarch.csrrd.w" => "__builtin_loongarch_csrrd_w", + "llvm.loongarch.csrwr.d" => "__builtin_loongarch_csrwr_d", + "llvm.loongarch.csrwr.w" => "__builtin_loongarch_csrwr_w", + "llvm.loongarch.csrxchg.d" => "__builtin_loongarch_csrxchg_d", + "llvm.loongarch.csrxchg.w" => "__builtin_loongarch_csrxchg_w", + "llvm.loongarch.dbar" => "__builtin_loongarch_dbar", + "llvm.loongarch.ibar" => "__builtin_loongarch_ibar", + "llvm.loongarch.iocsrrd.b" => "__builtin_loongarch_iocsrrd_b", + "llvm.loongarch.iocsrrd.d" => "__builtin_loongarch_iocsrrd_d", + "llvm.loongarch.iocsrrd.h" => "__builtin_loongarch_iocsrrd_h", + "llvm.loongarch.iocsrrd.w" => "__builtin_loongarch_iocsrrd_w", + "llvm.loongarch.iocsrwr.b" => "__builtin_loongarch_iocsrwr_b", + "llvm.loongarch.iocsrwr.d" => "__builtin_loongarch_iocsrwr_d", + "llvm.loongarch.iocsrwr.h" => "__builtin_loongarch_iocsrwr_h", + "llvm.loongarch.iocsrwr.w" => "__builtin_loongarch_iocsrwr_w", + "llvm.loongarch.lddir.d" => "__builtin_loongarch_lddir_d", + "llvm.loongarch.ldpte.d" => "__builtin_loongarch_ldpte_d", + "llvm.loongarch.movfcsr2gr" => "__builtin_loongarch_movfcsr2gr", + "llvm.loongarch.movgr2fcsr" => "__builtin_loongarch_movgr2fcsr", + "llvm.loongarch.syscall" => "__builtin_loongarch_syscall", // mips "llvm.mips.absq.s.ph" => "__builtin_mips_absq_s_ph", "llvm.mips.absq.s.qb" => "__builtin_mips_absq_s_qb", @@ -2954,6 +2990,8 @@ match name { "llvm.nvvm.barrier0.and" => "__nvvm_bar0_and", "llvm.nvvm.barrier0.or" => "__nvvm_bar0_or", "llvm.nvvm.barrier0.popc" => "__nvvm_bar0_popc", + "llvm.nvvm.bf2h.rn" => "__nvvm_bf2h_rn", + "llvm.nvvm.bf2h.rn.ftz" => "__nvvm_bf2h_rn_ftz", "llvm.nvvm.bitcast.d2ll" => "__nvvm_bitcast_d2ll", "llvm.nvvm.bitcast.f2i" => "__nvvm_bitcast_f2i", "llvm.nvvm.bitcast.i2f" => "__nvvm_bitcast_i2f", @@ -3016,8 +3054,6 @@ match name { "llvm.nvvm.div.rz.ftz.f" => "__nvvm_div_rz_ftz_f", "llvm.nvvm.ex2.approx.d" => "__nvvm_ex2_approx_d", "llvm.nvvm.ex2.approx.f" => "__nvvm_ex2_approx_f", - "llvm.nvvm.ex2.approx.f16" => "__nvvm_ex2_approx_f16", - "llvm.nvvm.ex2.approx.f16x2" => "__nvvm_ex2_approx_f16x2", "llvm.nvvm.ex2.approx.ftz.f" => "__nvvm_ex2_approx_ftz_f", "llvm.nvvm.f2bf16.rn" => "__nvvm_f2bf16_rn", "llvm.nvvm.f2bf16.rn.relu" => "__nvvm_f2bf16_rn_relu", @@ -3079,11 +3115,17 @@ match name { "llvm.nvvm.fma.rn.bf16x2" => "__nvvm_fma_rn_bf16x2", "llvm.nvvm.fma.rn.d" => "__nvvm_fma_rn_d", "llvm.nvvm.fma.rn.f" => "__nvvm_fma_rn_f", - "llvm.nvvm.fma.rn.f16" => "__nvvm_fma_rn_f16", - "llvm.nvvm.fma.rn.f16x2" => "__nvvm_fma_rn_f16x2", + "llvm.nvvm.fma.rn.ftz.bf16" => "__nvvm_fma_rn_ftz_bf16", + "llvm.nvvm.fma.rn.ftz.bf16x2" => "__nvvm_fma_rn_ftz_bf16x2", "llvm.nvvm.fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f", + "llvm.nvvm.fma.rn.ftz.relu.bf16" => "__nvvm_fma_rn_ftz_relu_bf16", + "llvm.nvvm.fma.rn.ftz.relu.bf16x2" => "__nvvm_fma_rn_ftz_relu_bf16x2", + "llvm.nvvm.fma.rn.ftz.sat.bf16" => "__nvvm_fma_rn_ftz_sat_bf16", + "llvm.nvvm.fma.rn.ftz.sat.bf16x2" => "__nvvm_fma_rn_ftz_sat_bf16x2", "llvm.nvvm.fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16", "llvm.nvvm.fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2", + "llvm.nvvm.fma.rn.sat.bf16" => "__nvvm_fma_rn_sat_bf16", + "llvm.nvvm.fma.rn.sat.bf16x2" => "__nvvm_fma_rn_sat_bf16x2", "llvm.nvvm.fma.rp.d" => "__nvvm_fma_rp_d", "llvm.nvvm.fma.rp.f" => "__nvvm_fma_rp_f", "llvm.nvvm.fma.rp.ftz.f" => "__nvvm_fma_rp_ftz_f", @@ -3094,11 +3136,17 @@ match name { "llvm.nvvm.fmax.bf16x2" => "__nvvm_fmax_bf16x2", "llvm.nvvm.fmax.d" => "__nvvm_fmax_d", "llvm.nvvm.fmax.f" => "__nvvm_fmax_f", - "llvm.nvvm.fmax.f16" => "__nvvm_fmax_f16", - "llvm.nvvm.fmax.f16x2" => "__nvvm_fmax_f16x2", + "llvm.nvvm.fmax.ftz.bf16" => "__nvvm_fmax_ftz_bf16", + "llvm.nvvm.fmax.ftz.bf16x2" => "__nvvm_fmax_ftz_bf16x2", "llvm.nvvm.fmax.ftz.f" => "__nvvm_fmax_ftz_f", + "llvm.nvvm.fmax.ftz.nan.bf16" => "__nvvm_fmax_ftz_nan_bf16", + "llvm.nvvm.fmax.ftz.nan.bf16x2" => "__nvvm_fmax_ftz_nan_bf16x2", "llvm.nvvm.fmax.ftz.nan.f" => "__nvvm_fmax_ftz_nan_f", + "llvm.nvvm.fmax.ftz.nan.xorsign.abs.bf16" => "__nvvm_fmax_ftz_nan_xorsign_abs_bf16", + "llvm.nvvm.fmax.ftz.nan.xorsign.abs.bf16x2" => "__nvvm_fmax_ftz_nan_xorsign_abs_bf16x2", "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f" => "__nvvm_fmax_ftz_nan_xorsign_abs_f", + "llvm.nvvm.fmax.ftz.xorsign.abs.bf16" => "__nvvm_fmax_ftz_xorsign_abs_bf16", + "llvm.nvvm.fmax.ftz.xorsign.abs.bf16x2" => "__nvvm_fmax_ftz_xorsign_abs_bf16x2", "llvm.nvvm.fmax.ftz.xorsign.abs.f" => "__nvvm_fmax_ftz_xorsign_abs_f", "llvm.nvvm.fmax.nan.bf16" => "__nvvm_fmax_nan_bf16", "llvm.nvvm.fmax.nan.bf16x2" => "__nvvm_fmax_nan_bf16x2", @@ -3113,11 +3161,17 @@ match name { "llvm.nvvm.fmin.bf16x2" => "__nvvm_fmin_bf16x2", "llvm.nvvm.fmin.d" => "__nvvm_fmin_d", "llvm.nvvm.fmin.f" => "__nvvm_fmin_f", - "llvm.nvvm.fmin.f16" => "__nvvm_fmin_f16", - "llvm.nvvm.fmin.f16x2" => "__nvvm_fmin_f16x2", + "llvm.nvvm.fmin.ftz.bf16" => "__nvvm_fmin_ftz_bf16", + "llvm.nvvm.fmin.ftz.bf16x2" => "__nvvm_fmin_ftz_bf16x2", "llvm.nvvm.fmin.ftz.f" => "__nvvm_fmin_ftz_f", + "llvm.nvvm.fmin.ftz.nan.bf16" => "__nvvm_fmin_ftz_nan_bf16", + "llvm.nvvm.fmin.ftz.nan.bf16x2" => "__nvvm_fmin_ftz_nan_bf16x2", "llvm.nvvm.fmin.ftz.nan.f" => "__nvvm_fmin_ftz_nan_f", + "llvm.nvvm.fmin.ftz.nan.xorsign.abs.bf16" => "__nvvm_fmin_ftz_nan_xorsign_abs_bf16", + "llvm.nvvm.fmin.ftz.nan.xorsign.abs.bf16x2" => "__nvvm_fmin_ftz_nan_xorsign_abs_bf16x2", "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f" => "__nvvm_fmin_ftz_nan_xorsign_abs_f", + "llvm.nvvm.fmin.ftz.xorsign.abs.bf16" => "__nvvm_fmin_ftz_xorsign_abs_bf16", + "llvm.nvvm.fmin.ftz.xorsign.abs.bf16x2" => "__nvvm_fmin_ftz_xorsign_abs_bf16x2", "llvm.nvvm.fmin.ftz.xorsign.abs.f" => "__nvvm_fmin_ftz_xorsign_abs_f", "llvm.nvvm.fmin.nan.bf16" => "__nvvm_fmin_nan_bf16", "llvm.nvvm.fmin.nan.bf16x2" => "__nvvm_fmin_nan_bf16x2", @@ -4213,6 +4267,28 @@ match name { "llvm.r600.read.tgid.x" => "__builtin_r600_read_tgid_x", "llvm.r600.read.tgid.y" => "__builtin_r600_read_tgid_y", "llvm.r600.read.tgid.z" => "__builtin_r600_read_tgid_z", + // riscv + "llvm.riscv.aes32dsi" => "__builtin_riscv_aes32dsi", + "llvm.riscv.aes32dsmi" => "__builtin_riscv_aes32dsmi", + "llvm.riscv.aes32esi" => "__builtin_riscv_aes32esi", + "llvm.riscv.aes32esmi" => "__builtin_riscv_aes32esmi", + "llvm.riscv.aes64ds" => "__builtin_riscv_aes64ds", + "llvm.riscv.aes64dsm" => "__builtin_riscv_aes64dsm", + "llvm.riscv.aes64es" => "__builtin_riscv_aes64es", + "llvm.riscv.aes64esm" => "__builtin_riscv_aes64esm", + "llvm.riscv.aes64im" => "__builtin_riscv_aes64im", + "llvm.riscv.aes64ks1i" => "__builtin_riscv_aes64ks1i", + "llvm.riscv.aes64ks2" => "__builtin_riscv_aes64ks2", + "llvm.riscv.sha512sig0" => "__builtin_riscv_sha512sig0", + "llvm.riscv.sha512sig0h" => "__builtin_riscv_sha512sig0h", + "llvm.riscv.sha512sig0l" => "__builtin_riscv_sha512sig0l", + "llvm.riscv.sha512sig1" => "__builtin_riscv_sha512sig1", + "llvm.riscv.sha512sig1h" => "__builtin_riscv_sha512sig1h", + "llvm.riscv.sha512sig1l" => "__builtin_riscv_sha512sig1l", + "llvm.riscv.sha512sum0" => "__builtin_riscv_sha512sum0", + "llvm.riscv.sha512sum0r" => "__builtin_riscv_sha512sum0r", + "llvm.riscv.sha512sum1" => "__builtin_riscv_sha512sum1", + "llvm.riscv.sha512sum1r" => "__builtin_riscv_sha512sum1r", // s390 "llvm.s390.efpc" => "__builtin_s390_efpc", "llvm.s390.etnd" => "__builtin_tx_nesting_depth", @@ -5912,6 +5988,18 @@ match name { "llvm.x86.avx2.vpdpbuud.256" => "__builtin_ia32_vpdpbuud256", "llvm.x86.avx2.vpdpbuuds.128" => "__builtin_ia32_vpdpbuuds128", "llvm.x86.avx2.vpdpbuuds.256" => "__builtin_ia32_vpdpbuuds256", + "llvm.x86.avx2.vpdpwsud.128" => "__builtin_ia32_vpdpwsud128", + "llvm.x86.avx2.vpdpwsud.256" => "__builtin_ia32_vpdpwsud256", + "llvm.x86.avx2.vpdpwsuds.128" => "__builtin_ia32_vpdpwsuds128", + "llvm.x86.avx2.vpdpwsuds.256" => "__builtin_ia32_vpdpwsuds256", + "llvm.x86.avx2.vpdpwusd.128" => "__builtin_ia32_vpdpwusd128", + "llvm.x86.avx2.vpdpwusd.256" => "__builtin_ia32_vpdpwusd256", + "llvm.x86.avx2.vpdpwusds.128" => "__builtin_ia32_vpdpwusds128", + "llvm.x86.avx2.vpdpwusds.256" => "__builtin_ia32_vpdpwusds256", + "llvm.x86.avx2.vpdpwuud.128" => "__builtin_ia32_vpdpwuud128", + "llvm.x86.avx2.vpdpwuud.256" => "__builtin_ia32_vpdpwuud256", + "llvm.x86.avx2.vpdpwuuds.128" => "__builtin_ia32_vpdpwuuds128", + "llvm.x86.avx2.vpdpwuuds.256" => "__builtin_ia32_vpdpwuuds256", "llvm.x86.avx2.vperm2i128" => "__builtin_ia32_permti256", "llvm.x86.avx512.add.pd.512" => "__builtin_ia32_addpd512", "llvm.x86.avx512.add.ps.512" => "__builtin_ia32_addps512", @@ -7909,6 +7997,16 @@ match name { "llvm.x86.vgf2p8mulb.128" => "__builtin_ia32_vgf2p8mulb_v16qi", "llvm.x86.vgf2p8mulb.256" => "__builtin_ia32_vgf2p8mulb_v32qi", "llvm.x86.vgf2p8mulb.512" => "__builtin_ia32_vgf2p8mulb_v64qi", + "llvm.x86.vsha512msg1" => "__builtin_ia32_vsha512msg1", + "llvm.x86.vsha512msg2" => "__builtin_ia32_vsha512msg2", + "llvm.x86.vsha512rnds2" => "__builtin_ia32_vsha512rnds2", + "llvm.x86.vsm3msg1" => "__builtin_ia32_vsm3msg1", + "llvm.x86.vsm3msg2" => "__builtin_ia32_vsm3msg2", + "llvm.x86.vsm3rnds2" => "__builtin_ia32_vsm3rnds2", + "llvm.x86.vsm4key4128" => "__builtin_ia32_vsm4key4128", + "llvm.x86.vsm4key4256" => "__builtin_ia32_vsm4key4256", + "llvm.x86.vsm4rnds4128" => "__builtin_ia32_vsm4rnds4128", + "llvm.x86.vsm4rnds4256" => "__builtin_ia32_vsm4rnds4256", "llvm.x86.wbinvd" => "__builtin_ia32_wbinvd", "llvm.x86.wbnoinvd" => "__builtin_ia32_wbnoinvd", "llvm.x86.wrfsbase.32" => "__builtin_ia32_wrfsbase32", From d929cf8ef16cce18b9446a718c6f13e735c2f290 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 11 Aug 2023 15:40:36 +0200 Subject: [PATCH 047/103] Display run commands when using `llvm-tblgen` --- tools/generate_intrinsics.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 83abe145e64..90fb7bfad27 100644 --- a/tools/generate_intrinsics.py +++ b/tools/generate_intrinsics.py @@ -46,10 +46,10 @@ def convert_to_string(content): def extract_instrinsics_from_llvm(llvm_path, intrinsics): - p = subprocess.Popen( - ["llvm-tblgen", "llvm/IR/Intrinsics.td"], - cwd=os.path.join(llvm_path, "llvm/include"), - stdout=subprocess.PIPE) + command = ["llvm-tblgen", "llvm/IR/Intrinsics.td"] + cwd = os.path.join(llvm_path, "llvm/include") + print("=> Running command `{}` from `{}`".format(command, cwd)) + p = subprocess.Popen(command, cwd=cwd, stdout=subprocess.PIPE) output, err = p.communicate() lines = convert_to_string(output).splitlines() pos = 0 From 4cbf1c76ff0d8b35c08a841aadee52f26be564d1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 15 Aug 2023 22:28:52 +0200 Subject: [PATCH 048/103] Fix command to run custom rustc --- Readme.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 55daad6dcd0..254aad61123 100644 --- a/Readme.md +++ b/Readme.md @@ -77,12 +77,16 @@ $ ./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. @@ -92,7 +96,7 @@ If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./t > 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 From 4748fdcbabfc8f24d8aa7492ec36767a7b9db278 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 16 Aug 2023 22:24:28 +0200 Subject: [PATCH 049/103] Add doc for sending patches to GCC --- doc/sending-gcc-patch.md | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 doc/sending-gcc-patch.md diff --git a/doc/sending-gcc-patch.md b/doc/sending-gcc-patch.md new file mode 100644 index 00000000000..7a47ef29f3c --- /dev/null +++ b/doc/sending-gcc-patch.md @@ -0,0 +1,44 @@ +This guide explains what to do to send a GCC patch for review. + +All the commands are supposed to be run in the folder where you cloned GCC. + +```bash +./contrib/gcc-changelog/git_check_commit.py +``` + +You can provide a specific commit hash: + +```bash +./contrib/gcc-changelog/git_check_commit.py abdef78989 +``` + +a range: + +```bash +./contrib/gcc-changelog/git_check_commit.py HEAD~2 +``` + +or even a comparison with a remote branch: + +```bash +./contrib/gcc-changelog/git_check_commit.py upstream/master..HEAD +``` + +When there is no more errors, generate the git patch: + +```bash +git format-patch -1 `git rev-parse --short HEAD` +``` + +Then you can run the remaining checks using: + +```bash +contrib/check_GNU_style.sh 0001-your-patch.patch +``` + +When you have no more errors, you can send the `.patch` file to GCC by sending an +email to `gcc-patches@gcc.gnu.org` and to the relevant GCC mailing lists +depending on what your patch changes. You can find the list of the mailing lists +[here](https://gcc.gnu.org/lists.html). + +You can find more information about "contributing to GCC" [here](https://gcc.gnu.org/contribute.html). From 6b588cc0077d9bdee81c8896d238c9107830b752 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Aug 2023 16:06:20 +0200 Subject: [PATCH 050/103] Rustify prepare.sh command --- .github/workflows/ci.yml | 4 +- .github/workflows/release.yml | 4 +- .github/workflows/stdarch.yml | 4 +- .gitignore | 1 + Readme.md | 2 +- build_sysroot/prepare_sysroot_src.sh | 39 ------- build_system/Cargo.lock | 7 ++ build_system/Cargo.toml | 11 ++ build_system/src/build.rs | 3 + build_system/src/main.rs | 49 +++++++++ build_system/src/prepare.rs | 157 +++++++++++++++++++++++++++ build_system/src/rustc_info.rs | 12 ++ build_system/src/utils.rs | 87 +++++++++++++++ prepare.sh | 30 ----- prepare_build.sh | 5 - rustup.sh | 2 +- y.sh | 7 ++ 17 files changed, 342 insertions(+), 82 deletions(-) delete mode 100755 build_sysroot/prepare_sysroot_src.sh create mode 100644 build_system/Cargo.lock create mode 100644 build_system/Cargo.toml create mode 100644 build_system/src/build.rs create mode 100644 build_system/src/main.rs create mode 100644 build_system/src/prepare.rs create mode 100644 build_system/src/rustc_info.rs create mode 100644 build_system/src/utils.rs delete mode 100755 prepare.sh delete mode 100755 prepare_build.sh create mode 100755 y.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2b7724a221..419468209ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,7 +119,7 @@ jobs: - name: Build run: | - ./prepare_build.sh + ./y.sh prepare --only-libcore ${{ matrix.libgccjit_version.env_extra }} ./build.sh ${{ matrix.libgccjit_version.extra }} ${{ matrix.libgccjit_version.env_extra }} cargo test ${{ matrix.libgccjit_version.extra }} ./clean_all.sh @@ -128,7 +128,7 @@ jobs: run: | git config --global user.email "user@example.com" git config --global user.name "User" - ./prepare.sh + ./y.sh prepare # Compile is a separate step, as the actions-rs/cargo action supports error annotations - name: Compile diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c4e99469bc2..655a94cbafd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,7 +88,7 @@ jobs: - name: Build run: | - ./prepare_build.sh + ./y.sh prepare --only-libcore ./build.sh --release --release-sysroot cargo test ./clean_all.sh @@ -97,7 +97,7 @@ jobs: run: | git config --global user.email "user@example.com" git config --global user.name "User" - ./prepare.sh + ./y.sh prepare # Compile is a separate step, as the actions-rs/cargo action supports error annotations - name: Compile diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 21b6a0d3a93..193c77f33c4 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -102,7 +102,7 @@ jobs: - name: Build run: | - ./prepare_build.sh + ./y.sh prepare --only-libcore ./build.sh --release --release-sysroot cargo test @@ -115,7 +115,7 @@ jobs: run: | git config --global user.email "user@example.com" git config --global user.name "User" - ./prepare.sh + ./y.sh prepare # Compile is a separate step, as the actions-rs/cargo action supports error annotations - name: Compile diff --git a/.gitignore b/.gitignore index c5ed7de200c..b44d1aa78c2 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ tools/llvmint tools/llvmint-2 # The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics. llvm +build_system/target diff --git a/Readme.md b/Readme.md index 55daad6dcd0..d26c2688991 100644 --- a/Readme.md +++ b/Readme.md @@ -65,7 +65,7 @@ $ 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 +$ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking $ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./build.sh --release ``` diff --git a/build_sysroot/prepare_sysroot_src.sh b/build_sysroot/prepare_sysroot_src.sh deleted file mode 100755 index 71b3876bac2..00000000000 --- a/build_sysroot/prepare_sysroot_src.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -set -e -cd $(dirname "$0") - -SRC_DIR=$(dirname $(rustup which rustc))"/../lib/rustlib/src/rust/" -DST_DIR="sysroot_src" - -if [ ! -e $SRC_DIR ]; then - echo "Please install rust-src component" - exit 1 -fi - -rm -rf $DST_DIR -mkdir -p $DST_DIR/library -cp -r $SRC_DIR/library $DST_DIR/ - -pushd $DST_DIR -echo "[GIT] init" -git init -echo "[GIT] add" -git add . -echo "[GIT] commit" - -# This is needed on systems where nothing is configured. -# git really needs something here, or it will fail. -# Even using --author is not enough. -git config user.email || git config user.email "none@example.com" -git config user.name || git config user.name "None" - -git commit -m "Initial commit" -q -for file in $(ls ../../patches/ | grep -v patcha); do - echo "[GIT] apply" $file - git apply ../../patches/$file - git add -A - git commit --no-gpg-sign -m "Patch $file" -done -popd - -echo "Successfully prepared libcore for building" diff --git a/build_system/Cargo.lock b/build_system/Cargo.lock new file mode 100644 index 00000000000..86268e19160 --- /dev/null +++ b/build_system/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "y" +version = "0.1.0" diff --git a/build_system/Cargo.toml b/build_system/Cargo.toml new file mode 100644 index 00000000000..b7487e38e63 --- /dev/null +++ b/build_system/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "y" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "y" +path = "src/main.rs" + +[features] +unstable-features = [] # for rust-analyzer diff --git a/build_system/src/build.rs b/build_system/src/build.rs new file mode 100644 index 00000000000..7384557d805 --- /dev/null +++ b/build_system/src/build.rs @@ -0,0 +1,3 @@ +pub fn run() -> Result<(), String> { + Ok(()) +} diff --git a/build_system/src/main.rs b/build_system/src/main.rs new file mode 100644 index 00000000000..c76418da579 --- /dev/null +++ b/build_system/src/main.rs @@ -0,0 +1,49 @@ +use std::env; +use std::process; + +mod build; +mod prepare; +mod rustc_info; +mod utils; + +macro_rules! arg_error { + ($($err:tt)*) => {{ + eprintln!($($err)*); + usage(); + std::process::exit(1); + }}; +} + +fn usage() { + // println!("{}", include_str!("usage.txt")); +} + +pub enum Command { + Prepare, + Build, +} + +fn main() { + if env::var("RUST_BACKTRACE").is_err() { + env::set_var("RUST_BACKTRACE", "1"); + } + + let command = match env::args().nth(1).as_deref() { + Some("prepare") => Command::Prepare, + Some("build") => Command::Build, + Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), + Some(command) => arg_error!("Unknown command {}", command), + None => { + usage(); + process::exit(0); + } + }; + + if let Err(e) = match command { + Command::Prepare => prepare::run(), + Command::Build => build::run(), + } { + eprintln!("Command failed to run: {e:?}"); + process::exit(1); + } +} diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs new file mode 100644 index 00000000000..74d0c2a2a06 --- /dev/null +++ b/build_system/src/prepare.rs @@ -0,0 +1,157 @@ +use crate::rustc_info::get_rustc_path; +use crate::utils::{cargo_install, git_clone, run_command, walk_dir}; + +use std::fs; +use std::path::Path; + +fn prepare_libcore() -> Result<(), String> { + let rustc_path = match get_rustc_path() { + Some(path) => path, + None => return Err("`rustc` path not found".to_owned()), + }; + + let parent = match rustc_path.parent() { + Some(path) => path, + None => return Err(format!("No parent for `{}`", rustc_path.display())), + }; + + let rustlib_dir = parent.join("../lib/rustlib/src/rust"); + if !rustlib_dir.is_dir() { + return Err("Please install `rust-src` component".to_owned()); + } + + let sysroot_dir = Path::new("build_sysroot/sysroot_src"); + if sysroot_dir.is_dir() { + if let Err(e) = fs::remove_dir_all(sysroot_dir) { + return Err(format!("Failed to remove `{}`: {:?}", sysroot_dir.display(), e)); + } + } + + let sysroot_library_dir = sysroot_dir.join("library"); + fs::create_dir_all(&sysroot_library_dir) + .map_err(|e| format!( + "Failed to create folder `{}`: {e:?}", + sysroot_library_dir.display(), + ))?; + + run_command(&[&"cp", &"-r", &rustlib_dir, &sysroot_library_dir], None)?; + + println!("[GIT] init (cwd): `{}`", sysroot_dir.display()); + run_command(&[&"git", &"init"], Some(&sysroot_dir))?; + println!("[GIT] add (cwd): `{}`", sysroot_dir.display()); + run_command(&[&"git", &"add", &"."], Some(&sysroot_dir))?; + println!("[GIT] commit (cwd): `{}`", sysroot_dir.display()); + + // This is needed on systems where nothing is configured. + // git really needs something here, or it will fail. + // Even using --author is not enough. + run_command(&[&"git", &"config", &"user.email", &"none@example.com"], Some(&sysroot_dir))?; + run_command(&[&"git", &"config", &"user.name", &"None"], Some(&sysroot_dir))?; + run_command(&[&"git", &"config", &"core.autocrlf=false"], Some(&sysroot_dir))?; + run_command(&[&"git", &"config", &"commit.gpgSign=false"], Some(&sysroot_dir))?; + run_command(&[&"git", &"commit", &"-m", &"Initial commit", &"-q"], Some(&sysroot_dir))?; + + walk_dir("patches", |_| Ok(()), |file_path: &Path| { + println!("[GIT] apply `{}`", file_path.display()); + let path = Path::new("../..").join(file_path); + run_command(&[&"git", &"apply", &path], Some(&sysroot_dir))?; + run_command(&[&"git", &"add", &"-A"], Some(&sysroot_dir))?; + run_command( + &[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())], + Some(&sysroot_dir), + )?; + Ok(()) + })?; + println!("Successfully prepared libcore for building"); + Ok(()) +} + +// build with cg_llvm for perf comparison +fn build_raytracer(repo_dir: &Path) -> Result<(), String> { + run_command(&[&"cargo", &"build"], Some(repo_dir))?; + run_command(&[&"mv", &"target/debug/main", &"raytracer_cg_llvm"], Some(repo_dir))?; + Ok(()) +} + +fn clone_and_setup(repo_url: &str, checkout_commit: &str, extra: Option) -> Result<(), String> +where + F: Fn(&Path) -> Result<(), String>, +{ + let clone_result = git_clone(repo_url, None)?; + if !clone_result.ran_clone { + println!("`{}` has already been cloned", clone_result.repo_name); + } + let repo_path = Path::new(&clone_result.repo_name); + run_command(&[&"git", &"checkout", &"--", &"."], Some(repo_path))?; + run_command(&[&"git", &"checkout", &checkout_commit], Some(repo_path))?; + let filter = format!("-{}-", clone_result.repo_name); + walk_dir("crate_patches", |_| Ok(()), |file_path| { + let s = file_path.as_os_str().to_str().unwrap(); + if s.contains(&filter) && s.ends_with(".patch") { + run_command(&[&"git", &"am", &s], Some(repo_path))?; + } + Ok(()) + })?; + if let Some(extra) = extra { + extra(repo_path)?; + } + Ok(()) +} + +struct PrepareArg { + only_libcore: bool, +} + +impl PrepareArg { + fn new() -> Result, String> { + let mut only_libcore = false; + + for arg in std::env::args().skip(2) { + match arg.as_str() { + "--only-libcore" => only_libcore = true, + "--help" => { + Self::usage(); + return Ok(None) + } + a => return Err(format!("Unknown argument `{a}`")), + } + } + Ok(Some(Self { + only_libcore, + })) + } + + fn usage() { + println!(r#" +`prepare` command help: + + --only-libcore : Only setup libcore and don't clone other repositories + --help : Show this help +"#) + } +} + +pub fn run() -> Result<(), String> { + let args = match PrepareArg::new()? { + Some(a) => a, + None => return Ok(()), + }; + prepare_libcore()?; + + if !args.only_libcore { + cargo_install("hyperfine")?; + + let to_clone = &[ + ("https://github.com/rust-random/rand.git", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", None), + ("https://github.com/rust-lang/regex.git", "341f207c1071f7290e3f228c710817c280c8dca1", None), + ("https://github.com/ebobby/simple-raytracer", "804a7a21b9e673a482797aa289a18ed480e4d813", Some(build_raytracer)), + ]; + + for (repo_url, checkout_commit, cb) in to_clone { + clone_and_setup(repo_url, checkout_commit, *cb)?; + } + } + + println!("Successfully ran `prepare`"); + Ok(()) +} diff --git a/build_system/src/rustc_info.rs b/build_system/src/rustc_info.rs new file mode 100644 index 00000000000..38c0045c7b3 --- /dev/null +++ b/build_system/src/rustc_info.rs @@ -0,0 +1,12 @@ +use std::path::{Path, PathBuf}; + +use crate::utils::run_command; + +pub fn get_rustc_path() -> Option { + if let Ok(rustc) = std::env::var("RUSTC") { + return Some(PathBuf::from(rustc)); + } + run_command(&[&"rustup", &"which", &"rustc"], None) + .ok() + .map(|out| Path::new(String::from_utf8(out.stdout).unwrap().trim()).to_owned()) +} diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs new file mode 100644 index 00000000000..f3c2571c28f --- /dev/null +++ b/build_system/src/utils.rs @@ -0,0 +1,87 @@ +use std::ffi::OsStr; +use std::fs; +use std::path::Path; +use std::process::{Command, Output}; + +pub fn run_command(input: &[&dyn AsRef], cwd: Option<&Path>) -> Result { + let (cmd, args) = match input { + [] => panic!("empty command"), + [cmd, args @ ..] => (cmd, args), + }; + let mut command = Command::new(cmd); + command.args(args); + if let Some(cwd) = cwd { + command.current_dir(cwd); + } + command.output() + .map_err(|e| format!( + "Command `{}` failed to run: {e:?}", + input.iter() + .map(|s| s.as_ref().to_str().unwrap()) + .collect::>() + .join(" "), + )) +} + +pub fn cargo_install(to_install: &str) -> Result<(), String> { + let output = run_command(&[&"cargo", &"install", &"--list"], None)?; + + let to_install = format!("{to_install} "); + // cargo install --list returns something like this: + // + // mdbook-toc v0.8.0: + // mdbook-toc + // rust-reduce v0.1.0: + // rust-reduce + // + // We are only interested into the command name so we only look for lines ending with `:`. + if String::from_utf8(output.stdout) + .unwrap() + .lines() + .any(|line| line.ends_with(':') && line.starts_with(&to_install)) + { + return Ok(()); + } + run_command(&[&"cargo", &"install", &to_install], None)?; + Ok(()) +} + +pub struct CloneResult { + pub ran_clone: bool, + pub repo_name: String, +} + +pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result { + let repo_name = to_clone.split('/').last().unwrap(); + let repo_name = match repo_name.strip_suffix(".git") { + Some(n) => n.to_owned(), + None => repo_name.to_owned(), + }; + + let dest = dest.unwrap_or_else(|| Path::new(&repo_name)); + if dest.is_dir() { + return Ok(CloneResult { ran_clone: false, repo_name }); + } + + run_command(&[&"git", &"clone", &to_clone, &dest], None)?; + Ok(CloneResult { ran_clone: true, repo_name }) +} + +pub fn walk_dir(dir: P, dir_cb: D, file_cb: F) -> Result<(), String> +where + P: AsRef, + D: Fn(&Path) -> Result<(), String>, + F: Fn(&Path) -> Result<(), String>, +{ + let dir = dir.as_ref(); + for entry in fs::read_dir(dir).map_err(|e| format!("Failed to read dir `{}`: {e:?}", dir.display()))? { + let entry = entry.map_err(|e| format!("Failed to read entry in `{}`: {e:?}", dir.display()))?; + let entry_path = entry.path(); + if entry_path.is_dir() { + dir_cb(&entry_path)?; + } else { + file_cb(&entry_path)?; + } + } + Ok(()) +} diff --git a/prepare.sh b/prepare.sh deleted file mode 100755 index e98f24c6e12..00000000000 --- a/prepare.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -set -e -set -v - -source prepare_build.sh - -cargo install hyperfine || echo "Skipping hyperfine install" - -git clone https://github.com/rust-random/rand.git || echo "rust-random/rand has already been cloned" -pushd rand -git checkout -- . -git checkout 0f933f9c7176e53b2a3c7952ded484e1783f0bf1 -git am ../crate_patches/*-rand-*.patch -popd - -git clone https://github.com/rust-lang/regex.git || echo "rust-lang/regex has already been cloned" -pushd regex -git checkout -- . -git checkout 341f207c1071f7290e3f228c710817c280c8dca1 -popd - -git clone https://github.com/ebobby/simple-raytracer || echo "ebobby/simple-raytracer has already been cloned" -pushd simple-raytracer -git checkout -- . -git checkout 804a7a21b9e673a482797aa289a18ed480e4d813 - -# build with cg_llvm for perf comparison -cargo build -mv target/debug/main raytracer_cg_llvm -popd diff --git a/prepare_build.sh b/prepare_build.sh deleted file mode 100755 index 8194360da4b..00000000000 --- a/prepare_build.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -e -set -v - -./build_sysroot/prepare_sysroot_src.sh diff --git a/rustup.sh b/rustup.sh index 041079bc9c6..a4f938e4b5b 100755 --- a/rustup.sh +++ b/rustup.sh @@ -16,7 +16,7 @@ case $1 in done ./clean_all.sh - ./prepare.sh + ./y.sh prepare ;; "commit") git add rust-toolchain diff --git a/y.sh b/y.sh new file mode 100755 index 00000000000..481b909c92a --- /dev/null +++ b/y.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e +echo "[BUILD] build system" 1>&2 +mkdir -p build_system/target +rustc build_system/src/main.rs -o build_system/target/y -Cdebuginfo=1 --edition 2021 +exec ./build_system/target/y "$@" From 18d22d56989db6590872cc6791b68cefc8695eab Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 19 Aug 2023 18:24:01 +0200 Subject: [PATCH 051/103] Don't capture output on git commands --- build_system/src/prepare.rs | 12 ++++++------ build_system/src/utils.rs | 31 +++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index 74d0c2a2a06..8e6183be629 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -1,5 +1,5 @@ use crate::rustc_info::get_rustc_path; -use crate::utils::{cargo_install, git_clone, run_command, walk_dir}; +use crate::utils::{cargo_install, git_clone, run_command, run_command_with_output, walk_dir}; use std::fs; use std::path::Path; @@ -37,9 +37,9 @@ fn prepare_libcore() -> Result<(), String> { run_command(&[&"cp", &"-r", &rustlib_dir, &sysroot_library_dir], None)?; println!("[GIT] init (cwd): `{}`", sysroot_dir.display()); - run_command(&[&"git", &"init"], Some(&sysroot_dir))?; + run_command_with_output(&[&"git", &"init"], Some(&sysroot_dir))?; println!("[GIT] add (cwd): `{}`", sysroot_dir.display()); - run_command(&[&"git", &"add", &"."], Some(&sysroot_dir))?; + run_command_with_output(&[&"git", &"add", &"."], Some(&sysroot_dir))?; println!("[GIT] commit (cwd): `{}`", sysroot_dir.display()); // This is needed on systems where nothing is configured. @@ -54,9 +54,9 @@ fn prepare_libcore() -> Result<(), String> { walk_dir("patches", |_| Ok(()), |file_path: &Path| { println!("[GIT] apply `{}`", file_path.display()); let path = Path::new("../..").join(file_path); - run_command(&[&"git", &"apply", &path], Some(&sysroot_dir))?; - run_command(&[&"git", &"add", &"-A"], Some(&sysroot_dir))?; - run_command( + run_command_with_output(&[&"git", &"apply", &path], Some(&sysroot_dir))?; + run_command_with_output(&[&"git", &"add", &"-A"], Some(&sysroot_dir))?; + run_command_with_output( &[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())], Some(&sysroot_dir), )?; diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index f3c2571c28f..145f40ec8ae 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -3,7 +3,7 @@ use std::fs; use std::path::Path; use std::process::{Command, Output}; -pub fn run_command(input: &[&dyn AsRef], cwd: Option<&Path>) -> Result { +fn run_command_inner(input: &[&dyn AsRef], cwd: Option<&Path>) -> Command { let (cmd, args) = match input { [] => panic!("empty command"), [cmd, args @ ..] => (cmd, args), @@ -13,7 +13,11 @@ pub fn run_command(input: &[&dyn AsRef], cwd: Option<&Path>) -> Result], cwd: Option<&Path>) -> Result { + run_command_inner(input, cwd).output() .map_err(|e| format!( "Command `{}` failed to run: {e:?}", input.iter() @@ -23,6 +27,29 @@ pub fn run_command(input: &[&dyn AsRef], cwd: Option<&Path>) -> Result], + cwd: Option<&Path>, +) -> Result<(), String> { + run_command_inner(input, cwd).spawn() + .map_err(|e| format!( + "Command `{}` failed to run: {e:?}", + input.iter() + .map(|s| s.as_ref().to_str().unwrap()) + .collect::>() + .join(" "), + ))? + .wait() + .map_err(|e| format!( + "Failed to wait for command `{}` to run: {e:?}", + input.iter() + .map(|s| s.as_ref().to_str().unwrap()) + .collect::>() + .join(" "), + ))?; + Ok(()) +} + pub fn cargo_install(to_install: &str) -> Result<(), String> { let output = run_command(&[&"cargo", &"install", &"--list"], None)?; From c682e9ca94e3b7d4c1dfcf4686360e7760e8ef9f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 19 Aug 2023 20:53:47 +0200 Subject: [PATCH 052/103] Correctly set path --- build_system/src/prepare.rs | 50 ++++++++++++++------- build_system/src/utils.rs | 87 ++++++++++++++++++++++++------------- 2 files changed, 92 insertions(+), 45 deletions(-) diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index 8e6183be629..9c31b5cb8b3 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -4,7 +4,7 @@ use crate::utils::{cargo_install, git_clone, run_command, run_command_with_outpu use std::fs; use std::path::Path; -fn prepare_libcore() -> Result<(), String> { +fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> { let rustc_path = match get_rustc_path() { Some(path) => path, None => return Err("`rustc` path not found".to_owned()), @@ -15,14 +15,18 @@ fn prepare_libcore() -> Result<(), String> { None => return Err(format!("No parent for `{}`", rustc_path.display())), }; - let rustlib_dir = parent.join("../lib/rustlib/src/rust"); + let rustlib_dir = + parent + .join("../lib/rustlib/src/rust") + .canonicalize() + .map_err(|e| format!("Failed to canonicalize path: {e:?}"))?; if !rustlib_dir.is_dir() { return Err("Please install `rust-src` component".to_owned()); } - let sysroot_dir = Path::new("build_sysroot/sysroot_src"); + let sysroot_dir = sysroot_path.join("sysroot_src"); if sysroot_dir.is_dir() { - if let Err(e) = fs::remove_dir_all(sysroot_dir) { + if let Err(e) = fs::remove_dir_all(&sysroot_dir) { return Err(format!("Failed to remove `{}`: {:?}", sysroot_dir.display(), e)); } } @@ -34,12 +38,12 @@ fn prepare_libcore() -> Result<(), String> { sysroot_library_dir.display(), ))?; - run_command(&[&"cp", &"-r", &rustlib_dir, &sysroot_library_dir], None)?; + run_command(&[&"cp", &"-r", &rustlib_dir.join("library"), &sysroot_dir], None)?; println!("[GIT] init (cwd): `{}`", sysroot_dir.display()); - run_command_with_output(&[&"git", &"init"], Some(&sysroot_dir))?; + run_command(&[&"git", &"init"], Some(&sysroot_dir))?; println!("[GIT] add (cwd): `{}`", sysroot_dir.display()); - run_command_with_output(&[&"git", &"add", &"."], Some(&sysroot_dir))?; + run_command(&[&"git", &"add", &"."], Some(&sysroot_dir))?; println!("[GIT] commit (cwd): `{}`", sysroot_dir.display()); // This is needed on systems where nothing is configured. @@ -47,11 +51,17 @@ fn prepare_libcore() -> Result<(), String> { // Even using --author is not enough. run_command(&[&"git", &"config", &"user.email", &"none@example.com"], Some(&sysroot_dir))?; run_command(&[&"git", &"config", &"user.name", &"None"], Some(&sysroot_dir))?; - run_command(&[&"git", &"config", &"core.autocrlf=false"], Some(&sysroot_dir))?; - run_command(&[&"git", &"config", &"commit.gpgSign=false"], Some(&sysroot_dir))?; + run_command(&[&"git", &"config", &"core.autocrlf", &"false"], Some(&sysroot_dir))?; + run_command(&[&"git", &"config", &"commit.gpgSign", &"false"], Some(&sysroot_dir))?; run_command(&[&"git", &"commit", &"-m", &"Initial commit", &"-q"], Some(&sysroot_dir))?; + let mut patches = Vec::new(); walk_dir("patches", |_| Ok(()), |file_path: &Path| { + patches.push(file_path.to_path_buf()); + Ok(()) + })?; + patches.sort(); + for file_path in patches { println!("[GIT] apply `{}`", file_path.display()); let path = Path::new("../..").join(file_path); run_command_with_output(&[&"git", &"apply", &path], Some(&sysroot_dir))?; @@ -60,8 +70,7 @@ fn prepare_libcore() -> Result<(), String> { &[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())], Some(&sysroot_dir), )?; - Ok(()) - })?; + } println!("Successfully prepared libcore for building"); Ok(()) } @@ -69,6 +78,11 @@ fn prepare_libcore() -> Result<(), String> { // build with cg_llvm for perf comparison fn build_raytracer(repo_dir: &Path) -> Result<(), String> { run_command(&[&"cargo", &"build"], Some(repo_dir))?; + let mv_target = repo_dir.join("raytracer_cg_llvm"); + if mv_target.is_file() { + std::fs::remove_file(&mv_target) + .map_err(|e| format!("Failed to remove file `{}`: {e:?}", mv_target.display()))?; + } run_command(&[&"mv", &"target/debug/main", &"raytracer_cg_llvm"], Some(repo_dir))?; Ok(()) } @@ -82,18 +96,21 @@ where println!("`{}` has already been cloned", clone_result.repo_name); } let repo_path = Path::new(&clone_result.repo_name); - run_command(&[&"git", &"checkout", &"--", &"."], Some(repo_path))?; - run_command(&[&"git", &"checkout", &checkout_commit], Some(repo_path))?; + run_command(&[&"git", &"checkout", &"--", &"."], Some(&repo_path))?; + run_command(&[&"git", &"checkout", &checkout_commit], Some(&repo_path))?; let filter = format!("-{}-", clone_result.repo_name); walk_dir("crate_patches", |_| Ok(()), |file_path| { let s = file_path.as_os_str().to_str().unwrap(); if s.contains(&filter) && s.ends_with(".patch") { - run_command(&[&"git", &"am", &s], Some(repo_path))?; + run_command_with_output( + &[&"git", &"am", &file_path.canonicalize().unwrap()], + Some(&repo_path), + )?; } Ok(()) })?; if let Some(extra) = extra { - extra(repo_path)?; + extra(&repo_path)?; } Ok(()) } @@ -136,7 +153,8 @@ pub fn run() -> Result<(), String> { Some(a) => a, None => return Ok(()), }; - prepare_libcore()?; + let sysroot_path = Path::new("build_sysroot"); + prepare_libcore(sysroot_path)?; if !args.only_libcore { cargo_install("hyperfine")?; diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 145f40ec8ae..c350864dbd2 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -1,9 +1,10 @@ use std::ffi::OsStr; +use std::fmt::Debug; use std::fs; use std::path::Path; -use std::process::{Command, Output}; +use std::process::{Command, ExitStatus, Output}; -fn run_command_inner(input: &[&dyn AsRef], cwd: Option<&Path>) -> Command { +fn get_command_inner(input: &[&dyn AsRef], cwd: Option<&Path>) -> Command { let (cmd, args) = match input { [] => panic!("empty command"), [cmd, args @ ..] => (cmd, args), @@ -16,44 +17,67 @@ fn run_command_inner(input: &[&dyn AsRef], cwd: Option<&Path>) -> Command command } -pub fn run_command(input: &[&dyn AsRef], cwd: Option<&Path>) -> Result { - run_command_inner(input, cwd).output() - .map_err(|e| format!( - "Command `{}` failed to run: {e:?}", +fn check_exit_status( + input: &[&dyn AsRef], + cwd: Option<&Path>, + exit_status: ExitStatus, +) -> Result<(), String> { + if exit_status.success() { + Ok(()) + } else { + Err(format!( + "Command `{}`{} exited with status {:?}", input.iter() .map(|s| s.as_ref().to_str().unwrap()) .collect::>() .join(" "), + cwd.map(|cwd| format!(" (running in folder `{}`)", cwd.display())) + .unwrap_or_default(), + exit_status.code(), )) + } +} + +fn command_error(input: &[&dyn AsRef], cwd: &Option<&Path>, error: D) -> String { + format!( + "Command `{}`{} failed to run: {error:?}", + input.iter() + .map(|s| s.as_ref().to_str().unwrap()) + .collect::>() + .join(" "), + cwd.as_ref() + .map(|cwd| format!( + " (running in folder `{}`)", + cwd.display(), + )) + .unwrap_or_default(), + ) +} + +pub fn run_command(input: &[&dyn AsRef], cwd: Option<&Path>) -> Result { + let output = get_command_inner(input, cwd) + .output() + .map_err(|e| command_error(input, &cwd, e))?; + check_exit_status(input, cwd, output.status)?; + Ok(output) } pub fn run_command_with_output( input: &[&dyn AsRef], cwd: Option<&Path>, ) -> Result<(), String> { - run_command_inner(input, cwd).spawn() - .map_err(|e| format!( - "Command `{}` failed to run: {e:?}", - input.iter() - .map(|s| s.as_ref().to_str().unwrap()) - .collect::>() - .join(" "), - ))? + let exit_status = get_command_inner(input, cwd).spawn() + .map_err(|e| command_error(input, &cwd, e))? .wait() - .map_err(|e| format!( - "Failed to wait for command `{}` to run: {e:?}", - input.iter() - .map(|s| s.as_ref().to_str().unwrap()) - .collect::>() - .join(" "), - ))?; + .map_err(|e| command_error(input, &cwd, e))?; + check_exit_status(input, cwd, exit_status)?; Ok(()) } pub fn cargo_install(to_install: &str) -> Result<(), String> { let output = run_command(&[&"cargo", &"install", &"--list"], None)?; - let to_install = format!("{to_install} "); + let to_install_needle = format!("{to_install} "); // cargo install --list returns something like this: // // mdbook-toc v0.8.0: @@ -65,11 +89,14 @@ pub fn cargo_install(to_install: &str) -> Result<(), String> { if String::from_utf8(output.stdout) .unwrap() .lines() - .any(|line| line.ends_with(':') && line.starts_with(&to_install)) + .any(|line| line.ends_with(':') && line.starts_with(&to_install_needle)) { return Ok(()); } - run_command(&[&"cargo", &"install", &to_install], None)?; + // We voluntarily ignore this error. + if run_command_with_output(&[&"cargo", &"install", &to_install], None).is_err() { + println!("Skipping installation of `{to_install}`"); + } Ok(()) } @@ -85,20 +112,22 @@ pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result repo_name.to_owned(), }; - let dest = dest.unwrap_or_else(|| Path::new(&repo_name)); + let dest = dest + .map(|dest| dest.join(&repo_name)) + .unwrap_or_else(|| Path::new(&repo_name).into()); if dest.is_dir() { return Ok(CloneResult { ran_clone: false, repo_name }); } - run_command(&[&"git", &"clone", &to_clone, &dest], None)?; + run_command_with_output(&[&"git", &"clone", &to_clone, &dest], None)?; Ok(CloneResult { ran_clone: true, repo_name }) } -pub fn walk_dir(dir: P, dir_cb: D, file_cb: F) -> Result<(), String> +pub fn walk_dir(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), String> where P: AsRef, - D: Fn(&Path) -> Result<(), String>, - F: Fn(&Path) -> Result<(), String>, + D: FnMut(&Path) -> Result<(), String>, + F: FnMut(&Path) -> Result<(), String>, { let dir = dir.as_ref(); for entry in fs::read_dir(dir).map_err(|e| format!("Failed to read dir `{}`: {e:?}", dir.display()))? { From 08eb006f71c3c089045c9eeef560de5f68850676 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 21 Aug 2023 15:52:05 +0200 Subject: [PATCH 053/103] Remove unused Cargo feature --- build_system/Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/build_system/Cargo.toml b/build_system/Cargo.toml index b7487e38e63..f36709ea036 100644 --- a/build_system/Cargo.toml +++ b/build_system/Cargo.toml @@ -6,6 +6,3 @@ edition = "2021" [[bin]] name = "y" path = "src/main.rs" - -[features] -unstable-features = [] # for rust-analyzer From 5ac2530d3ce2632226456edcb5d60403bbe6e79a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 12 Aug 2023 16:12:15 +0200 Subject: [PATCH 054/103] Add support for `noalias` function parameters --- src/abi.rs | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 6fb1cbfad8c..8f5cd30fe3c 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -3,7 +3,7 @@ use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::ty::Ty; -use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg, RegKind}; +use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; use crate::builder::Builder; use crate::context::CodegenCx; @@ -120,30 +120,49 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } }; + #[cfg(feature = "master")] + let apply_attrs = |ty: Type<'gcc>, attrs: &ArgAttributes| { + if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) + && ty.get_pointee().is_some() + { + ty.make_restrict() + } else { + ty + } + }; + #[cfg(not(feature = "master"))] + let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes| { + ty + }; + for arg in self.args.iter() { let arg_ty = match arg.mode { PassMode::Ignore => continue, - PassMode::Direct(_) => arg.layout.immediate_gcc_type(cx), - PassMode::Pair(..) => { - argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 0, true)); - argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 1, true)); + PassMode::Pair(a, b) => { + argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0, true), &a)); + argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1, true), &b)); continue; } - PassMode::Indirect { extra_attrs: Some(_), .. } => { - unimplemented!(); - } PassMode::Cast(ref cast, pad_i32) => { // add padding if pad_i32 { argument_tys.push(Reg::i32().gcc_type(cx)); } - cast.gcc_type(cx) + let ty = cast.gcc_type(cx); + apply_attrs(ty, &cast.attrs) } - PassMode::Indirect { extra_attrs: None, on_stack: true, .. } => { + PassMode::Indirect { attrs, extra_attrs: None, on_stack: true } => { on_stack_param_indices.insert(argument_tys.len()); - arg.memory_ty(cx) + apply_attrs(arg.memory_ty(cx), &attrs) }, - PassMode::Indirect { extra_attrs: None, on_stack: false, .. } => cx.type_ptr_to(arg.memory_ty(cx)), + PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs), + PassMode::Indirect { attrs, extra_attrs: None, on_stack: false } => { + apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs) + } + PassMode::Indirect { attrs, extra_attrs: Some(extra_attrs), on_stack } => { + assert!(!on_stack); + apply_attrs(apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs), &extra_attrs) + } }; argument_tys.push(arg_ty); } From 189dd7022a8c325ceb34b64014066e0b2b78a5f4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 17 Aug 2023 10:46:48 +0200 Subject: [PATCH 055/103] Update gccjit dependency --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7fcb124927a..40da783dbe8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,7 +74,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#814eea1a0a098d08a113794225cad301622fd7b4" +source = "git+https://github.com/antoyo/gccjit.rs#ff1f82584c760a8b870dc6bad9841bd090f92f80" dependencies = [ "gccjit_sys", ] @@ -82,7 +82,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#814eea1a0a098d08a113794225cad301622fd7b4" +source = "git+https://github.com/antoyo/gccjit.rs#ff1f82584c760a8b870dc6bad9841bd090f92f80" dependencies = [ "libc", ] From ec4a85e889743295e0f58b554eb9c17d17e6c254 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 25 Aug 2023 19:49:10 -0400 Subject: [PATCH 056/103] Revert "Use the same DISubprogram for each instance of the same inlined function within the caller" This reverts commit 687bffa49375aa00bacc51f5d9adfb84a9453e17. Reverting to resolve ICEs reported on nightly. --- src/debuginfo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index d1bfd833cd8..a81585d4128 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -55,7 +55,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _llfn: RValue<'gcc>, _mir: &mir::Body<'tcx>, - ) -> Option> { + ) -> Option> { // TODO(antoyo) None } From 44401b89ad114d804fecfc76a3f2ea083b558cd5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 28 Aug 2023 16:35:22 +0200 Subject: [PATCH 057/103] carry out the same changes in the gcc backend --- src/type_of.rs | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/src/type_of.rs b/src/type_of.rs index 84d57838512..bb5f561ebc3 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -182,23 +182,16 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { /// of that field's type - this is useful for taking the address of /// that field and ensuring the struct has the right alignment. fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { + // This must produce the same result for `repr(transparent)` wrappers as for the inner type! + // In other words, this should generally not look at the type at all, but only at the + // layout. if let Abi::Scalar(ref scalar) = self.abi { // Use a different cache for scalars because pointers to DSTs // can be either fat or thin (data pointers of fat pointers). if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) { return ty; } - let ty = - match *self.ty.kind() { - ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { - cx.type_ptr_to(cx.layout_of(ty).gcc_type(cx)) - } - ty::Adt(def, _) if def.is_box() => { - cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).gcc_type(cx)) - } - ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())), - _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO), - }; + let ty = self.scalar_gcc_type_at(cx, scalar, Size::ZERO); cx.scalar_types.borrow_mut().insert(self.ty, ty); return ty; } @@ -273,22 +266,9 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { } fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize, immediate: bool) -> Type<'gcc> { - // TODO(antoyo): remove llvm hack: - // HACK(eddyb) special-case fat pointers until LLVM removes - // pointee types, to avoid bitcasting every `OperandRef::deref`. - match self.ty.kind() { - ty::Ref(..) | ty::RawPtr(_) => { - return self.field(cx, index).gcc_type(cx); - } - // only wide pointer boxes are handled as pointers - // thin pointer boxes with scalar allocators are handled by the general logic below - ty::Adt(def, args) if def.is_box() && cx.layout_of(args.type_at(1)).is_zst() => { - let ptr_ty = Ty::new_mut_ptr(cx.tcx,self.ty.boxed_ty()); - return cx.layout_of(ptr_ty).scalar_pair_element_gcc_type(cx, index, immediate); - } - _ => {} - } - + // This must produce the same result for `repr(transparent)` wrappers as for the inner type! + // In other words, this should generally not look at the type at all, but only at the + // layout. let (a, b) = match self.abi { Abi::ScalarPair(ref a, ref b) => (a, b), _ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self), From 0d2cd6f650a20ff344b3959c704ecbb8b49e8445 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 28 Aug 2023 18:21:16 +0200 Subject: [PATCH 058/103] remove an unused argument it was already unused before, but due to the recursion the compiler did not realize --- src/abi.rs | 4 ++-- src/builder.rs | 2 +- src/type_of.rs | 14 +++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 6fb1cbfad8c..377dc753f68 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -125,8 +125,8 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { PassMode::Ignore => continue, PassMode::Direct(_) => arg.layout.immediate_gcc_type(cx), PassMode::Pair(..) => { - argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 0, true)); - argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 1, true)); + argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 0)); + argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 1)); continue; } PassMode::Indirect { extra_attrs: Some(_), .. } => { diff --git a/src/builder.rs b/src/builder.rs index 0b1f2fe6a87..308cb04cac3 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -821,7 +821,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let mut load = |i, scalar: &abi::Scalar, align| { let llptr = self.struct_gep(pair_type, place.llval, i as u64); - let llty = place.layout.scalar_pair_element_gcc_type(self, i, false); + let llty = place.layout.scalar_pair_element_gcc_type(self, i); let load = self.load(llty, llptr, align); scalar_load_metadata(self, load, scalar); if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load } diff --git a/src/type_of.rs b/src/type_of.rs index bb5f561ebc3..cc467801beb 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -4,7 +4,7 @@ use gccjit::{Struct, Type}; use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods}; use rustc_middle::bug; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; -use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants}; use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; @@ -74,8 +74,8 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout Abi::ScalarPair(..) => { return cx.type_struct( &[ - layout.scalar_pair_element_gcc_type(cx, 0, false), - layout.scalar_pair_element_gcc_type(cx, 1, false), + layout.scalar_pair_element_gcc_type(cx, 0), + layout.scalar_pair_element_gcc_type(cx, 1), ], false, ); @@ -150,7 +150,7 @@ pub trait LayoutGccExt<'tcx> { fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc>; - fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize, immediate: bool) -> Type<'gcc>; + fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize) -> Type<'gcc>; fn gcc_field_index(&self, index: usize) -> u64; fn pointee_info_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, offset: Size) -> Option; } @@ -265,7 +265,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { } } - fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize, immediate: bool) -> Type<'gcc> { + fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize) -> Type<'gcc> { // This must produce the same result for `repr(transparent)` wrappers as for the inner type! // In other words, this should generally not look at the type at all, but only at the // layout. @@ -347,8 +347,8 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { layout.gcc_field_index(index) } - fn scalar_pair_element_backend_type(&self, layout: TyAndLayout<'tcx>, index: usize, immediate: bool) -> Type<'gcc> { - layout.scalar_pair_element_gcc_type(self, index, immediate) + fn scalar_pair_element_backend_type(&self, layout: TyAndLayout<'tcx>, index: usize, _immediate: bool) -> Type<'gcc> { + layout.scalar_pair_element_gcc_type(self, index) } fn cast_backend_type(&self, ty: &CastTarget) -> Type<'gcc> { From 642fae9409dd565cb873dab3bf32a7fe739c8ac2 Mon Sep 17 00:00:00 2001 From: Katherine Philip Date: Mon, 28 Aug 2023 12:40:39 -0700 Subject: [PATCH 059/103] Don't ICE on layout computation failure --- src/context.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 88dcafa7370..dcebd92a61c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -7,6 +7,7 @@ use rustc_codegen_ssa::traits::{ BaseTypeMethods, MiscMethods, }; +use rustc_codegen_ssa::errors as ssa_errors; use rustc_data_structures::base_n; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::span_bug; @@ -479,7 +480,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err { self.sess().emit_fatal(respan(span, err.into_diagnostic())) } else { - span_bug!(span, "failed to get layout for `{}`: {}", ty, err) + self.tcx.sess.emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err }) } } } From c83e5679b3cef0beca335f8e010af491335b4c82 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 29 Aug 2023 15:45:48 +0200 Subject: [PATCH 060/103] Don't generate __restrict__ attribute for ByValue arguments --- src/abi.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 8f5cd30fe3c..874ac0b087e 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -123,7 +123,6 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { #[cfg(feature = "master")] let apply_attrs = |ty: Type<'gcc>, attrs: &ArgAttributes| { if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) - && ty.get_pointee().is_some() { ty.make_restrict() } else { @@ -151,9 +150,10 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { let ty = cast.gcc_type(cx); apply_attrs(ty, &cast.attrs) } - PassMode::Indirect { attrs, extra_attrs: None, on_stack: true } => { + PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: true } => { + // This is a "byval" argument, so we don't apply the `restrict` attribute on it. on_stack_param_indices.insert(argument_tys.len()); - apply_attrs(arg.memory_ty(cx), &attrs) + arg.memory_ty(cx) }, PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs), PassMode::Indirect { attrs, extra_attrs: None, on_stack: false } => { From 62867dc29f8772db166139d954dbe606ab28c34b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 12 May 2023 11:40:04 -0400 Subject: [PATCH 061/103] LTO implementation --- .github/workflows/ci.yml | 12 +- .github/workflows/release.yml | 22 +- .github/workflows/stdarch.yml | 14 +- Cargo.lock | 10 + Cargo.toml | 4 + Readme.md | 47 ++- build_sysroot/Cargo.toml | 1 + config.sh | 13 +- failing-lto-tests.txt | 23 ++ failing-non-lto-tests.txt | 11 + failing-ui-tests.txt | 19 +- locales/en-US.ftl | 65 ---- messages.ftl | 14 + ...1-Add-stdarch-Cargo.toml-for-testing.patch | 19 +- patches/0001-Disable-examples.patch | 25 -- src/back/lto.rs | 341 ++++++++++++++++++ src/back/mod.rs | 1 + src/back/write.rs | 102 +++++- src/base.rs | 15 +- src/declare.rs | 40 ++ src/errors.rs | 31 ++ src/lib.rs | 52 +-- test.sh | 6 +- 23 files changed, 713 insertions(+), 174 deletions(-) create mode 100644 failing-lto-tests.txt create mode 100644 failing-non-lto-tests.txt delete mode 100644 locales/en-US.ftl delete mode 100644 patches/0001-Disable-examples.patch create mode 100644 src/back/lto.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 419468209ef..4702494f05c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,8 +57,8 @@ jobs: uses: dawidd6/action-download-artifact@v2 with: workflow: main.yml - name: ${{ matrix.libgccjit_version.gcc }} - path: gcc-build + name: gcc-13 + path: gcc-13 repo: antoyo/gcc branch: ${{ matrix.libgccjit_version.artifacts_branch }} event: push @@ -71,9 +71,8 @@ jobs: - name: Setup path to libgccjit if: matrix.libgccjit_version.gcc != 'libgccjit12.so' run: | - echo $(readlink -f gcc-build) > gcc_path - # NOTE: the filename is still libgccjit.so even when the artifact name is different. - ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0 + sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb + echo /usr/lib/ > gcc_path - name: Set env run: | @@ -141,6 +140,9 @@ jobs: if: ${{ matrix.libgccjit_version.gcc == 'libgccjit12.so' }} run: cat failing-ui-tests12.txt >> failing-ui-tests.txt + - name: Add more failing tests because the sysroot is not compiled with LTO + run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt + - name: Run tests run: | ${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} ${{ matrix.libgccjit_version.extra }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 655a94cbafd..51fc5c76cdb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,8 +18,6 @@ jobs: strategy: fail-fast: false matrix: - libgccjit_version: - - { gcc: "libgccjit.so", artifacts_branch: "master" } commands: [ "--test-successful-rustc --nb-parts 2 --current-part 0", "--test-successful-rustc --nb-parts 2 --current-part 1", @@ -40,18 +38,17 @@ jobs: uses: dawidd6/action-download-artifact@v2 with: workflow: main.yml - name: ${{ matrix.libgccjit_version.gcc }} - path: gcc-build + name: gcc-13 + path: gcc-13 repo: antoyo/gcc - branch: ${{ matrix.libgccjit_version.artifacts_branch }} + branch: "master" event: push search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts. - name: Setup path to libgccjit run: | - echo $(readlink -f gcc-build) > gcc_path - # NOTE: the filename is still libgccjit.so even when the artifact name is different. - ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0 + sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb + echo /usr/lib/ > gcc_path - name: Set env run: | @@ -89,7 +86,7 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - ./build.sh --release --release-sysroot + EMBED_LTO_BITCODE=1 ./build.sh --release --release-sysroot cargo test ./clean_all.sh @@ -98,6 +95,8 @@ jobs: git config --global user.email "user@example.com" git config --global user.name "User" ./y.sh prepare + # FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros. + echo -n 'lto = "fat"' >> build_sysroot/Cargo.toml # Compile is a separate step, as the actions-rs/cargo action supports error annotations - name: Compile @@ -106,6 +105,9 @@ jobs: command: build args: --release + - name: Add more failing tests because of undefined symbol errors (FIXME) + run: cat failing-lto-tests.txt >> failing-ui-tests.txt + - name: Run tests run: | - ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} + EMBED_LTO_BITCODE=1 ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 193c77f33c4..c44d8efe3c7 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -18,8 +18,6 @@ jobs: strategy: fail-fast: false matrix: - libgccjit_version: - - { gcc: "libgccjit.so", artifacts_branch: "master" } cargo_runner: [ "sde -future -rtm_mode full --", "", @@ -54,18 +52,17 @@ jobs: uses: dawidd6/action-download-artifact@v2 with: workflow: main.yml - name: ${{ matrix.libgccjit_version.gcc }} - path: gcc-build + name: gcc-13 + path: gcc-13 repo: antoyo/gcc - branch: ${{ matrix.libgccjit_version.artifacts_branch }} + branch: "master" event: push search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts. - name: Setup path to libgccjit run: | - echo $(readlink -f gcc-build) > gcc_path - # NOTE: the filename is still libgccjit.so even when the artifact name is different. - ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0 + sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb + echo /usr/lib/ > gcc_path - name: Set env run: | @@ -139,4 +136,5 @@ jobs: if: ${{ matrix.cargo_runner }} run: | cd build_sysroot/sysroot_src/library/stdarch/ + # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a diff --git a/Cargo.lock b/Cargo.lock index 40da783dbe8..404fb9c6db1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -146,6 +146,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +dependencies = [ + "memchr", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -178,6 +187,7 @@ version = "0.1.0" dependencies = [ "gccjit", "lang_tester", + "object", "smallvec", "tempfile", ] diff --git a/Cargo.toml b/Cargo.toml index 3bf629fc662..51fab147aa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,10 @@ gccjit = { git = "https://github.com/antoyo/gccjit.rs" } # Local copy. #gccjit = { path = "../gccjit.rs" } +object = { version = "0.30.1", default-features = false, features = [ + "std", + "read", +] } smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } # TODO(antoyo): make tempfile optional. tempfile = "3.7.1" diff --git a/Readme.md b/Readme.md index 47fb840efb9..daee6e8588d 100644 --- a/Readme.md +++ b/Readme.md @@ -91,6 +91,9 @@ $ 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. +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`. + ### Rustc > You should prefer using the Cargo method. @@ -191,6 +194,48 @@ 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`.) + +### 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`). @@ -253,4 +298,4 @@ generate it in [gimple.md](./doc/gimple.md). * Set `linker='-Clinker=m68k-linux-gcc'`. * 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?). + * (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?): Remove dylib from build_sysroot/sysroot_src/library/std/Cargo.toml. diff --git a/build_sysroot/Cargo.toml b/build_sysroot/Cargo.toml index dca2ffdc24b..e5658273c97 100644 --- a/build_sysroot/Cargo.toml +++ b/build_sysroot/Cargo.toml @@ -19,3 +19,4 @@ rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-st [profile.release] debug = true +#lto = "fat" # TODO(antoyo): re-enable when the failing LTO tests regarding proc-macros are fixed. diff --git a/config.sh b/config.sh index 166e83901c4..ecc6d56b00e 100644 --- a/config.sh +++ b/config.sh @@ -38,7 +38,14 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then fi fi -export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS" +# Since we don't support ThinLTO, disable LTO completely when not trying to do LTO. +# TODO(antoyo): remove when we can handle ThinLTO. +disable_lto_flags='' +if [[ ! -v FAT_LTO ]]; then + disable_lto_flags='-Clto=off' +fi + +export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS" # FIXME(antoyo): remove once the atomic shim is gone if [[ `uname` == 'Darwin' ]]; then @@ -50,3 +57,7 @@ export RUSTC_LOG=warn # display metadata load errors export LD_LIBRARY_PATH="$(pwd)/target/out:$(pwd)/build_sysroot/sysroot/lib/rustlib/$TARGET_TRIPLE/lib:$GCC_PATH" export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH +# NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc. +# To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH. +# Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc +export PATH="/opt/gcc/bin:$PATH" diff --git a/failing-lto-tests.txt b/failing-lto-tests.txt new file mode 100644 index 00000000000..2e0b6134070 --- /dev/null +++ b/failing-lto-tests.txt @@ -0,0 +1,23 @@ +tests/ui/lint/unsafe_code/forge_unsafe_block.rs +tests/ui/lint/unused-qualification-in-derive-expansion.rs +tests/ui/macro-quote-test.rs +tests/ui/macros/proc_macro.rs +tests/ui/panic-runtime/lto-unwind.rs +tests/ui/resolve/derive-macro-1.rs +tests/ui/resolve/derive-macro-2.rs +tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs +tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs +tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs +tests/ui/rust-2018/suggestions-not-always-applicable.rs +tests/ui/rust-2021/reserved-prefixes-via-macro.rs +tests/ui/underscore-imports/duplicate.rs +tests/ui/async-await/issues/issue-60674.rs +tests/ui/attributes/main-removed-2/main.rs +tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs +tests/ui/crate-loading/cross-compiled-proc-macro.rs +tests/ui/derives/derive-marker-tricky.rs +tests/ui/diagnostic_namespace/existing_proc_macros.rs +tests/ui/fmt/format-args-capture-issue-106408.rs +tests/ui/fmt/indoc-issue-106408.rs +tests/ui/hygiene/issue-77523-def-site-async-await.rs +tests/ui/inherent-impls-overlap-check/no-overlap.rs diff --git a/failing-non-lto-tests.txt b/failing-non-lto-tests.txt new file mode 100644 index 00000000000..2f338f7d3c8 --- /dev/null +++ b/failing-non-lto-tests.txt @@ -0,0 +1,11 @@ +tests/ui/issues/issue-44056.rs +tests/ui/lto/fat-lto.rs +tests/ui/lto/debuginfo-lto.rs +tests/ui/lto/lto-many-codegen-units.rs +tests/ui/lto/issue-100772.rs +tests/ui/lto/lto-rustc-loads-linker-plugin.rs +tests/ui/panic-runtime/lto-unwind.rs +tests/ui/sanitize/issue-111184-generator-witness.rs +tests/ui/sepcomp/sepcomp-lib-lto.rs +tests/ui/lto/lto-opt-level-s.rs +tests/ui/lto/lto-opt-level-z.rs diff --git a/failing-ui-tests.txt b/failing-ui-tests.txt index fe0df3347bb..0711ae99a3e 100644 --- a/failing-ui-tests.txt +++ b/failing-ui-tests.txt @@ -1,11 +1,5 @@ -tests/ui/allocator/custom-in-block.rs -tests/ui/allocator/custom-in-submodule.rs -tests/ui/allocator/custom.rs -tests/ui/allocator/hygiene.rs tests/ui/allocator/no_std-alloc-error-handler-custom.rs tests/ui/allocator/no_std-alloc-error-handler-default.rs -tests/ui/allocator/xcrate-use.rs -tests/ui/allocator/xcrate-use2.rs tests/ui/asm/may_unwind.rs tests/ui/asm/x86_64/multiple-clobber-abi.rs tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs @@ -14,7 +8,6 @@ tests/ui/linkage-attr/linkage1.rs tests/ui/lto/dylib-works.rs tests/ui/numbers-arithmetic/saturating-float-casts.rs tests/ui/polymorphization/promoted-function.rs -tests/ui/process/nofile-limit.rs tests/ui/sepcomp/sepcomp-cci.rs tests/ui/sepcomp/sepcomp-extern.rs tests/ui/sepcomp/sepcomp-fns-backwards.rs @@ -53,8 +46,8 @@ tests/ui/issues/issue-40883.rs tests/ui/issues/issue-43853.rs tests/ui/issues/issue-47364.rs tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs -tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs +tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs tests/ui/simd/issue-89193.rs @@ -64,9 +57,15 @@ tests/ui/alloc-error/default-alloc-error-hook.rs tests/ui/generator/panic-safe.rs tests/ui/issues/issue-14875.rs tests/ui/issues/issue-29948.rs -tests/ui/panic-while-printing.rs -tests/ui/enum-discriminant/get_discr.rs tests/ui/panics/nested_panic_caught.rs tests/ui/simd/intrinsic/generic-bswap-byte.rs tests/ui/const_prop/ice-issue-111353.rs tests/ui/process/println-with-broken-pipe.rs +tests/ui/panic-runtime/lto-abort.rs +tests/ui/lto/thin-lto-inlines2.rs +tests/ui/lto/weak-works.rs +tests/ui/lto/thin-lto-inlines.rs +tests/ui/lto/thin-lto-global-allocator.rs +tests/ui/lto/msvc-imp-present.rs +tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs +tests/ui/lto/all-crates.rs diff --git a/locales/en-US.ftl b/locales/en-US.ftl deleted file mode 100644 index 2181d49eeef..00000000000 --- a/locales/en-US.ftl +++ /dev/null @@ -1,65 +0,0 @@ -codegen_gcc_unwinding_inline_asm = - GCC backend does not support unwinding from inline asm - -codegen_gcc_lto_not_supported = - LTO is not supported. You may get a linker error. - -codegen_gcc_invalid_monomorphization_basic_integer = - invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}` - -codegen_gcc_invalid_monomorphization_invalid_float_vector = - invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}` - -codegen_gcc_invalid_monomorphization_not_float = - invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type - -codegen_gcc_invalid_monomorphization_unrecognized = - invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` - -codegen_gcc_invalid_monomorphization_expected_signed_unsigned = - invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type - -codegen_gcc_invalid_monomorphization_unsupported_element = - invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}` - -codegen_gcc_invalid_monomorphization_invalid_bitmask = - invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` - -codegen_gcc_invalid_monomorphization_simd_shuffle = - invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}` - -codegen_gcc_invalid_monomorphization_expected_simd = - invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}` - -codegen_gcc_invalid_monomorphization_mask_type = - invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_` - -codegen_gcc_invalid_monomorphization_return_length = - invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len} - -codegen_gcc_invalid_monomorphization_return_length_input_type = - invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len} - -codegen_gcc_invalid_monomorphization_return_element = - invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}` - -codegen_gcc_invalid_monomorphization_return_type = - invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` - -codegen_gcc_invalid_monomorphization_inserted_type = - invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}` - -codegen_gcc_invalid_monomorphization_return_integer_type = - invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}` - -codegen_gcc_invalid_monomorphization_mismatched_lengths = - invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}` - -codegen_gcc_invalid_monomorphization_unsupported_cast = - invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}` - -codegen_gcc_invalid_monomorphization_unsupported_operation = - invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` - -codegen_gcc_invalid_minimum_alignment = - invalid minimum global alignment: {$err} diff --git a/messages.ftl b/messages.ftl index 2fd0daee3e7..de9be3a5528 100644 --- a/messages.ftl +++ b/messages.ftl @@ -9,3 +9,17 @@ codegen_gcc_tied_target_features = the target features {$features} must all be e codegen_gcc_unwinding_inline_asm = GCC backend does not support unwinding from inline asm + +codegen_gcc_copy_bitcode = failed to copy bitcode to object file: {$err} + +codegen_gcc_dynamic_linking_with_lto = + cannot prefer dynamic linking when performing LTO + .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO + +codegen_gcc_load_bitcode = failed to load bitcode of module "{$name}" + +codegen_gcc_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs + +codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto` + +codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err}) diff --git a/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch b/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch index 93c63b5dcac..2a55f2cb796 100644 --- a/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch +++ b/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch @@ -1,25 +1,26 @@ -From c3821e02fbd6cb5ad6e06d759fccdc9073712375 Mon Sep 17 00:00:00 2001 +From b8f3eed3053c9333b5dfbeaeb2a6a65a4b3156df Mon Sep 17 00:00:00 2001 From: Antoni Boucher -Date: Tue, 7 Jun 2022 21:40:13 -0400 -Subject: [PATCH] Add stdarch Cargo.toml for testing +Date: Tue, 29 Aug 2023 13:06:34 -0400 +Subject: [PATCH] Patch 0001-Add-stdarch-Cargo.toml-for-testing.patch --- - library/stdarch/Cargo.toml | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) + library/stdarch/Cargo.toml | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) create mode 100644 library/stdarch/Cargo.toml diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml new file mode 100644 -index 0000000..fbe0a95 +index 0000000..4c63700 --- /dev/null +++ b/library/stdarch/Cargo.toml -@@ -0,0 +1,20 @@ +@@ -0,0 +1,21 @@ +[workspace] ++resolver = "1" +members = [ + "crates/core_arch", + "crates/std_detect", + "crates/stdarch-gen", -+ "examples/" ++ #"examples/" +] +exclude = [ + "crates/wasm-assert-instr-tests" @@ -35,5 +36,5 @@ index 0000000..fbe0a95 +opt-level = 3 +incremental = true -- -2.26.2.7.g19db9cfb68.dirty +2.42.0 diff --git a/patches/0001-Disable-examples.patch b/patches/0001-Disable-examples.patch deleted file mode 100644 index 1b71df1ca8d..00000000000 --- a/patches/0001-Disable-examples.patch +++ /dev/null @@ -1,25 +0,0 @@ -From a2d53a324a02c04b76c0e9d39dc15cd443a3b8b2 Mon Sep 17 00:00:00 2001 -From: Antoni Boucher -Date: Fri, 25 Nov 2022 11:18:11 -0500 -Subject: [PATCH] Disable examples - ---- - library/stdarch/Cargo.toml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml -index fbe0a95..748d72d 100644 ---- a/library/stdarch/Cargo.toml -+++ b/library/stdarch/Cargo.toml -@@ -3,7 +3,7 @@ members = [ - "crates/core_arch", - "crates/std_detect", - "crates/stdarch-gen", -- "examples/" -+ #"examples/" - ] - exclude = [ - "crates/wasm-assert-instr-tests" --- -2.26.2.7.g19db9cfb68.dirty - diff --git a/src/back/lto.rs b/src/back/lto.rs new file mode 100644 index 00000000000..529454b119e --- /dev/null +++ b/src/back/lto.rs @@ -0,0 +1,341 @@ +/// GCC requires to use the same toolchain for the whole compilation when doing LTO. +/// So, we need the same version/commit of the linker (gcc) and lto front-end binaries (lto1, +/// lto-wrapper, liblto_plugin.so). + +// FIXME(antoyo): the executables compiled with LTO are bigger than those compiled without LTO. +// Since it is the opposite for cg_llvm, check if this is normal. +// +// Maybe we embed the bitcode in the final binary? +// It doesn't look like we try to generate fat objects for the final binary. +// Check if the way we combine the object files make it keep the LTO sections on the final link. +// Maybe that's because the combined object files contain the IR (true) and the final link +// does not remove it? +// +// TODO(antoyo): for performance, check which optimizations the C++ frontend enables. +// +// Fix these warnings: +// /usr/bin/ld: warning: type of symbol `_RNvNvNvNtCs5JWOrf9uCus_5rayon11thread_pool19WORKER_THREAD_STATE7___getit5___KEY' changed from 1 to 6 in /tmp/ccKeUSiR.ltrans0.ltrans.o +// /usr/bin/ld: warning: type of symbol `_RNvNvNvNvNtNtNtCsAj5i4SGTR7_3std4sync4mpmc5waker17current_thread_id5DUMMY7___getit5___KEY' changed from 1 to 6 in /tmp/ccKeUSiR.ltrans0.ltrans.o +// /usr/bin/ld: warning: incremental linking of LTO and non-LTO objects; using -flinker-output=nolto-rel which will bypass whole program optimization + +use std::ffi::CString; +use std::fs::{self, File}; +use std::path::{Path, PathBuf}; + +use gccjit::OutputKind; +use object::read::archive::ArchiveFile; +use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule}; +use rustc_codegen_ssa::back::symbol_export; +use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput}; +use rustc_codegen_ssa::traits::*; +use rustc_codegen_ssa::{looks_like_rust_object_file, ModuleCodegen, ModuleKind}; +use rustc_data_structures::memmap::Mmap; +use rustc_errors::{FatalError, Handler}; +use rustc_hir::def_id::LOCAL_CRATE; +use rustc_middle::dep_graph::WorkProduct; +use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel}; +use rustc_session::config::{CrateType, Lto}; +use tempfile::{TempDir, tempdir}; + +use crate::back::write::save_temp_bitcode; +use crate::errors::{ + DynamicLinkingWithLTO, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, +}; +use crate::{GccCodegenBackend, GccContext, to_gcc_opt_level}; + +/// We keep track of the computed LTO cache keys from the previous +/// session to determine which CGUs we can reuse. +//pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin"; + +pub fn crate_type_allows_lto(crate_type: CrateType) -> bool { + match crate_type { + CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true, + CrateType::Rlib | CrateType::ProcMacro => false, + } +} + +struct LtoData { + // TODO(antoyo): use symbols_below_threshold. + //symbols_below_threshold: Vec, + upstream_modules: Vec<(SerializedModule, CString)>, + tmp_path: TempDir, +} + +fn prepare_lto(cgcx: &CodegenContext, diag_handler: &Handler) -> Result { + let export_threshold = match cgcx.lto { + // We're just doing LTO for our one crate + Lto::ThinLocal => SymbolExportLevel::Rust, + + // We're doing LTO for the entire crate graph + Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&cgcx.crate_types), + + Lto::No => panic!("didn't request LTO but we're doing LTO"), + }; + + let tmp_path = + match tempdir() { + Ok(tmp_path) => tmp_path, + Err(error) => { + eprintln!("Cannot create temporary directory: {}", error); + return Err(FatalError); + }, + }; + + let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| { + if info.level.is_below_threshold(export_threshold) || info.used { + Some(CString::new(name.as_str()).unwrap()) + } else { + None + } + }; + let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO"); + let mut symbols_below_threshold = { + let _timer = cgcx.prof.generic_activity("GCC_lto_generate_symbols_below_threshold"); + exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::>() + }; + info!("{} symbols to preserve in this crate", symbols_below_threshold.len()); + + // If we're performing LTO for the entire crate graph, then for each of our + // upstream dependencies, find the corresponding rlib and load the bitcode + // from the archive. + // + // We save off all the bytecode and GCC module file path for later processing + // with either fat or thin LTO + let mut upstream_modules = Vec::new(); + if cgcx.lto != Lto::ThinLocal { + // Make sure we actually can run LTO + for crate_type in cgcx.crate_types.iter() { + if !crate_type_allows_lto(*crate_type) { + diag_handler.emit_err(LtoDisallowed); + return Err(FatalError); + } else if *crate_type == CrateType::Dylib { + if !cgcx.opts.unstable_opts.dylib_lto { + diag_handler.emit_err(LtoDylib); + return Err(FatalError); + } + } + } + + if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto { + diag_handler.emit_err(DynamicLinkingWithLTO); + return Err(FatalError); + } + + for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() { + let exported_symbols = + cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO"); + { + let _timer = + cgcx.prof.generic_activity("GCC_lto_generate_symbols_below_threshold"); + symbols_below_threshold + .extend(exported_symbols[&cnum].iter().filter_map(symbol_filter)); + } + + let archive_data = unsafe { + Mmap::map(File::open(&path).expect("couldn't open rlib")) + .expect("couldn't map rlib") + }; + let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib"); + let obj_files = archive + .members() + .filter_map(|child| { + child.ok().and_then(|c| { + std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c)) + }) + }) + .filter(|&(name, _)| looks_like_rust_object_file(name)); + for (name, child) in obj_files { + info!("adding bitcode from {}", name); + let path = tmp_path.path().join(name); + match save_as_file(child.data(&*archive_data).expect("corrupt rlib"), &path) { + Ok(()) => { + let buffer = ModuleBuffer::new(path); + let module = SerializedModule::Local(buffer); + upstream_modules.push((module, CString::new(name).unwrap())); + } + Err(e) => { + diag_handler.emit_err(e); + return Err(FatalError); + } + } + } + } + } + + Ok(LtoData { + //symbols_below_threshold, + upstream_modules, + tmp_path, + }) +} + +fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { + fs::write(path, obj) + .map_err(|error| LtoBitcodeFromRlib { + gcc_err: format!("write object file to temp dir: {}", error) + }) +} + +/// Performs fat LTO by merging all modules into a single one and returning it +/// for further optimization. +pub(crate) fn run_fat( + cgcx: &CodegenContext, + modules: Vec>, + cached_modules: Vec<(SerializedModule, WorkProduct)>, +) -> Result, FatalError> { + let diag_handler = cgcx.create_diag_handler(); + let lto_data = prepare_lto(cgcx, &diag_handler)?; + /*let symbols_below_threshold = + lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ + fat_lto(cgcx, &diag_handler, modules, cached_modules, lto_data.upstream_modules, lto_data.tmp_path, + //&symbols_below_threshold, + ) +} + +fn fat_lto(cgcx: &CodegenContext, _diag_handler: &Handler, modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, + //symbols_below_threshold: &[*const libc::c_char], +) -> Result, FatalError> { + let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module"); + info!("going for a fat lto"); + + // Sort out all our lists of incoming modules into two lists. + // + // * `serialized_modules` (also and argument to this function) contains all + // modules that are serialized in-memory. + // * `in_memory` contains modules which are already parsed and in-memory, + // such as from multi-CGU builds. + // + // All of `cached_modules` (cached from previous incremental builds) can + // immediately go onto the `serialized_modules` modules list and then we can + // split the `modules` array into these two lists. + let mut in_memory = Vec::new(); + serialized_modules.extend(cached_modules.into_iter().map(|(buffer, wp)| { + info!("pushing cached module {:?}", wp.cgu_name); + (buffer, CString::new(wp.cgu_name).unwrap()) + })); + for module in modules { + match module { + FatLtoInput::InMemory(m) => in_memory.push(m), + FatLtoInput::Serialized { name, buffer } => { + info!("pushing serialized module {:?}", name); + let buffer = SerializedModule::Local(buffer); + serialized_modules.push((buffer, CString::new(name).unwrap())); + } + } + } + + // Find the "costliest" module and merge everything into that codegen unit. + // All the other modules will be serialized and reparsed into the new + // context, so this hopefully avoids serializing and parsing the largest + // codegen unit. + // + // Additionally use a regular module as the base here to ensure that various + // file copy operations in the backend work correctly. The only other kind + // of module here should be an allocator one, and if your crate is smaller + // than the allocator module then the size doesn't really matter anyway. + let costliest_module = in_memory + .iter() + .enumerate() + .filter(|&(_, module)| module.kind == ModuleKind::Regular) + .map(|(i, _module)| { + //let cost = unsafe { llvm::LLVMRustModuleCost(module.module_llvm.llmod()) }; + // TODO(antoyo): compute the cost of a module if GCC allows this. + (0, i) + }) + .max(); + + // If we found a costliest module, we're good to go. Otherwise all our + // inputs were serialized which could happen in the case, for example, that + // all our inputs were incrementally reread from the cache and we're just + // re-executing the LTO passes. If that's the case deserialize the first + // module and create a linker with it. + let mut module: ModuleCodegen = match costliest_module { + Some((_cost, i)) => in_memory.remove(i), + None => { + unimplemented!("Incremental"); + /*assert!(!serialized_modules.is_empty(), "must have at least one serialized module"); + let (buffer, name) = serialized_modules.remove(0); + info!("no in-memory regular modules to choose from, parsing {:?}", name); + ModuleCodegen { + module_llvm: GccContext::parse(cgcx, &name, buffer.data(), diag_handler)?, + name: name.into_string().unwrap(), + kind: ModuleKind::Regular, + }*/ + } + }; + let mut serialized_bitcode = Vec::new(); + { + info!("using {:?} as a base module", module.name); + + // We cannot load and merge GCC contexts in memory like cg_llvm is doing. + // Instead, we combine the object files into a single object file. + for module in in_memory { + let path = tmp_path.path().to_path_buf().join(&module.name); + let path = path.to_str().expect("path"); + let context = &module.module_llvm.context; + let config = cgcx.config(module.kind); + // NOTE: we need to set the optimization level here in order for LTO to do its job. + context.set_optimization_level(to_gcc_opt_level(config.opt_level)); + context.add_command_line_option("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + context.compile_to_file(OutputKind::ObjectFile, path); + let buffer = ModuleBuffer::new(PathBuf::from(path)); + let llmod_id = CString::new(&module.name[..]).unwrap(); + serialized_modules.push((SerializedModule::Local(buffer), llmod_id)); + } + // Sort the modules to ensure we produce deterministic results. + serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1)); + + // We add the object files and save in should_combine_object_files that we should combine + // them into a single object file when compiling later. + for (bc_decoded, name) in serialized_modules { + let _timer = cgcx + .prof + .generic_activity_with_arg_recorder("GCC_fat_lto_link_module", |recorder| { + recorder.record_arg(format!("{:?}", name)) + }); + info!("linking {:?}", name); + match bc_decoded { + SerializedModule::Local(ref module_buffer) => { + module.module_llvm.should_combine_object_files = true; + module.module_llvm.context.add_driver_option(module_buffer.0.to_str().expect("path")); + }, + SerializedModule::FromRlib(_) => unimplemented!("from rlib"), + SerializedModule::FromUncompressedFile(_) => unimplemented!("from uncompressed file"), + } + serialized_bitcode.push(bc_decoded); + } + save_temp_bitcode(cgcx, &module, "lto.input"); + + // Internalize everything below threshold to help strip out more modules and such. + /*unsafe { + let ptr = symbols_below_threshold.as_ptr(); + llvm::LLVMRustRunRestrictionPass( + llmod, + ptr as *const *const libc::c_char, + symbols_below_threshold.len() as libc::size_t, + );*/ + save_temp_bitcode(cgcx, &module, "lto.after-restriction"); + //} + } + + // NOTE: save the temporary directory used by LTO so that it gets deleted after linking instead + // of now. + module.module_llvm.temp_dir = Some(tmp_path); + + Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: serialized_bitcode }) +} + +pub struct ModuleBuffer(PathBuf); + +impl ModuleBuffer { + pub fn new(path: PathBuf) -> ModuleBuffer { + ModuleBuffer(path) + } +} + +impl ModuleBufferMethods for ModuleBuffer { + fn data(&self) -> &[u8] { + unimplemented!("data not needed for GCC codegen"); + } +} diff --git a/src/back/mod.rs b/src/back/mod.rs index d692799d764..10187eab0d7 100644 --- a/src/back/mod.rs +++ b/src/back/mod.rs @@ -1 +1,2 @@ +pub mod lto; pub mod write; diff --git a/src/back/write.rs b/src/back/write.rs index 5f54ac4ebc6..04772d7707a 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -2,27 +2,71 @@ use std::{env, fs}; use gccjit::OutputKind; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; -use rustc_codegen_ssa::back::write::{CodegenContext, EmitObj, ModuleConfig}; +use rustc_codegen_ssa::back::link::ensure_removed; +use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig}; use rustc_errors::Handler; +use rustc_fs_util::link_or_copy; use rustc_session::config::OutputType; use rustc_span::fatal_error::FatalError; use rustc_target::spec::SplitDebuginfo; use crate::{GccCodegenBackend, GccContext}; +use crate::errors::CopyBitcode; -pub(crate) unsafe fn codegen(cgcx: &CodegenContext, _diag_handler: &Handler, module: ModuleCodegen, config: &ModuleConfig) -> Result { - let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name); +pub(crate) unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &Handler, module: ModuleCodegen, config: &ModuleConfig) -> Result { + let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name); { let context = &module.module_llvm.context; let module_name = module.name.clone(); + + let should_combine_object_files = module.module_llvm.should_combine_object_files; + let module_name = Some(&module_name[..]); - let _bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); + // NOTE: Only generate object files with GIMPLE when this environment variable is set for + // now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit). + let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1"); + + let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); - if config.bitcode_needed() { + if config.bitcode_needed() && fat_lto { + let _timer = cgcx + .prof + .generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name); + // TODO(antoyo) + /*if let Some(bitcode_filename) = bc_out.file_name() { + cgcx.prof.artifact_size( + "llvm_bitcode", + bitcode_filename.to_string_lossy(), + data.len() as u64, + ); + }*/ + + if config.emit_bc || config.emit_obj == EmitObj::Bitcode { + let _timer = cgcx + .prof + .generic_activity_with_arg("GCC_module_codegen_emit_bitcode", &*module.name); + context.add_command_line_option("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + context.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str")); + } + + if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) { + let _timer = cgcx + .prof + .generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name); + // TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? + //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); + + context.add_command_line_option("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + context.add_command_line_option("-ffat-lto-objects"); + // TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument). + context.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str")); + } } if config.emit_ir { @@ -32,7 +76,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, _diag_han if config.emit_asm { let _timer = cgcx .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name); + .generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name); let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str")); } @@ -41,7 +85,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, _diag_han EmitObj::ObjectCode(_) => { let _timer = cgcx .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name); + .generic_activity_with_arg("GCC_module_codegen_emit_obj", &*module.name); if env::var("CG_GCCJIT_DUMP_MODULE_NAMES").as_deref() == Ok("1") { println!("Module {}", module.name); } @@ -60,11 +104,36 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, _diag_han context.set_debug_info(true); context.dump_to_file(path, true); } - context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str")); + if should_combine_object_files && fat_lto { + context.add_command_line_option("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + + context.add_driver_option("-Wl,-r"); + // NOTE: we need -nostdlib, otherwise, we get the following error: + // /usr/bin/ld: cannot find -lgcc_s: No such file or directory + context.add_driver_option("-nostdlib"); + // NOTE: without -fuse-linker-plugin, we get the following error: + // lto1: internal compiler error: decompressed stream: Destination buffer is too small + context.add_driver_option("-fuse-linker-plugin"); + + // NOTE: this doesn't actually generate an executable. With the above flags, it combines the .o files together in another .o. + context.compile_to_file(OutputKind::Executable, obj_out.to_str().expect("path to str")); + } + else { + context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str")); + } } EmitObj::Bitcode => { - // TODO(antoyo) + debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); + if let Err(err) = link_or_copy(&bc_out, &obj_out) { + diag_handler.emit_err(CopyBitcode { err }); + } + + if !config.emit_bc { + debug!("removing_bitcode {:?}", bc_out); + ensure_removed(diag_handler, &bc_out); + } } EmitObj::None => {} @@ -82,3 +151,18 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, _diag_han pub(crate) fn link(_cgcx: &CodegenContext, _diag_handler: &Handler, mut _modules: Vec>) -> Result, FatalError> { unimplemented!(); } + +pub(crate) fn save_temp_bitcode(cgcx: &CodegenContext, _module: &ModuleCodegen, _name: &str) { + if !cgcx.save_temps { + return; + } + unimplemented!(); + /*unsafe { + let ext = format!("{}.bc", name); + let cgu = Some(&module.name[..]); + let path = cgcx.output_filenames.temp_path_ext(&ext, cgu); + let cstr = path_to_c_string(&path); + let llmod = module.module_llvm.llmod(); + llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr()); + }*/ +} diff --git a/src/base.rs b/src/base.rs index bf0309fea14..266d60da10c 100644 --- a/src/base.rs +++ b/src/base.rs @@ -56,6 +56,7 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { match linkage { Linkage::External => FunctionType::Exported, + // TODO(antoyo): set the attribute externally_visible. Linkage::AvailableExternally => FunctionType::Extern, Linkage::LinkOnceAny => unimplemented!(), Linkage::LinkOnceODR => unimplemented!(), @@ -91,7 +92,6 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, Arc)) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... - //let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str()); let context = Context::default(); context.add_command_line_option("-fexceptions"); @@ -152,7 +152,10 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< context.add_command_line_option("-fdump-rtl-all"); } if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-tree-all"); + context.add_command_line_option("-fdump-tree-all-eh"); + } + if env::var("CG_GCCJIT_DUMP_IPA_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-ipa-all-eh"); } if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { context.set_dump_code_on_compile(true); @@ -168,6 +171,10 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< context.set_keep_intermediates(true); } + if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") { + context.add_driver_option("-v"); + } + // NOTE: The codegen generates unrechable blocks. context.set_allow_unreachable_blocks(true); @@ -197,7 +204,9 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< ModuleCodegen { name: cgu_name.to_string(), module_llvm: GccContext { - context + context, + should_combine_object_files: false, + temp_dir: None, }, kind: ModuleKind::Regular, } diff --git a/src/declare.rs b/src/declare.rs index 493626c3cf5..e673d0af4c7 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -1,4 +1,6 @@ use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type}; +#[cfg(feature="master")] +use gccjit::{FnAttribute, ToRValue}; use rustc_codegen_ssa::traits::BaseTypeMethods; use rustc_middle::ty::Ty; use rustc_span::Symbol; @@ -114,6 +116,44 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll .collect(); let func = cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, mangle_name(name), variadic); cx.functions.borrow_mut().insert(name.to_string(), func); + + #[cfg(feature="master")] + if name == "rust_eh_personality" { + // NOTE: GCC will sometimes change the personality function set on a function from + // rust_eh_personality to __gcc_personality_v0 as an optimization. + // As such, we need to create a weak alias from __gcc_personality_v0 to + // rust_eh_personality in order to avoid a linker error. + // This needs to be weak in order to still allow using the standard + // __gcc_personality_v0 when the linking to it. + // Since aliases don't work (maybe because of a bug in LTO partitioning?), we + // create a wrapper function that calls rust_eh_personality. + + let params: Vec<_> = param_types.into_iter().enumerate() + .map(|(index, param)| cx.context.new_parameter(None, *param, &format!("param{}", index))) // TODO(antoyo): set name. + .collect(); + let gcc_func = cx.context.new_function(None, FunctionType::Exported, return_type, ¶ms, "__gcc_personality_v0", variadic); + + // We need a normal extern function for the crates that access rust_eh_personality + // without defining it, otherwise we'll get a compiler error. + // + // For the crate defining it, that needs to be a weak alias instead. + gcc_func.add_attribute(FnAttribute::Weak); + + let block = gcc_func.new_block("start"); + let mut args = vec![]; + for param in ¶ms { + args.push(param.to_rvalue()); + } + let call = cx.context.new_call(None, func, &args); + if return_type == cx.type_void() { + block.add_eval(None, call); + block.end_with_void_return(None); + } + else { + block.end_with_return(None, call); + } + } + func }; diff --git a/src/errors.rs b/src/errors.rs index 693367192b1..19a967cb489 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -40,3 +40,34 @@ pub(crate) struct TiedTargetFeatures { pub span: Span, pub features: String, } + +#[derive(Diagnostic)] +#[diag(codegen_gcc_copy_bitcode)] +pub(crate) struct CopyBitcode { + pub err: std::io::Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_gcc_dynamic_linking_with_lto)] +#[note] +pub(crate) struct DynamicLinkingWithLTO; + +#[derive(Diagnostic)] +#[diag(codegen_gcc_load_bitcode)] +pub(crate) struct LoadBitcode { + name: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_gcc_lto_disallowed)] +pub(crate) struct LtoDisallowed; + +#[derive(Diagnostic)] +#[diag(codegen_gcc_lto_dylib)] +pub(crate) struct LtoDylib; + +#[derive(Diagnostic)] +#[diag(codegen_gcc_lto_bitcode_from_rlib)] +pub(crate) struct LtoBitcodeFromRlib { + pub gcc_err: String, +} diff --git a/src/lib.rs b/src/lib.rs index 7b55a4e4082..2de8fb3fc70 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,12 @@ * TODO(antoyo): implement equality in libgccjit based on https://zpz.github.io/blog/overloading-equality-operator-in-cpp-class-hierarchy/ (for type equality?) * TODO(antoyo): support #[inline] attributes. * TODO(antoyo): support LTO (gcc's equivalent to Full LTO is -flto -flto-partition=one — https://documentation.suse.com/sbp/all/html/SBP-GCC-10/index.html). + * For Thin LTO, this might be helpful: + * In gcc 4.6 -fwhopr was removed and became default with -flto. The non-whopr path can still be executed via -flto-partition=none. + * + * Maybe some missing optizations enabled by rustc's LTO is in there: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html + * Like -fipa-icf (should be already enabled) and maybe -fdevirtualize-at-ltrans. + * TODO: disable debug info always being emitted. Perhaps this slows down things? * * TODO(antoyo): remove the patches. */ @@ -28,6 +34,7 @@ extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_errors; extern crate rustc_fluent_macro; +extern crate rustc_fs_util; extern crate rustc_hir; extern crate rustc_macros; extern crate rustc_metadata; @@ -35,6 +42,8 @@ extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; +#[macro_use] +extern crate tracing; // This prevents duplicating functions and statics that are already part of the host rustc process. #[allow(unused_extern_crates)] @@ -65,22 +74,24 @@ mod type_of; use std::any::Any; use std::sync::Arc; #[cfg(not(feature="master"))] -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::AtomicBool; +#[cfg(not(feature="master"))] +use std::sync::atomic::Ordering; -use crate::errors::LTONotSupported; use gccjit::{Context, OptimizationLevel}; #[cfg(feature="master")] use gccjit::TargetInfo; #[cfg(not(feature="master"))] use gccjit::CType; +use errors::LTONotSupported; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; use rustc_codegen_ssa::base::codegen_crate; use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn}; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; use rustc_codegen_ssa::target_features::supported_target_features; -use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods}; use rustc_data_structures::fx::FxIndexMap; +use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods}; use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMessage}; use rustc_fluent_macro::fluent_messages; use rustc_metadata::EncodedMetadata; @@ -91,9 +102,10 @@ use rustc_session::config::{Lto, OptLevel, OutputFilenames}; use rustc_session::Session; use rustc_span::Symbol; use rustc_span::fatal_error::FatalError; -#[cfg(not(feature="master"))] use tempfile::TempDir; +use crate::back::lto::ModuleBuffer; + fluent_messages! { "../messages.ftl" } pub struct PrintOnPanic String>(pub F); @@ -136,7 +148,7 @@ impl CodegenBackend for GccCodegenBackend { fn init(&self, sess: &Session) { #[cfg(feature="master")] gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); - if sess.lto() != Lto::No { + if sess.lto() == Lto::Thin { sess.emit_warning(LTONotSupported {}); } @@ -194,7 +206,12 @@ impl ExtraBackendMethods for GccCodegenBackend { fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module { let mut mods = GccContext { context: Context::default(), + should_combine_object_files: false, + temp_dir: None, }; + + // TODO(antoyo): only set for x86. + mods.context.add_command_line_option("-masm=intel"); unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); } mods } @@ -211,14 +228,6 @@ impl ExtraBackendMethods for GccCodegenBackend { } } -pub struct ModuleBuffer; - -impl ModuleBufferMethods for ModuleBuffer { - fn data(&self) -> &[u8] { - unimplemented!(); - } -} - pub struct ThinBuffer; impl ThinBufferMethods for ThinBuffer { @@ -229,6 +238,9 @@ impl ThinBufferMethods for ThinBuffer { pub struct GccContext { context: Context<'static>, + should_combine_object_files: bool, + // Temporary directory used by LTO. We keep it here so that it's not removed before linking. + temp_dir: Option, } unsafe impl Send for GccContext {} @@ -243,18 +255,8 @@ impl WriteBackendMethods for GccCodegenBackend { type ThinData = (); type ThinBuffer = ThinBuffer; - fn run_fat_lto(_cgcx: &CodegenContext, mut modules: Vec>, _cached_modules: Vec<(SerializedModule, WorkProduct)>) -> Result, FatalError> { - // TODO(antoyo): implement LTO by sending -flto to libgccjit and adding the appropriate gcc linker plugins. - // NOTE: implemented elsewhere. - // TODO(antoyo): what is implemented elsewhere ^ ? - let module = - match modules.remove(0) { - FatLtoInput::InMemory(module) => module, - FatLtoInput::Serialized { .. } => { - unimplemented!(); - } - }; - Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: vec![] }) + fn run_fat_lto(cgcx: &CodegenContext, modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>) -> Result, FatalError> { + back::lto::run_fat(cgcx, modules, cached_modules) } fn run_thin_lto(_cgcx: &CodegenContext, _modules: Vec<(String, Self::ThinBuffer)>, _cached_modules: Vec<(SerializedModule, WorkProduct)>) -> Result<(Vec>, Vec), FatalError> { diff --git a/test.sh b/test.sh index 1054fdf7ea1..c47cf140ae4 100755 --- a/test.sh +++ b/test.sh @@ -3,6 +3,7 @@ # TODO(antoyo): rewrite to cargo-make (or just) or something like that to only rebuild the sysroot when needed? set -e +#set -x if [ -f ./gcc_path ]; then export GCC_PATH=$(cat gcc_path) @@ -345,14 +346,13 @@ function test_rustc() { git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed - rm -r tests/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,borrowck/,chalkify/bugs/,test*,*lto*.rs,consts/const-float-bits-reject-conv.rs,consts/issue-miri-1910.rs} || true + rm -r tests/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,borrowck/,chalkify/bugs/,test*,consts/const-float-bits-reject-conv.rs,consts/issue-miri-1910.rs} || true rm tests/ui/mir/mir_heavy_promoted.rs # this test is oom-killed in the CI. # Tests generating errors. rm tests/ui/consts/const-eval/nonnull_as_ref_ub.rs tests/ui/consts/issue-94675.rs - for test in $(rg --files-with-matches "thread|lto" tests/ui); do + for test in $(rg --files-with-matches "thread" tests/ui); do rm $test done - git checkout tests/ui/lto/auxiliary/dylib.rs git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs git checkout tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs From 03bcfff8b37f465143fccdcab7f5576a015984af Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 31 Aug 2023 21:19:36 +0200 Subject: [PATCH 062/103] Only apply NoAlias attribute if optimization is enabled --- src/abi.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/abi.rs b/src/abi.rs index 874ac0b087e..9f6e2f7ff10 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -3,6 +3,7 @@ use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::ty::Ty; +use rustc_session::config; use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; use crate::builder::Builder; @@ -122,7 +123,8 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { #[cfg(feature = "master")] let apply_attrs = |ty: Type<'gcc>, attrs: &ArgAttributes| { - if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) + if cx.sess().opts.optimize != config::OptLevel::No + && attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) { ty.make_restrict() } else { From 8028885239406c9ebd9b62dc886732024a03b8e5 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 1 Sep 2023 14:27:21 -0700 Subject: [PATCH 063/103] Deduplicate inlined function debug info, but create a new lexical scope to child subsequent scopes and variables from colliding --- src/debuginfo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index a81585d4128..d1bfd833cd8 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -55,7 +55,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _llfn: RValue<'gcc>, _mir: &mir::Body<'tcx>, - ) -> Option> { + ) -> Option> { // TODO(antoyo) None } From d214df291c7f627288a9c14ee84a754ba077eea4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 6 Sep 2023 15:20:08 +0200 Subject: [PATCH 064/103] Fix gimple guide --- doc/gimple.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/gimple.md b/doc/gimple.md index 589cf3db7a6..1bd8035e75d 100644 --- a/doc/gimple.md +++ b/doc/gimple.md @@ -34,7 +34,7 @@ also add the calls we need to generate the GIMPLE: int main() { gcc_jit_context *ctxt = gcc_jit_context_acquire(); create_code(ctxt, NULL); - gcc_jit_context_compile_to_file(ctxt, GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY, "tmp"); + gcc_jit_context_dump_to_file(ctxt, "tmp.gimple", 1); return 0; } ``` @@ -42,16 +42,16 @@ int main() { Then we can compile it by using: ```console -gcc const.c -I `pwd`/gcc/gcc/jit/ -L `pwd`/gcc-build/gcc -lgccjit -o out +gcc local.c -I `pwd`/gcc/gcc/jit/ -L `pwd`/gcc-build/gcc -lgccjit -o out ``` And finally when you run it: ```console -LD_LIBRARY_PATH=`pwd`/gcc-build/gcc ./out +LD_LIBRARY_PATH=`pwd`/gcc-build/gcc LIBRARY_PATH=`pwd`/gcc-build/gcc ./out ``` -It should display: +You should now have a file named `tmp.gimple` which contains: ```c __attribute__((const)) From 7324ee2da86b560eae238d7a77314e3027441d43 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 6 Sep 2023 17:38:50 +0200 Subject: [PATCH 065/103] Add missing compilation --- doc/gimple.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/gimple.md b/doc/gimple.md index 1bd8035e75d..e2ae93cf20d 100644 --- a/doc/gimple.md +++ b/doc/gimple.md @@ -34,6 +34,7 @@ also add the calls we need to generate the GIMPLE: int main() { gcc_jit_context *ctxt = gcc_jit_context_acquire(); create_code(ctxt, NULL); + gcc_jit_context_compile(ctxt); gcc_jit_context_dump_to_file(ctxt, "tmp.gimple", 1); return 0; } From b3916539dd56c52a9d8e62a7b06bf9449aa8a23d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 7 Sep 2023 14:03:56 +0200 Subject: [PATCH 066/103] Set the correct gimple output format --- doc/gimple.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/doc/gimple.md b/doc/gimple.md index e2ae93cf20d..f97e50c32cb 100644 --- a/doc/gimple.md +++ b/doc/gimple.md @@ -33,9 +33,17 @@ also add the calls we need to generate the GIMPLE: ```C int main() { gcc_jit_context *ctxt = gcc_jit_context_acquire(); + // To set `-O3`, update it depending on your needs. + gcc_jit_context_set_int_option(ctxt, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); + // Very important option to generate the gimple format. + gcc_jit_context_add_command_line_option(ctxt, "-fdump-tree-gimple"); create_code(ctxt, NULL); + gcc_jit_context_compile(ctxt); - gcc_jit_context_dump_to_file(ctxt, "tmp.gimple", 1); + // If you want to compile to assembly (or any other format) directly, you can + // use the following call instead: + // gcc_jit_context_compile_to_file(ctxt, GCC_JIT_OUTPUT_KIND_ASSEMBLER, "out.s"); + return 0; } ``` @@ -46,13 +54,21 @@ Then we can compile it by using: gcc local.c -I `pwd`/gcc/gcc/jit/ -L `pwd`/gcc-build/gcc -lgccjit -o out ``` +Before running it, I recommend running: + +```console +rm -rf /tmp/libgccjit-* +``` + +to make it easier for you to know which folder to look into. + And finally when you run it: ```console LD_LIBRARY_PATH=`pwd`/gcc-build/gcc LIBRARY_PATH=`pwd`/gcc-build/gcc ./out ``` -You should now have a file named `tmp.gimple` which contains: +You should now have a file named with path looking like `/tmp/libgccjit-9OFqkD/fake.c.006t.gimple` which contains: ```c __attribute__((const)) From 3e61cc3de2c8835293bb864c9cec49439817e8ee Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 7 Sep 2023 14:21:58 +0200 Subject: [PATCH 067/103] Add simpler alternative to generate gimple --- doc/gimple.md | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/doc/gimple.md b/doc/gimple.md index f97e50c32cb..145c4eda3c1 100644 --- a/doc/gimple.md +++ b/doc/gimple.md @@ -36,7 +36,7 @@ int main() { // To set `-O3`, update it depending on your needs. gcc_jit_context_set_int_option(ctxt, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); // Very important option to generate the gimple format. - gcc_jit_context_add_command_line_option(ctxt, "-fdump-tree-gimple"); + gcc_jit_context_set_bool_option(ctxt, GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1); create_code(ctxt, NULL); gcc_jit_context_compile(ctxt); @@ -54,21 +54,13 @@ Then we can compile it by using: gcc local.c -I `pwd`/gcc/gcc/jit/ -L `pwd`/gcc-build/gcc -lgccjit -o out ``` -Before running it, I recommend running: - -```console -rm -rf /tmp/libgccjit-* -``` - -to make it easier for you to know which folder to look into. - And finally when you run it: ```console LD_LIBRARY_PATH=`pwd`/gcc-build/gcc LIBRARY_PATH=`pwd`/gcc-build/gcc ./out ``` -You should now have a file named with path looking like `/tmp/libgccjit-9OFqkD/fake.c.006t.gimple` which contains: +It should display: ```c __attribute__((const)) @@ -95,3 +87,25 @@ int xxx () return D.3394; } ``` + +An alternative way to generate the GIMPLE is to replace: + +```c + gcc_jit_context_set_bool_option(ctxt, GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1); +``` + +with: + +```c + gcc_jit_context_add_command_line_option(ctxt, "-fdump-tree-gimple"); +``` + +(although you can have both at the same time too). Then you can compile it like previously. Only one difference: before executing it, I recommend to run: + +```console +rm -rf /tmp/libgccjit-* +``` + +to make it easier for you to know which folder to look into. + +Once the execution is done, you should now have a file with path looking like `/tmp/libgccjit-9OFqkD/fake.c.006t.gimple` which contains the GIMPLE format. From cd1644a658825b1aa87f1b54fafb49159d72c992 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 9 Sep 2023 12:50:25 -0400 Subject: [PATCH 068/103] Fix const handling in ATT syntax --- src/asm.rs | 4 ---- tests/run/asm.rs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 4c3b7f5036c..b0e615d2de2 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -452,10 +452,6 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } InlineAsmOperandRef::Const { ref string } => { - // Const operands get injected directly into the template - if att_dialect { - template_str.push('$'); - } template_str.push_str(string); } } diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 38c1eac7adf..507b65ca049 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -124,7 +124,7 @@ fn main() { // check const (ATT syntax) let mut x: u64 = 42; unsafe { - asm!("add {}, {}", + asm!("add ${}, {}", const 1, inout(reg) x, options(att_syntax) From d7766ffa36d2f3a518181b16c1732fe2751e809d Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 13 Sep 2023 13:55:23 +0000 Subject: [PATCH 069/103] treat host effect params as erased generics in codegen This fixes the changes brought to codegen tests when effect params are added to libcore, by not attempting to monomorphize functions that get the host param by being `const fn`. --- src/callee.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/callee.rs b/src/callee.rs index a96bd66ba79..9fc77627b1b 100644 --- a/src/callee.rs +++ b/src/callee.rs @@ -100,7 +100,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) // whether we are sharing generics or not. The important thing here is // that the visibility we apply to the declaration is the same one that // has been applied to the definition (wherever that definition may be). - let is_generic = instance.args.non_erasable_generics().next().is_some(); + let is_generic = instance.args.non_erasable_generics(tcx, instance.def_id()).next().is_some(); if is_generic { // This is a monomorphization. Its expected visibility depends From 32df82648d0d8f7687a22f470c7e56fccb5b4b2f Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 14 Sep 2023 19:02:00 -0400 Subject: [PATCH 070/103] Handle static relocation model --- src/base.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/base.rs b/src/base.rs index 266d60da10c..ef3db24f708 100644 --- a/src/base.rs +++ b/src/base.rs @@ -140,6 +140,11 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< // NOTE: Rust relies on LLVM doing wrapping on overflow. context.add_command_line_option("-fwrapv"); + if tcx.sess.opts.cg.relocation_model == Some(rustc_target::spec::RelocModel::Static) { + context.add_command_line_option("-mcmodel=kernel"); + context.add_command_line_option("-fno-pie"); + } + if tcx.sess.opts.unstable_opts.function_sections.unwrap_or(tcx.sess.target.function_sections) { context.add_command_line_option("-ffunction-sections"); context.add_command_line_option("-fdata-sections"); From f6337e4966b43af7ee2779c3c778762426337273 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 9 Sep 2023 12:48:31 -0400 Subject: [PATCH 071/103] Don't always enabled CPU features --- src/base.rs | 11 ++--------- src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/base.rs b/src/base.rs index ef3db24f708..f4e7300b3fb 100644 --- a/src/base.rs +++ b/src/base.rs @@ -103,9 +103,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< .collect(); let add_cpu_feature_flag = |feature: &str| { - // FIXME(antoyo): some tests cause a segfault in GCC when not enabling all these - // features. - if (true || target_info.cpu_supports(feature)) && !disabled_features.contains(feature) { + if target_info.cpu_supports(feature) && !disabled_features.contains(feature) { context.add_command_line_option(&format!("-m{}", feature)); } }; @@ -113,7 +111,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< // TODO(antoyo): only set on x86 platforms. context.add_command_line_option("-masm=intel"); - let features = ["sse2", "avx", "avx2", "sha", "fma", "gfni", "f16c", "aes", "bmi2", "rtm", + let features = ["64", "bmi", "sse2", "avx", "avx2", "sha", "fma", "fma4", "gfni", "f16c", "aes", "bmi2", "pclmul", "rtm", "vaes", "vpclmulqdq", "xsavec", ]; @@ -121,11 +119,6 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< add_cpu_feature_flag(feature); } - // TODO(antoyo): only add the following cli arguments if the feature is supported. - context.add_command_line_option("-mpclmul"); - context.add_command_line_option("-mfma4"); - context.add_command_line_option("-m64"); - context.add_command_line_option("-mbmi"); //context.add_command_line_option("-mavxvnni"); // The CI doesn't support this option. for arg in &tcx.sess.opts.cg.llvm_args { diff --git a/src/lib.rs b/src/lib.rs index 2de8fb3fc70..b330f770597 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -313,7 +313,7 @@ pub fn __rustc_codegen_backend() -> Box { // Get the second TargetInfo with the correct CPU features by setting the arch. let context = Context::default(); - context.add_driver_option(&format!("-march={}", arch.to_str().unwrap())); + context.add_command_line_option(&format!("-march={}", arch.to_str().unwrap())); Arc::new(context.get_target_info()) }; #[cfg(not(feature="master"))] From adc0b210f31324af637517aa28d81772fdf28719 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 9 Sep 2023 12:48:49 -0400 Subject: [PATCH 072/103] Enable one more feature --- src/base.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/base.rs b/src/base.rs index f4e7300b3fb..ff3f7a6d175 100644 --- a/src/base.rs +++ b/src/base.rs @@ -111,7 +111,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< // TODO(antoyo): only set on x86 platforms. context.add_command_line_option("-masm=intel"); - let features = ["64", "bmi", "sse2", "avx", "avx2", "sha", "fma", "fma4", "gfni", "f16c", "aes", "bmi2", "pclmul", "rtm", + let features = ["64", "avxvnni", "bmi", "sse2", "avx", "avx2", "sha", "fma", "fma4", "gfni", "f16c", "aes", "bmi2", "pclmul", "rtm", "vaes", "vpclmulqdq", "xsavec", ]; @@ -119,8 +119,6 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< add_cpu_feature_flag(feature); } - //context.add_command_line_option("-mavxvnni"); // The CI doesn't support this option. - for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); } From 45c501cdf9e711c8d7c8d06250fdc2a84caf69bd Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 13 Sep 2023 18:56:06 -0400 Subject: [PATCH 073/103] Add note to readme --- Readme.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Readme.md b/Readme.md index daee6e8588d..1666cbc4f75 100644 --- a/Readme.md +++ b/Readme.md @@ -205,6 +205,19 @@ error: failed to build archive: failed to open object file: No such file or dire 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. From 5bb0d630ab1875e093df83714c30e11fd48ef383 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 13 Sep 2023 21:12:59 -0400 Subject: [PATCH 074/103] Do not always enable avx2 --- src/abi.rs | 1 + src/base.rs | 20 ++++++++-------- src/intrinsic/llvm.rs | 1 + src/lib.rs | 54 +++++++++++++++++++++++++++++++------------ 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 9f6e2f7ff10..813abaac793 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -3,6 +3,7 @@ use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::ty::Ty; +#[cfg(feature = "master")] use rustc_session::config; use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; diff --git a/src/base.rs b/src/base.rs index ff3f7a6d175..bb88c89fa53 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,6 +1,5 @@ use std::collections::HashSet; use std::env; -use std::sync::Arc; use std::time::Instant; use gccjit::{ @@ -8,8 +7,6 @@ use gccjit::{ FunctionType, GlobalKind, }; -#[cfg(feature="master")] -use gccjit::TargetInfo; use rustc_middle::dep_graph; use rustc_middle::ty::TyCtxt; #[cfg(feature="master")] @@ -22,8 +19,7 @@ use rustc_codegen_ssa::traits::DebugInfoMethods; use rustc_session::config::DebugInfo; use rustc_span::Symbol; -#[cfg(not(feature="master"))] -use crate::TargetInfo; +use crate::LockedTargetInfo; use crate::GccContext; use crate::builder::Builder; use crate::context::CodegenCx; @@ -70,7 +66,7 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { } } -pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc) -> (ModuleCodegen, u64) { +pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: LockedTargetInfo) -> (ModuleCodegen, u64) { let prof_timer = tcx.prof.generic_activity("codegen_module"); let start_time = Instant::now(); @@ -89,7 +85,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< // the time we needed for codegenning it. let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64; - fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, Arc)) -> ModuleCodegen { + fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, LockedTargetInfo)) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... let context = Context::default(); @@ -111,13 +107,19 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Arc< // TODO(antoyo): only set on x86 platforms. context.add_command_line_option("-masm=intel"); - let features = ["64", "avxvnni", "bmi", "sse2", "avx", "avx2", "sha", "fma", "fma4", "gfni", "f16c", "aes", "bmi2", "pclmul", "rtm", + // TODO: instead of setting the features manually, set the correct -march flag. + /*let features = ["64", "avxvnni", "bmi", "sse2", "avx2", "sha", "fma", "fma4", "gfni", "f16c", "aes", "bmi2", "pclmul", "rtm", "vaes", "vpclmulqdq", "xsavec", ]; for feature in &features { add_cpu_feature_flag(feature); - } + }*/ + + // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for + // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. + // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar. + context.add_command_line_option("-mavx"); for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index f28348380d7..cb070e8267a 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -236,6 +236,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc let arg2 = builder.context.new_cast(None, arg2, arg2_type); args = vec![new_args[0], arg2].into(); }, + // These builtins are sent one more argument than needed. "__builtin_prefetch" => { let mut new_args = args.to_vec(); new_args.pop(); diff --git a/src/lib.rs b/src/lib.rs index b330f770597..9dbe6aab8cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,6 +73,7 @@ mod type_of; use std::any::Any; use std::sync::Arc; +use std::sync::Mutex; #[cfg(not(feature="master"))] use std::sync::atomic::AtomicBool; #[cfg(not(feature="master"))] @@ -135,9 +136,24 @@ impl TargetInfo { } } +#[derive(Clone, Debug)] +pub struct LockedTargetInfo { + info: Arc>, +} + +impl LockedTargetInfo { + fn cpu_supports(&self, feature: &str) -> bool { + self.info.lock().expect("lock").cpu_supports(feature) + } + + fn supports_128bit_int(&self) -> bool { + self.info.lock().expect("lock").supports_128bit_int() + } +} + #[derive(Clone)] pub struct GccCodegenBackend { - target_info: Arc, + target_info: LockedTargetInfo, } impl CodegenBackend for GccCodegenBackend { @@ -146,6 +162,19 @@ impl CodegenBackend for GccCodegenBackend { } fn init(&self, sess: &Session) { + #[cfg(feature="master")] + { + let target_cpu = target_cpu(sess); + + // Get the second TargetInfo with the correct CPU features by setting the arch. + let context = Context::default(); + if target_cpu != "generic" { + context.add_command_line_option(&format!("-march={}", target_cpu)); + } + + *self.target_info.info.lock().expect("lock") = context.get_target_info(); + } + #[cfg(feature="master")] gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); if sess.lto() == Lto::Thin { @@ -161,7 +190,7 @@ impl CodegenBackend for GccCodegenBackend { let _int128_ty = check_context.new_c_type(CType::UInt128t); // NOTE: we cannot just call compile() as this would require other files than libgccjit.so. check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str")); - self.target_info.supports_128bit_integers.store(check_context.get_last_error() == Ok(None), Ordering::SeqCst); + self.target_info.info.lock().expect("lock").supports_128bit_integers.store(check_context.get_last_error() == Ok(None), Ordering::SeqCst); } } @@ -217,7 +246,7 @@ impl ExtraBackendMethods for GccCodegenBackend { } fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen, u64) { - base::compile_codegen_unit(tcx, cgu_name, Arc::clone(&self.target_info)) + base::compile_codegen_unit(tcx, cgu_name, self.target_info.clone()) } fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel, _features: &[String]) -> TargetMachineFactoryFn { @@ -306,23 +335,18 @@ impl WriteBackendMethods for GccCodegenBackend { #[no_mangle] pub fn __rustc_codegen_backend() -> Box { #[cfg(feature="master")] - let target_info = { - // Get the native arch and check whether the target supports 128-bit integers. + let info = { + // Check whether the target supports 128-bit integers. let context = Context::default(); - let arch = context.get_target_info().arch().unwrap(); - - // Get the second TargetInfo with the correct CPU features by setting the arch. - let context = Context::default(); - context.add_command_line_option(&format!("-march={}", arch.to_str().unwrap())); - Arc::new(context.get_target_info()) + Arc::new(Mutex::new(context.get_target_info())) }; #[cfg(not(feature="master"))] - let target_info = Arc::new(TargetInfo { + let info = Arc::new(Mutex::new(TargetInfo { supports_128bit_integers: AtomicBool::new(false), - }); + })); Box::new(GccCodegenBackend { - target_info, + target_info: LockedTargetInfo { info }, }) } @@ -356,7 +380,7 @@ pub fn target_cpu(sess: &Session) -> &str { } } -pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &Arc) -> Vec { +pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &LockedTargetInfo) -> Vec { supported_target_features(sess) .iter() .filter_map( From f692124c5d11bdf95a66552c769fbbb4d4b89208 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 14 Sep 2023 19:01:31 -0400 Subject: [PATCH 075/103] Handle disabled features --- src/base.rs | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/base.rs b/src/base.rs index bb88c89fa53..380be341704 100644 --- a/src/base.rs +++ b/src/base.rs @@ -104,22 +104,33 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock } }; + let disable_cpu_feature = |feature: &str| { + if disabled_features.contains(feature) { + context.add_command_line_option(&format!("-mno-{}", feature)); + } + }; + // TODO(antoyo): only set on x86 platforms. context.add_command_line_option("-masm=intel"); // TODO: instead of setting the features manually, set the correct -march flag. - /*let features = ["64", "avxvnni", "bmi", "sse2", "avx2", "sha", "fma", "fma4", "gfni", "f16c", "aes", "bmi2", "pclmul", "rtm", + let features = ["64", "avxvnni", "bmi", "sse2", "avx2", "sha", "fma", "fma4", "gfni", "f16c", "aes", "bmi2", "pclmul", "rtm", "vaes", "vpclmulqdq", "xsavec", ]; - for feature in &features { - add_cpu_feature_flag(feature); - }*/ - // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for - // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. - // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar. - context.add_command_line_option("-mavx"); + for feature in &features { + disable_cpu_feature(feature); + + //add_cpu_feature_flag(feature); + } + + if !disabled_features.contains("avx") { + // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for + // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. + // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar. + context.add_command_line_option("-mavx"); + } for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); From 20d4c3946281bfe8cf0fc5585438857113143c36 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 14 Sep 2023 19:55:01 -0400 Subject: [PATCH 076/103] Correctly handle target features --- messages.ftl | 16 ++++ src/attributes.rs | 86 ++++++--------------- src/errors.rs | 56 +++++++++++++- src/gcc_util.rs | 193 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 +- 5 files changed, 289 insertions(+), 67 deletions(-) create mode 100644 src/gcc_util.rs diff --git a/messages.ftl b/messages.ftl index de9be3a5528..5ca0a2e1b6d 100644 --- a/messages.ftl +++ b/messages.ftl @@ -1,3 +1,7 @@ +codegen_gcc_unknown_ctarget_feature_prefix = + unknown feature specified for `-Ctarget-feature`: `{$feature}` + .note = features must begin with a `+` to enable or `-` to disable it + codegen_gcc_invalid_minimum_alignment = invalid minimum global alignment: {$err} @@ -23,3 +27,15 @@ codegen_gcc_lto_disallowed = lto can only be run for executables, cdylibs and st codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto` codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err}) + +codegen_gcc_unknown_ctarget_feature = + unknown feature specified for `-Ctarget-feature`: `{$feature}` + .note = it is still passed through to the codegen backend + .possible_feature = you might have meant: `{$rust_feature}` + .consider_filing_feature_request = consider filing a feature request + +codegen_gcc_missing_features = + add the missing features in a `target_feature` attribute + +codegen_gcc_target_feature_disable_or_enable = + the target features {$features} must all be either enabled or disabled together diff --git a/src/attributes.rs b/src/attributes.rs index 35682db9c78..ced13848c0b 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -4,72 +4,13 @@ use gccjit::Function; use rustc_attr::InstructionSetAttr; #[cfg(feature="master")] use rustc_attr::InlineAttr; -use rustc_codegen_ssa::target_features::tied_target_features; -use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty; #[cfg(feature="master")] use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_session::Session; use rustc_span::symbol::sym; -use smallvec::{smallvec, SmallVec}; use crate::{context::CodegenCx, errors::TiedTargetFeatures}; - -// Given a map from target_features to whether they are enabled or disabled, -// ensure only valid combinations are allowed. -pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) -> Option<&'static [&'static str]> { - for tied in tied_target_features(sess) { - // Tied features must be set to the same value, or not set at all - let mut tied_iter = tied.iter(); - let enabled = features.get(tied_iter.next().unwrap()); - if tied_iter.any(|feature| enabled != features.get(feature)) { - return Some(tied); - } - } - None -} - -// TODO(antoyo): maybe move to a new module gcc_util. -// To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html -fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { - let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; - match (arch, s) { - ("x86", "sse4.2") => smallvec!["sse4.2", "crc32"], - ("x86", "pclmulqdq") => smallvec!["pclmul"], - ("x86", "rdrand") => smallvec!["rdrnd"], - ("x86", "bmi1") => smallvec!["bmi"], - ("x86", "cmpxchg16b") => smallvec!["cx16"], - ("x86", "avx512vaes") => smallvec!["vaes"], - ("x86", "avx512gfni") => smallvec!["gfni"], - ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"], - // NOTE: seems like GCC requires 'avx512bw' for 'avx512vbmi2'. - ("x86", "avx512vbmi2") => smallvec!["avx512vbmi2", "avx512bw"], - // NOTE: seems like GCC requires 'avx512bw' for 'avx512bitalg'. - ("x86", "avx512bitalg") => smallvec!["avx512bitalg", "avx512bw"], - ("aarch64", "rcpc2") => smallvec!["rcpc-immo"], - ("aarch64", "dpb") => smallvec!["ccpp"], - ("aarch64", "dpb2") => smallvec!["ccdp"], - ("aarch64", "frintts") => smallvec!["fptoint"], - ("aarch64", "fcma") => smallvec!["complxnum"], - ("aarch64", "pmuv3") => smallvec!["perfmon"], - ("aarch64", "paca") => smallvec!["pauth"], - ("aarch64", "pacg") => smallvec!["pauth"], - // Rust ties fp and neon together. In LLVM neon implicitly enables fp, - // but we manually enable neon when a feature only implicitly enables fp - ("aarch64", "f32mm") => smallvec!["f32mm", "neon"], - ("aarch64", "f64mm") => smallvec!["f64mm", "neon"], - ("aarch64", "fhm") => smallvec!["fp16fml", "neon"], - ("aarch64", "fp16") => smallvec!["fullfp16", "neon"], - ("aarch64", "jsconv") => smallvec!["jsconv", "neon"], - ("aarch64", "sve") => smallvec!["sve", "neon"], - ("aarch64", "sve2") => smallvec!["sve2", "neon"], - ("aarch64", "sve2-aes") => smallvec!["sve2-aes", "neon"], - ("aarch64", "sve2-sm4") => smallvec!["sve2-sm4", "neon"], - ("aarch64", "sve2-sha3") => smallvec!["sve2-sha3", "neon"], - ("aarch64", "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"], - (_, s) => smallvec![s], - } -} +use crate::gcc_util::{check_tied_features, to_gcc_features}; /// Get GCC attribute for the provided inline heuristic. #[cfg(feature="master")] @@ -153,12 +94,31 @@ pub fn from_fn_attrs<'gcc, 'tcx>( })) .collect::>(); - // TODO(antoyo): check if we really need global backend features. (Maybe they could be applied - // globally?) + // TODO(antoyo): cg_llvm add global features to each function so that LTO keep them. + // Check if GCC requires the same. let mut global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str()); function_features.extend(&mut global_features); - let target_features = function_features.join(","); + let target_features = function_features + .iter() + .filter_map(|feature| { + if feature.contains("soft-float") || feature.contains("retpoline-external-thunk") { + return None; + } + + if feature.starts_with('-') { + Some(format!("no{}", feature)) + } + else if feature.starts_with('+') { + Some(feature[1..].to_string()) + } + else { + Some(feature.to_string()) + } + }) + .collect::>() + .join(","); if !target_features.is_empty() { + println!("Function {:?}", function_features); #[cfg(feature="master")] func.add_attribute(FnAttribute::Target(&target_features)); } diff --git a/src/errors.rs b/src/errors.rs index 19a967cb489..4bf3b71f503 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,8 +1,36 @@ -use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; -use rustc_macros::Diagnostic; +use rustc_errors::{ + DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, IntoDiagnosticArg, +}; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; use std::borrow::Cow; +use crate::fluent_generated as fluent; + +#[derive(Diagnostic)] +#[diag(codegen_gcc_unknown_ctarget_feature_prefix)] +#[note] +pub(crate) struct UnknownCTargetFeaturePrefix<'a> { + pub feature: &'a str, +} + +#[derive(Diagnostic)] +#[diag(codegen_gcc_unknown_ctarget_feature)] +#[note] +pub(crate) struct UnknownCTargetFeature<'a> { + pub feature: &'a str, + #[subdiagnostic] + pub rust_feature: PossibleFeature<'a>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum PossibleFeature<'a> { + #[help(codegen_gcc_possible_feature)] + Some { rust_feature: &'a str }, + #[help(codegen_gcc_consider_filing_feature_request)] + None, +} + struct ExitCode(Option); impl IntoDiagnosticArg for ExitCode { @@ -71,3 +99,27 @@ pub(crate) struct LtoDylib; pub(crate) struct LtoBitcodeFromRlib { pub gcc_err: String, } + +pub(crate) struct TargetFeatureDisableOrEnable<'a> { + pub features: &'a [&'a str], + pub span: Option, + pub missing_features: Option, +} + +#[derive(Subdiagnostic)] +#[help(codegen_gcc_missing_features)] +pub(crate) struct MissingFeatures; + +impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); + if let Some(span) = self.span { + diag.set_span(span); + }; + if let Some(missing_features) = self.missing_features { + diag.subdiagnostic(missing_features); + } + diag.set_arg("features", self.features.join(", ")); + diag + } +} diff --git a/src/gcc_util.rs b/src/gcc_util.rs new file mode 100644 index 00000000000..da1c0dfe559 --- /dev/null +++ b/src/gcc_util.rs @@ -0,0 +1,193 @@ +use smallvec::{smallvec, SmallVec}; + +use rustc_codegen_ssa::target_features::{ + supported_target_features, tied_target_features, RUSTC_SPECIFIC_FEATURES, +}; +use rustc_data_structures::fx::FxHashMap; +use rustc_middle::bug; +use rustc_session::Session; + +use crate::errors::{PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, UnknownCTargetFeaturePrefix}; + +/// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, +/// `--target` and similar). +pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec { + // Features that come earlier are overridden by conflicting features later in the string. + // Typically we'll want more explicit settings to override the implicit ones, so: + // + // * Features from -Ctarget-cpu=*; are overridden by [^1] + // * Features implied by --target; are overridden by + // * Features from -Ctarget-feature; are overridden by + // * function specific features. + // + // [^1]: target-cpu=native is handled here, other target-cpu values are handled implicitly + // through GCC TargetMachine implementation. + // + // FIXME(nagisa): it isn't clear what's the best interaction between features implied by + // `-Ctarget-cpu` and `--target` are. On one hand, you'd expect CLI arguments to always + // override anything that's implicit, so e.g. when there's no `--target` flag, features implied + // the host target are overridden by `-Ctarget-cpu=*`. On the other hand, what about when both + // `--target` and `-Ctarget-cpu=*` are specified? Both then imply some target features and both + // flags are specified by the user on the CLI. It isn't as clear-cut which order of precedence + // should be taken in cases like these. + let mut features = vec![]; + + // TODO(antoyo): -Ctarget-cpu=native + + // Features implied by an implicit or explicit `--target`. + features.extend( + sess.target + .features + .split(',') + .filter(|v| !v.is_empty() && backend_feature_name(v).is_some()) + .map(String::from), + ); + + // -Ctarget-features + let supported_features = supported_target_features(sess); + let mut featsmap = FxHashMap::default(); + let feats = sess.opts.cg.target_feature + .split(',') + .filter_map(|s| { + let enable_disable = match s.chars().next() { + None => return None, + Some(c @ ('+' | '-')) => c, + Some(_) => { + if diagnostics { + sess.emit_warning(UnknownCTargetFeaturePrefix { feature: s }); + } + return None; + } + }; + + let feature = backend_feature_name(s)?; + // Warn against use of GCC specific feature names on the CLI. + if diagnostics && !supported_features.iter().any(|&(v, _)| v == feature) { + let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| { + let gcc_features = to_gcc_features(sess, rust_feature); + if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) { + Some(rust_feature) + } else { + None + } + }); + let unknown_feature = + if let Some(rust_feature) = rust_feature { + UnknownCTargetFeature { + feature, + rust_feature: PossibleFeature::Some { rust_feature }, + } + } + else { + UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } + }; + sess.emit_warning(unknown_feature); + } + + if diagnostics { + // FIXME(nagisa): figure out how to not allocate a full hashset here. + featsmap.insert(feature, enable_disable == '+'); + } + + // rustc-specific features do not get passed down to GCC… + if RUSTC_SPECIFIC_FEATURES.contains(&feature) { + return None; + } + // ... otherwise though we run through `to_gcc_features` when + // passing requests down to GCC. This means that all in-language + // features also work on the command line instead of having two + // different names when the GCC name and the Rust name differ. + Some(to_gcc_features(sess, feature) + .iter() + .flat_map(|feat| to_gcc_features(sess, feat).into_iter()) + .map(String::from) + .collect::>(), + ) + }) + .flatten(); + features.extend(feats); + + if diagnostics { + if let Some(f) = check_tied_features(sess, &featsmap) { + sess.emit_err(TargetFeatureDisableOrEnable { + features: f, + span: None, + missing_features: None, + }); + } + } + + features +} + +/// Returns a feature name for the given `+feature` or `-feature` string. +/// +/// Only allows features that are backend specific (i.e. not [`RUSTC_SPECIFIC_FEATURES`].) +fn backend_feature_name(s: &str) -> Option<&str> { + // features must start with a `+` or `-`. + let feature = s.strip_prefix(&['+', '-'][..]).unwrap_or_else(|| { + bug!("target feature `{}` must begin with a `+` or `-`", s); + }); + // Rustc-specific feature requests like `+crt-static` or `-crt-static` + // are not passed down to GCC. + if RUSTC_SPECIFIC_FEATURES.contains(&feature) { + return None; + } + Some(feature) +} + +// TODO(antoyo): maybe move to a new module gcc_util. +// To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { + let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; + match (arch, s) { + ("x86", "sse4.2") => smallvec!["sse4.2", "crc32"], + ("x86", "pclmulqdq") => smallvec!["pclmul"], + ("x86", "rdrand") => smallvec!["rdrnd"], + ("x86", "bmi1") => smallvec!["bmi"], + ("x86", "cmpxchg16b") => smallvec!["cx16"], + ("x86", "avx512vaes") => smallvec!["vaes"], + ("x86", "avx512gfni") => smallvec!["gfni"], + ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"], + // NOTE: seems like GCC requires 'avx512bw' for 'avx512vbmi2'. + ("x86", "avx512vbmi2") => smallvec!["avx512vbmi2", "avx512bw"], + // NOTE: seems like GCC requires 'avx512bw' for 'avx512bitalg'. + ("x86", "avx512bitalg") => smallvec!["avx512bitalg", "avx512bw"], + ("aarch64", "rcpc2") => smallvec!["rcpc-immo"], + ("aarch64", "dpb") => smallvec!["ccpp"], + ("aarch64", "dpb2") => smallvec!["ccdp"], + ("aarch64", "frintts") => smallvec!["fptoint"], + ("aarch64", "fcma") => smallvec!["complxnum"], + ("aarch64", "pmuv3") => smallvec!["perfmon"], + ("aarch64", "paca") => smallvec!["pauth"], + ("aarch64", "pacg") => smallvec!["pauth"], + // Rust ties fp and neon together. In GCC neon implicitly enables fp, + // but we manually enable neon when a feature only implicitly enables fp + ("aarch64", "f32mm") => smallvec!["f32mm", "neon"], + ("aarch64", "f64mm") => smallvec!["f64mm", "neon"], + ("aarch64", "fhm") => smallvec!["fp16fml", "neon"], + ("aarch64", "fp16") => smallvec!["fullfp16", "neon"], + ("aarch64", "jsconv") => smallvec!["jsconv", "neon"], + ("aarch64", "sve") => smallvec!["sve", "neon"], + ("aarch64", "sve2") => smallvec!["sve2", "neon"], + ("aarch64", "sve2-aes") => smallvec!["sve2-aes", "neon"], + ("aarch64", "sve2-sm4") => smallvec!["sve2-sm4", "neon"], + ("aarch64", "sve2-sha3") => smallvec!["sve2-sha3", "neon"], + ("aarch64", "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"], + (_, s) => smallvec![s], + } +} + +// Given a map from target_features to whether they are enabled or disabled, +// ensure only valid combinations are allowed. +pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) -> Option<&'static [&'static str]> { + for tied in tied_target_features(sess) { + // Tied features must be set to the same value, or not set at all + let mut tied_iter = tied.iter(); + let enabled = features.get(tied_iter.next().unwrap()); + if tied_iter.any(|feature| enabled != features.get(feature)) { + return Some(tied); + } + } + None +} diff --git a/src/lib.rs b/src/lib.rs index 9dbe6aab8cb..eedac315c60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,6 +65,7 @@ mod coverageinfo; mod debuginfo; mod declare; mod errors; +mod gcc_util; mod int; mod intrinsic; mod mono_item; @@ -195,8 +196,8 @@ impl CodegenBackend for GccCodegenBackend { } fn provide(&self, providers: &mut Providers) { - // FIXME(antoyo) compute list of enabled features from cli flags - providers.global_backend_features = |_tcx, ()| vec![]; + providers.global_backend_features = + |tcx, ()| gcc_util::global_gcc_features(tcx.sess, true) } fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool) -> Box { From 87daba2cadb642fa1d1e683f04652805e8f7499a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 14 Sep 2023 20:35:11 -0400 Subject: [PATCH 077/103] Only add feature flags on functions --- src/attributes.rs | 9 ++++++--- src/base.rs | 24 +----------------------- src/gcc_util.rs | 9 ++++++++- 3 files changed, 15 insertions(+), 27 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index ced13848c0b..971e019a4f6 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -94,14 +94,18 @@ pub fn from_fn_attrs<'gcc, 'tcx>( })) .collect::>(); - // TODO(antoyo): cg_llvm add global features to each function so that LTO keep them. + // TODO(antoyo): cg_llvm adds global features to each function so that LTO keep them. // Check if GCC requires the same. let mut global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str()); function_features.extend(&mut global_features); let target_features = function_features .iter() .filter_map(|feature| { - if feature.contains("soft-float") || feature.contains("retpoline-external-thunk") { + // FIXME(antoyo): for some reasons, disabling SSE results in the following error when + // compiling Rust for Linux: + // SSE register return with SSE disabled + // TODO(antoyo): support soft-float and retpoline-external-thunk. + if feature.contains("soft-float") || feature.contains("retpoline-external-thunk") || *feature == "-sse" { return None; } @@ -118,7 +122,6 @@ pub fn from_fn_attrs<'gcc, 'tcx>( .collect::>() .join(","); if !target_features.is_empty() { - println!("Function {:?}", function_features); #[cfg(feature="master")] func.add_attribute(FnAttribute::Target(&target_features)); } diff --git a/src/base.rs b/src/base.rs index 380be341704..91efcf18bf4 100644 --- a/src/base.rs +++ b/src/base.rs @@ -98,32 +98,10 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock .map(|string| &string[1..]) .collect(); - let add_cpu_feature_flag = |feature: &str| { - if target_info.cpu_supports(feature) && !disabled_features.contains(feature) { - context.add_command_line_option(&format!("-m{}", feature)); - } - }; - - let disable_cpu_feature = |feature: &str| { - if disabled_features.contains(feature) { - context.add_command_line_option(&format!("-mno-{}", feature)); - } - }; - // TODO(antoyo): only set on x86 platforms. context.add_command_line_option("-masm=intel"); - // TODO: instead of setting the features manually, set the correct -march flag. - let features = ["64", "avxvnni", "bmi", "sse2", "avx2", "sha", "fma", "fma4", "gfni", "f16c", "aes", "bmi2", "pclmul", "rtm", - "vaes", "vpclmulqdq", "xsavec", - ]; - - - for feature in &features { - disable_cpu_feature(feature); - - //add_cpu_feature_flag(feature); - } + // TODO(antoyo): set the correct -march flag. if !disabled_features.contains("avx") { // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for diff --git a/src/gcc_util.rs b/src/gcc_util.rs index da1c0dfe559..09a0af5d00d 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -100,7 +100,14 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec>(), ) }) From a9a2c687ff7ee755d92375d57b5c88a42f6acb66 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 14 Sep 2023 20:42:14 -0400 Subject: [PATCH 078/103] Send -march to gcc --- src/base.rs | 9 ++++++--- src/gcc_util.rs | 15 +++++++++++++++ src/lib.rs | 16 +--------------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/base.rs b/src/base.rs index 91efcf18bf4..61da38f4b0d 100644 --- a/src/base.rs +++ b/src/base.rs @@ -19,7 +19,7 @@ use rustc_codegen_ssa::traits::DebugInfoMethods; use rustc_session::config::DebugInfo; use rustc_span::Symbol; -use crate::LockedTargetInfo; +use crate::{LockedTargetInfo, gcc_util}; use crate::GccContext; use crate::builder::Builder; use crate::context::CodegenCx; @@ -101,8 +101,6 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock // TODO(antoyo): only set on x86 platforms. context.add_command_line_option("-masm=intel"); - // TODO(antoyo): set the correct -march flag. - if !disabled_features.contains("avx") { // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. @@ -127,6 +125,11 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock context.add_command_line_option("-fno-pie"); } + let target_cpu = gcc_util::target_cpu(tcx.sess); + if target_cpu != "generic" { + context.add_command_line_option(&format!("-march={}", target_cpu)); + } + if tcx.sess.opts.unstable_opts.function_sections.unwrap_or(tcx.sess.target.function_sections) { context.add_command_line_option("-ffunction-sections"); context.add_command_line_option("-fdata-sections"); diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 09a0af5d00d..91a815c0771 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -198,3 +198,18 @@ pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) -> } None } + +fn handle_native(name: &str) -> &str { + if name != "native" { + return name; + } + + unimplemented!(); +} + +pub fn target_cpu(sess: &Session) -> &str { + match sess.opts.cg.target_cpu { + Some(ref name) => handle_native(name), + None => handle_native(sess.target.cpu.as_ref()), + } +} diff --git a/src/lib.rs b/src/lib.rs index eedac315c60..df33e6cbd61 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -107,6 +107,7 @@ use rustc_span::fatal_error::FatalError; use tempfile::TempDir; use crate::back::lto::ModuleBuffer; +use crate::gcc_util::target_cpu; fluent_messages! { "../messages.ftl" } @@ -366,21 +367,6 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { } } -fn handle_native(name: &str) -> &str { - if name != "native" { - return name; - } - - unimplemented!(); -} - -pub fn target_cpu(sess: &Session) -> &str { - match sess.opts.cg.target_cpu { - Some(ref name) => handle_native(name), - None => handle_native(sess.target.cpu.as_ref()), - } -} - pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &LockedTargetInfo) -> Vec { supported_target_features(sess) .iter() From f096c19db502957ecc571654cc5c821368a42eec Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 14 Sep 2023 20:47:14 -0400 Subject: [PATCH 079/103] Handle target-cpu=native --- src/gcc_util.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 91a815c0771..fc992ec6d2a 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -1,3 +1,4 @@ +use gccjit::Context; use smallvec::{smallvec, SmallVec}; use rustc_codegen_ssa::target_features::{ @@ -204,7 +205,11 @@ fn handle_native(name: &str) -> &str { return name; } - unimplemented!(); + // Get the native arch. + let context = Context::default(); + context.get_target_info().arch().unwrap() + .to_str() + .unwrap() } pub fn target_cpu(sess: &Session) -> &str { From f3b82df8f8f59238bf9ba9aafa4896e8a72c888e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 14 Sep 2023 21:49:14 -0400 Subject: [PATCH 080/103] Add note to readme --- Readme.md | 2 ++ src/gcc_util.rs | 5 +---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index 1666cbc4f75..060f7c0326d 100644 --- a/Readme.md +++ b/Readme.md @@ -111,6 +111,8 @@ $ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) rustc +$(cat $CG_ 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`.
## Licensing diff --git a/src/gcc_util.rs b/src/gcc_util.rs index fc992ec6d2a..18343d58c35 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -22,7 +22,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Vec Option<&str> { Some(feature) } -// TODO(antoyo): maybe move to a new module gcc_util. // To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; From 22e13b4c55b65e0f73483cb3a61a091feef64d47 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 8 Sep 2023 08:48:41 +0200 Subject: [PATCH 081/103] clarify PassMode::Indirect as well --- src/abi.rs | 6 +++--- src/intrinsic/mod.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 377dc753f68..9c93a1b52fa 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -129,7 +129,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 1)); continue; } - PassMode::Indirect { extra_attrs: Some(_), .. } => { + PassMode::Indirect { meta_attrs: Some(_), .. } => { unimplemented!(); } PassMode::Cast(ref cast, pad_i32) => { @@ -139,11 +139,11 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } cast.gcc_type(cx) } - PassMode::Indirect { extra_attrs: None, on_stack: true, .. } => { + PassMode::Indirect { meta_attrs: None, on_stack: true, .. } => { on_stack_param_indices.insert(argument_tys.len()); arg.memory_ty(cx) }, - PassMode::Indirect { extra_attrs: None, on_stack: false, .. } => cx.type_ptr_to(arg.memory_ty(cx)), + PassMode::Indirect { meta_attrs: None, on_stack: false, .. } => cx.type_ptr_to(arg.memory_ty(cx)), }; argument_tys.push(arg_ty); } diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index f8c32c6dbbb..b59a17b5cad 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -511,10 +511,10 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { PassMode::Pair(..) => { OperandValue::Pair(next(), next()).store(bx, dst); }, - PassMode::Indirect { extra_attrs: Some(_), .. } => { + PassMode::Indirect { meta_attrs: Some(_), .. } => { OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst); }, - PassMode::Direct(_) | PassMode::Indirect { extra_attrs: None, .. } | PassMode::Cast(..) => { + PassMode::Direct(_) | PassMode::Indirect { meta_attrs: None, .. } | PassMode::Cast(..) => { let next_arg = next(); self.store(bx, next_arg, dst); }, From cd519aabd71e1c7b43eab0d69bcc075cfe7d054f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Sep 2023 09:23:56 +0200 Subject: [PATCH 082/103] fix gcc, cranelift build --- src/abi.rs | 4 ++-- src/intrinsic/mod.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 9c93a1b52fa..a49530ebb4c 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -113,7 +113,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { match self.ret.mode { PassMode::Ignore => cx.type_void(), PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx), - PassMode::Cast(ref cast, _) => cast.gcc_type(cx), + PassMode::Cast { ref cast, .. } => cast.gcc_type(cx), PassMode::Indirect { .. } => { argument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx))); cx.type_void() @@ -132,7 +132,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { PassMode::Indirect { meta_attrs: Some(_), .. } => { unimplemented!(); } - PassMode::Cast(ref cast, pad_i32) => { + PassMode::Cast { ref cast, pad_i32 } => { // add padding if pad_i32 { argument_tys.push(Reg::i32().gcc_type(cx)); diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index b59a17b5cad..68a087a1d7f 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -144,7 +144,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { sym::volatile_load | sym::unaligned_volatile_load => { let tp_ty = fn_args.type_at(0); let mut ptr = args[0].immediate(); - if let PassMode::Cast(ty, _) = &fn_abi.ret.mode { + if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode { ptr = self.pointercast(ptr, self.type_ptr_to(ty.gcc_type(self))); } let load = self.volatile_load(ptr.get_type(), ptr); @@ -353,7 +353,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { }; if !fn_abi.ret.is_ignore() { - if let PassMode::Cast(ty, _) = &fn_abi.ret.mode { + if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode { let ptr_llty = self.type_ptr_to(ty.gcc_type(self)); let ptr = self.pointercast(result.llval, ptr_llty); self.store(llval, ptr, result.align); @@ -449,7 +449,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { else if self.is_unsized_indirect() { bug!("unsized `ArgAbi` must be handled through `store_fn_arg`"); } - else if let PassMode::Cast(ref cast, _) = self.mode { + else if let PassMode::Cast { ref cast, .. } = self.mode { // FIXME(eddyb): Figure out when the simpler Store is safe, clang // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}. let can_store_through_cast_ptr = false; @@ -514,7 +514,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { PassMode::Indirect { meta_attrs: Some(_), .. } => { OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst); }, - PassMode::Direct(_) | PassMode::Indirect { meta_attrs: None, .. } | PassMode::Cast(..) => { + PassMode::Direct(_) | PassMode::Indirect { meta_attrs: None, .. } | PassMode::Cast { .. } => { let next_arg = next(); self.store(bx, next_arg, dst); }, From 5ab4e2b484ea9b3ffd861c2ed9c358c405576bbd Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 18 Sep 2023 18:24:09 -0400 Subject: [PATCH 083/103] Implement llvm.x86.rdrand.64 --- src/intrinsic/llvm.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index cb070e8267a..5996623bdc5 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -242,6 +242,11 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc new_args.pop(); args = new_args.into(); }, + // The GCC version returns one value of the tuple through a pointer. + "__builtin_ia32_rdrand64_step" => { + let arg = builder.current_func().new_local(None, builder.ulonglong_type, "return_rdrand_arg"); + args = vec![arg.get_address(None)].into(); + }, _ => (), } } @@ -362,6 +367,19 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc, // builtin twice, we overwrite the return value with a dummy value. return_value = builder.context.new_rvalue_zero(builder.int_type); }, + "__builtin_ia32_rdrand64_step" => { + let random_number = args[0].dereference(None).to_rvalue(); + let success_variable = builder.current_func().new_local(None, return_value.get_type(), "success"); + builder.llbb().add_assignment(None, success_variable, return_value); + + let field1 = builder.context.new_field(None, random_number.get_type(), "random_number"); + let field2 = builder.context.new_field(None, return_value.get_type(), "success"); + let struct_type = builder.context.new_struct_type(None, "rdrand_result", &[field1, field2]); + return_value = builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[ + random_number, + success_variable.to_rvalue(), + ]); + }, _ => (), } @@ -614,6 +632,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.fshr.v8i16" => "__builtin_ia32_vpshrdv_v8hi", "llvm.x86.fma.vfmadd.sd" => "__builtin_ia32_vfmaddsd3", "llvm.x86.fma.vfmadd.ss" => "__builtin_ia32_vfmaddss3", + "llvm.x86.rdrand.64" => "__builtin_ia32_rdrand64_step", // The above doc points to unknown builtins for the following, so override them: "llvm.x86.avx2.gather.d.d" => "__builtin_ia32_gathersiv4si", From be3b1e33215bec2d47bcb0455c9b27d412b9328a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 19 Sep 2023 22:20:35 -0400 Subject: [PATCH 084/103] Fix gep on pointers to non-number --- Cargo.lock | 4 ++-- failing-ui-tests.txt | 1 - failing-ui-tests12.txt | 1 + src/builder.rs | 6 ++++++ src/gcc_util.rs | 16 +++++++++++----- test.sh | 1 + tests/run/gep.rs | 10 ++++++++++ 7 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 tests/run/gep.rs diff --git a/Cargo.lock b/Cargo.lock index 404fb9c6db1..85675fc40c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,7 +74,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#ff1f82584c760a8b870dc6bad9841bd090f92f80" +source = "git+https://github.com/antoyo/gccjit.rs#0b158c68bf7e46732869d90550a98e886dee8858" dependencies = [ "gccjit_sys", ] @@ -82,7 +82,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#ff1f82584c760a8b870dc6bad9841bd090f92f80" +source = "git+https://github.com/antoyo/gccjit.rs#0b158c68bf7e46732869d90550a98e886dee8858" dependencies = [ "libc", ] diff --git a/failing-ui-tests.txt b/failing-ui-tests.txt index 0711ae99a3e..8ec151f7838 100644 --- a/failing-ui-tests.txt +++ b/failing-ui-tests.txt @@ -14,7 +14,6 @@ tests/ui/sepcomp/sepcomp-fns-backwards.rs tests/ui/sepcomp/sepcomp-fns.rs tests/ui/sepcomp/sepcomp-statics.rs tests/ui/simd/intrinsic/generic-arithmetic-pass.rs -tests/ui/target-feature/missing-plusminus.rs tests/ui/asm/x86_64/may_unwind.rs tests/ui/backtrace.rs tests/ui/catch-unwind-bang.rs diff --git a/failing-ui-tests12.txt b/failing-ui-tests12.txt index 8c27bd8b8ca..0ac0a034af4 100644 --- a/failing-ui-tests12.txt +++ b/failing-ui-tests12.txt @@ -37,3 +37,4 @@ tests/ui/simd/intrinsic/generic-gather-pass.rs tests/ui/simd/issue-85915-simd-ptrs.rs tests/ui/issues/issue-68010-large-zst-consts.rs tests/ui/rust-2018/proc-macro-crate-in-paths.rs +tests/ui/target-feature/missing-plusminus.rs diff --git a/src/builder.rs b/src/builder.rs index b0feb99e3c6..04100f2ad2e 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -922,6 +922,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // require dereferencing the pointer. for index in indices { pointee_type = pointee_type.get_pointee().expect("pointee type"); + #[cfg(feature="master")] + let pointee_size = { + let size = self.cx.context.new_sizeof(pointee_type); + self.context.new_cast(None, size, index.get_type()) + }; + #[cfg(not(feature="master"))] let pointee_size = self.context.new_rvalue_from_int(index.get_type(), pointee_type.get_size() as i32); result = result + self.gcc_int_cast(*index * pointee_size, self.sizet_type); } diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 18343d58c35..0514c9988e0 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -1,3 +1,4 @@ +#[cfg(feature="master")] use gccjit::Context; use smallvec::{smallvec, SmallVec}; @@ -202,11 +203,16 @@ fn handle_native(name: &str) -> &str { return name; } - // Get the native arch. - let context = Context::default(); - context.get_target_info().arch().unwrap() - .to_str() - .unwrap() + #[cfg(feature="master")] + { + // Get the native arch. + let context = Context::default(); + context.get_target_info().arch().unwrap() + .to_str() + .unwrap() + } + #[cfg(not(feature="master"))] + unimplemented!(); } pub fn target_cpu(sess: &Session) -> &str { diff --git a/test.sh b/test.sh index c47cf140ae4..5b7ef7ab101 100755 --- a/test.sh +++ b/test.sh @@ -220,6 +220,7 @@ changelog-seen = 2 [rust] codegen-backends = [] deny-warnings = false +verbose-tests = true [build] cargo = "$(rustup which cargo)" diff --git a/tests/run/gep.rs b/tests/run/gep.rs new file mode 100644 index 00000000000..c3d1672cff5 --- /dev/null +++ b/tests/run/gep.rs @@ -0,0 +1,10 @@ +// Compiler: +// +// Run-time: +// status: 0 + +fn main() { + let mut value = (1, 1); + let ptr = &mut value as *mut (i32, i32); + println!("{:?}", ptr.wrapping_offset(10)); +} From 38b9e26a75e6fba2ca5f0e217f267fc0651b23f8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 22 Sep 2023 09:14:39 +0000 Subject: [PATCH 085/103] Add a way to decouple the implementation and the declaration of a TyCtxt method. --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 697ae015fed..1567fea3e1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,6 +82,7 @@ use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; +use rustc_middle::hooks; use rustc_session::config::{Lto, OptLevel, OutputFilenames}; use rustc_session::Session; use rustc_span::Symbol; @@ -127,7 +128,7 @@ impl CodegenBackend for GccCodegenBackend { *self.supports_128bit_integers.lock().expect("lock") = check_context.get_last_error() == Ok(None); } - fn provide(&self, providers: &mut Providers) { + fn provide(&self, providers: &mut Providers, _: &mut hooks::Providers) { // FIXME(antoyo) compute list of enabled features from cli flags providers.global_backend_features = |_tcx, ()| vec![]; } From a7d8b8eb9f6012dd726ec904f45e00b806619a78 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 22 Sep 2023 16:39:11 +0200 Subject: [PATCH 086/103] Add guide to add new attributes support in libgccjit --- doc/add-attribute.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 doc/add-attribute.md diff --git a/doc/add-attribute.md b/doc/add-attribute.md new file mode 100644 index 00000000000..ae3bcc5e2eb --- /dev/null +++ b/doc/add-attribute.md @@ -0,0 +1,17 @@ +# Add support for a new function attribute + +To add support for a new function attribute in libgccjit, you need to do the following steps: + + 1. Copy the corresponding function from `c-family/c-attribs.cc` into `jit/dummy-frontend.cc`. For example if you add the `target` attribute, the function name will be `handle_target_attribute`. + 2. Copy the corresponding entry from the `c_common_attribute_table` variable in the `c-family/c-attribs.cc` file into the `jit_attribute_table` variable in `jit/dummy-frontend.cc`. + 3. Add a new variant in the `gcc_jit_fn_attribute` enum in the `jit/libgccjit.h` file. + 4. Add a test to ensure the attribute is correctly applied in `gcc/testsuite/jit.dg/`. Take a look at `gcc/testsuite/jit.dg/test-nonnull.c` if you want an example. + 5. Run the example like this (in your `gcc-build` folder): `make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-nonnull.c"` + +Once done, you need to update the [gccjit.rs] crate to add the new enum variant in the corresponding enum (`FnAttribute`). + +Finally, you need to update this repository by calling the relevant API you added in [gccjit.rs]. + +To test it, build `gcc`, run `cargo update -p gccjit` and then you can test the generated output for a given Rust crate. + +[gccjit.rs]: https://github.com/antoyo/gccjit.rs From 8373b055146c00978201e8a7dc299bd1a9c3ec3f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 22 Sep 2023 16:26:20 +0000 Subject: [PATCH 087/103] Have a single struct for queries and hook --- src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1567fea3e1c..ce7e31682f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,9 +80,8 @@ use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMes use rustc_fluent_macro::fluent_messages; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::query::Providers; +use rustc_middle::util::Providers; use rustc_middle::ty::TyCtxt; -use rustc_middle::hooks; use rustc_session::config::{Lto, OptLevel, OutputFilenames}; use rustc_session::Session; use rustc_span::Symbol; @@ -128,7 +127,7 @@ impl CodegenBackend for GccCodegenBackend { *self.supports_128bit_integers.lock().expect("lock") = check_context.get_last_error() == Ok(None); } - fn provide(&self, providers: &mut Providers, _: &mut hooks::Providers) { + fn provide(&self, providers: &mut Providers) { // FIXME(antoyo) compute list of enabled features from cli flags providers.global_backend_features = |_tcx, ()| vec![]; } From ccf57997826581da83eff3a29cadc1c9fb728875 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Sep 2023 17:04:44 +0200 Subject: [PATCH 088/103] Use cargo to build the build system binary --- y.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/y.sh b/y.sh index 481b909c92a..188109743e3 100755 --- a/y.sh +++ b/y.sh @@ -2,6 +2,7 @@ set -e echo "[BUILD] build system" 1>&2 -mkdir -p build_system/target -rustc build_system/src/main.rs -o build_system/target/y -Cdebuginfo=1 --edition 2021 -exec ./build_system/target/y "$@" +cd build_system +cargo build --release +cd .. +./build_system/target/release/y $@ From 6be1f3674460cb0c91341dc07e1c31699bd0980e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Sep 2023 17:12:40 +0200 Subject: [PATCH 089/103] Add help message --- build_system/src/main.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/build_system/src/main.rs b/build_system/src/main.rs index c76418da579..16c4c3a9c62 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -9,13 +9,19 @@ mod utils; macro_rules! arg_error { ($($err:tt)*) => {{ eprintln!($($err)*); + eprintln!(); usage(); std::process::exit(1); }}; } fn usage() { - // println!("{}", include_str!("usage.txt")); + println!("\ +Available commands for build_system: + + prepare : Run prepare command + build : Run build command + --help : Show this message"); } pub enum Command { @@ -31,6 +37,10 @@ fn main() { let command = match env::args().nth(1).as_deref() { Some("prepare") => Command::Prepare, Some("build") => Command::Build, + Some("--help") => { + usage(); + process::exit(0); + } Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), Some(command) => arg_error!("Unknown command {}", command), None => { From b1862af177dcfa0afe1a04df40c93e9d6ca18ad7 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 1 Oct 2023 16:54:52 +0300 Subject: [PATCH 090/103] implement major change tracking for the bootstrap configuration Signed-off-by: onur-ozkan --- test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.sh b/test.sh index 592997b8ab9..b462e5d156b 100755 --- a/test.sh +++ b/test.sh @@ -214,7 +214,7 @@ function setup_rustc() { rm config.toml || true cat > config.toml < Date: Thu, 10 Mar 2022 17:10:36 -0500 Subject: [PATCH 091/103] Reapply: Mark drop calls in landing pads cold instead of noinline Co-authored-by: Max Fan Co-authored-by: Nikita Popov --- src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index 308cb04cac3..ecc293aee23 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1420,7 +1420,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.cx } - fn do_not_inline(&mut self, _llret: RValue<'gcc>) { + fn apply_attrs_to_cleanup_callsite(&mut self, _llret: RValue<'gcc>) { // FIXME(bjorn3): implement } From eedf1b6cb458c6a474bf2e9ccc29cbe9059f7764 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 26 Sep 2023 16:09:51 +0200 Subject: [PATCH 092/103] Migrate build.sh script to rust --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/stdarch.yml | 2 +- Readme.md | 2 +- build.sh | 67 ---------- build_sysroot/build_sysroot.sh | 4 +- build_system/src/build.rs | 217 ++++++++++++++++++++++++++++++++- build_system/src/config.rs | 121 ++++++++++++++++++ build_system/src/main.rs | 7 +- build_system/src/prepare.rs | 137 ++++++++++++++------- build_system/src/utils.rs | 113 ++++++++++++++--- config.sh | 2 +- 12 files changed, 542 insertions(+), 134 deletions(-) delete mode 100755 build.sh create mode 100644 build_system/src/config.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4702494f05c..f075c744e45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,7 +119,7 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - ${{ matrix.libgccjit_version.env_extra }} ./build.sh ${{ matrix.libgccjit_version.extra }} + ${{ matrix.libgccjit_version.env_extra }} ./y.sh build ${{ matrix.libgccjit_version.extra }} ${{ matrix.libgccjit_version.env_extra }} cargo test ${{ matrix.libgccjit_version.extra }} ./clean_all.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 51fc5c76cdb..bd0415040e7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -86,7 +86,7 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - EMBED_LTO_BITCODE=1 ./build.sh --release --release-sysroot + EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot cargo test ./clean_all.sh diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index c44d8efe3c7..6c28326823c 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -100,7 +100,7 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - ./build.sh --release --release-sysroot + ./y.sh build --release --release-sysroot cargo test - name: Clean diff --git a/Readme.md b/Readme.md index 060f7c0326d..de6cab120a4 100644 --- a/Readme.md +++ b/Readme.md @@ -66,7 +66,7 @@ Then you can run commands like this: ```bash $ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking -$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./build.sh --release +$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./y.sh build --release ``` To run the tests: diff --git a/build.sh b/build.sh deleted file mode 100755 index ba0d0d04948..00000000000 --- a/build.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env bash - -#set -x -set -e - -codegen_channel=debug -sysroot_channel=debug - -flags= - -while [[ $# -gt 0 ]]; do - case $1 in - --release) - codegen_channel=release - shift - ;; - --release-sysroot) - sysroot_channel=release - shift - ;; - --no-default-features) - flags="$flags --no-default-features" - shift - ;; - --features) - shift - flags="$flags --features $1" - shift - ;; - *) - echo "Unknown option $1" - exit 1 - ;; - esac -done - -if [ -f ./gcc_path ]; then - export GCC_PATH=$(cat gcc_path) -else - echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details' - exit 1 -fi - -export LD_LIBRARY_PATH="$GCC_PATH" -export LIBRARY_PATH="$GCC_PATH" - -if [[ "$codegen_channel" == "release" ]]; then - export CHANNEL='release' - CARGO_INCREMENTAL=1 cargo rustc --release $flags -else - echo $LD_LIBRARY_PATH - export CHANNEL='debug' - cargo rustc $flags -fi - -source config.sh - -rm -r target/out || true -mkdir -p target/out/gccjit - -echo "[BUILD] sysroot" -if [[ "$sysroot_channel" == "release" ]]; then - time ./build_sysroot/build_sysroot.sh --release -else - time ./build_sysroot/build_sysroot.sh -fi - diff --git a/build_sysroot/build_sysroot.sh b/build_sysroot/build_sysroot.sh index 9d692d599f6..851e9895ce2 100755 --- a/build_sysroot/build_sysroot.sh +++ b/build_sysroot/build_sysroot.sh @@ -5,9 +5,9 @@ set -e cd $(dirname "$0") -pushd ../ >/dev/null +pushd ../ source ./config.sh -popd >/dev/null +popd # Cleanup for previous run # v Clean target dir except for build scripts and incremental cache diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 7384557d805..58c36412ea5 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -1,3 +1,218 @@ -pub fn run() -> Result<(), String> { +use crate::config::set_config; +use crate::utils::{get_gcc_path, run_command_with_env, run_command_with_output, walk_dir}; +use std::collections::HashMap; +use std::ffi::OsStr; +use std::fs; +use std::path::Path; + +#[derive(Default)] +struct BuildArg { + codegen_release_channel: bool, + sysroot_release_channel: bool, + no_default_features: bool, + features: Vec, + gcc_path: String, +} + +impl BuildArg { + fn new() -> Result, String> { + let gcc_path = get_gcc_path()?; + let mut build_arg = Self { + gcc_path, + ..Default::default() + }; + let mut args = std::env::args().skip(2); + + while let Some(arg) = args.next() { + match arg.as_str() { + "--release" => build_arg.codegen_release_channel = true, + "--release-sysroot" => build_arg.sysroot_release_channel = true, + "--no-default-features" => build_arg.no_default_features = true, + "--features" => { + if let Some(arg) = args.next() { + build_arg.features.push(arg.as_str().into()); + } else { + return Err(format!( + "Expected a value after `--features`, found nothing" + )); + } + } + "--help" => { + Self::usage(); + return Ok(None); + } + a => return Err(format!("Unknown argument `{a}`")), + } + } + Ok(Some(build_arg)) + } + + fn usage() { + println!( + r#" +`build` command help: + + --release : Build codegen in release mode + --release-sysroot : Build sysroot in release mode + --no-default-features : Add `--no-default-features` flag + --features [arg] : Add a new feature [arg] + --help : Show this help +"# + ) + } +} + +fn build_sysroot( + env: &mut HashMap, + release_mode: bool, + target_triple: &str, +) -> Result<(), String> { + std::env::set_current_dir("build_sysroot") + .map_err(|e| format!("Failed to go to `build_sysroot` directory: {e:?}"))?; + // Cleanup for previous run + // v Clean target dir except for build scripts and incremental cache + let _e = walk_dir( + "target", + |dir: &Path| { + for top in &["debug", "release"] { + let _e = fs::remove_dir_all(dir.join(top).join("build")); + let _e = fs::remove_dir_all(dir.join(top).join("deps")); + let _e = fs::remove_dir_all(dir.join(top).join("examples")); + let _e = fs::remove_dir_all(dir.join(top).join("native")); + + let _e = walk_dir( + dir.join(top), + |sub_dir: &Path| { + if sub_dir + .file_name() + .map(|s| s.to_str().unwrap().starts_with("libsysroot")) + .unwrap_or(false) + { + let _e = fs::remove_dir_all(sub_dir); + } + Ok(()) + }, + |file: &Path| { + if file + .file_name() + .map(|s| s.to_str().unwrap().starts_with("libsysroot")) + .unwrap_or(false) + { + let _e = fs::remove_file(file); + } + Ok(()) + }, + ); + } + Ok(()) + }, + |_| Ok(()), + ); + + let _e = fs::remove_file("Cargo.lock"); + let _e = fs::remove_file("test_target/Cargo.lock"); + let _e = fs::remove_dir_all("sysroot"); + + // Builds libs + let channel = if release_mode { + let rustflags = env + .get(&"RUSTFLAGS".to_owned()) + .cloned() + .unwrap_or_default(); + env.insert( + "RUSTFLAGS".to_owned(), + format!("{rustflags} -Zmir-opt-level=3"), + ); + run_command_with_output( + &[ + &"cargo", + &"build", + &"--target", + &target_triple, + &"--release", + ], + None, + Some(&env), + )?; + "release" + } else { + run_command_with_output( + &[ + &"cargo", + &"build", + &"--target", + &target_triple, + &"--features", + &"compiler_builtins/c", + ], + None, + Some(env), + )?; + "debug" + }; + + // Copy files to sysroot + let sysroot_path = format!("sysroot/lib/rustlib/{target_triple}/lib/"); + fs::create_dir_all(&sysroot_path) + .map_err(|e| format!("Failed to create directory `{sysroot_path}`: {e:?}"))?; + let copier = |d: &Path| run_command_with_output(&[&"cp", &"-r", &d, &sysroot_path], None, None); + walk_dir( + &format!("target/{target_triple}/{channel}/deps"), + copier, + copier, + )?; + + Ok(()) +} + +fn build_codegen(args: &BuildArg) -> Result<(), String> { + let mut env = HashMap::new(); + + let current_dir = + std::env::current_dir().map_err(|e| format!("`current_dir` failed: {e:?}"))?; + env.insert( + "RUST_COMPILER_RT_ROOT".to_owned(), + format!("{}", current_dir.join("llvm/compiler-rt").display()), + ); + env.insert("LD_LIBRARY_PATH".to_owned(), args.gcc_path.clone()); + env.insert("LIBRARY_PATH".to_owned(), args.gcc_path.clone()); + + let mut command: Vec<&dyn AsRef> = vec![&"cargo", &"rustc"]; + if args.codegen_release_channel { + command.push(&"--release"); + env.insert("CHANNEL".to_owned(), "release".to_owned()); + env.insert("CARGO_INCREMENTAL".to_owned(), "1".to_owned()); + } else { + env.insert("CHANNEL".to_owned(), "debug".to_owned()); + } + let ref_features = args.features.iter().map(|s| s.as_str()).collect::>(); + for feature in &ref_features { + command.push(feature); + } + run_command_with_env(&command, None, Some(&env))?; + + let config = set_config(&mut env, &[], Some(&args.gcc_path))?; + + // We voluntarily ignore the error. + let _e = fs::remove_dir_all("target/out"); + let gccjit_target = "target/out/gccjit"; + fs::create_dir_all(gccjit_target) + .map_err(|e| format!("Failed to create directory `{gccjit_target}`: {e:?}"))?; + + println!("[BUILD] sysroot"); + build_sysroot( + &mut env, + args.sysroot_release_channel, + &config.target_triple, + )?; + Ok(()) +} + +pub fn run() -> Result<(), String> { + let args = match BuildArg::new()? { + Some(a) => a, + None => return Ok(()), + }; + build_codegen(&args)?; Ok(()) } diff --git a/build_system/src/config.rs b/build_system/src/config.rs new file mode 100644 index 00000000000..5160eb2ecae --- /dev/null +++ b/build_system/src/config.rs @@ -0,0 +1,121 @@ +use crate::utils::{get_gcc_path, get_os_name, get_rustc_host_triple}; +use std::collections::HashMap; +use std::env as std_env; + +pub struct ConfigInfo { + pub target_triple: String, + pub rustc_command: Vec, + pub run_wrapper: Option<&'static str>, +} + +// Returns the beginning for the command line of rustc. +pub fn set_config( + env: &mut HashMap, + test_flags: &[String], + gcc_path: Option<&str>, +) -> Result { + env.insert("CARGO_INCREMENTAL".to_owned(), "0".to_owned()); + + let gcc_path = match gcc_path { + Some(g) => g.to_owned(), + None => get_gcc_path()?, + }; + env.insert("GCC_PATH".to_owned(), gcc_path.clone()); + + let os_name = get_os_name()?; + let dylib_ext = match os_name.as_str() { + "Linux" => "so", + "Darwin" => "dylib", + os => return Err(format!("unsupported OS `{os}`")), + }; + let host_triple = get_rustc_host_triple()?; + let mut linker = None; + let mut target_triple = host_triple.as_str(); + let mut run_wrapper = None; + // FIXME: handle this with a command line flag? + // let mut target_triple = "m68k-unknown-linux-gnu"; + + if host_triple != target_triple { + if target_triple == "m68k-unknown-linux-gnu" { + target_triple = "mips-unknown-linux-gnu"; + linker = Some("-Clinker=m68k-linux-gcc"); + } else if target_triple == "aarch64-unknown-linux-gnu" { + // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. + linker = Some("-Clinker=aarch64-linux-gnu-gcc"); + run_wrapper = Some("qemu-aarch64 -L /usr/aarch64-linux-gnu"); + } else { + return Err(format!("unknown non-native platform `{target_triple}`")); + } + } + // Since we don't support ThinLTO, disable LTO completely when not trying to do LTO. + // TODO(antoyo): remove when we can handle ThinLTO. + let disable_lto_lfags = "-Clto=off"; + let current_dir = std_env::current_dir().map_err(|e| format!("`current_dir` failed: {e:?}"))?; + let cg_backend_path = current_dir + .join("target") + .join(if let Some(channel) = env.get(&"CHANNEL".to_owned()) { + channel.as_str() + } else { + "debug" + }) + .join(&format!("librustc_codegen_gcc.{dylib_ext}")); + let sysroot_path = current_dir.join("build_sysroot/sysroot"); + let mut rustflags = Vec::new(); + if let Some(cg_rustflags) = env.get(&"CG_RUSTFLAGS".to_owned()) { + rustflags.push(cg_rustflags.clone()); + } + if let Some(linker) = linker { + rustflags.push(linker.to_owned()); + } + rustflags.extend_from_slice(&[ + "-Csymbol-mangling-version=v0".to_owned(), + "-Cdebuginfo=2".to_owned(), + disable_lto_lfags.to_owned(), + format!("-Zcodegen-backend={}", cg_backend_path.display()), + "--sysroot".to_owned(), + format!("{}", sysroot_path.display()), + ]); + rustflags.extend_from_slice(test_flags); + // FIXME(antoyo): remove once the atomic shim is gone + if os_name == "Darwin" { + rustflags.extend_from_slice(&[ + "-Clink-arg=-undefined".to_owned(), + "-Clink-arg=dynamic_lookup".to_owned(), + ]); + } + env.insert("RUSTFLAGS".to_owned(), rustflags.join(" ")); + // display metadata load errors + env.insert("RUSTC_LOG".to_owned(), "warn".to_owned()); + + let ld_library_path = format!( + "{target}:{sysroot}:{gcc_path}", + target = current_dir.join("target/out").display(), + sysroot = current_dir + .join(&format!( + "build_sysroot/sysroot/lib/rustlib/{target_triple}/lib" + ),) + .display(), + ); + env.insert("LD_LIBRARY_PATH".to_owned(), ld_library_path.clone()); + env.insert("DYLD_LIBRARY_PATH".to_owned(), ld_library_path); + + // NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc. + // To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH. + // Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc + let path = std::env::var("PATH").unwrap_or_default(); + env.insert("PATH".to_owned(), format!("/opt/gcc/bin:{path}")); + + let mut rustc_command = vec!["rustc".to_owned()]; + rustc_command.extend_from_slice(&rustflags); + rustc_command.extend_from_slice(&[ + "-L".to_owned(), + "crate=target/out".to_owned(), + "--out-dir".to_owned(), + "target/out".to_owned(), + ]); + Ok(ConfigInfo { + target_triple: target_triple.to_owned(), + rustc_command, + run_wrapper, + }) +} diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 16c4c3a9c62..332a14ff0a2 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -2,6 +2,7 @@ use std::env; use std::process; mod build; +mod config; mod prepare; mod rustc_info; mod utils; @@ -16,12 +17,14 @@ macro_rules! arg_error { } fn usage() { - println!("\ + println!( + "\ Available commands for build_system: prepare : Run prepare command build : Run build command - --help : Show this message"); + --help : Show this message" + ); } pub enum Command { diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index 9c31b5cb8b3..6274628378e 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -15,11 +15,10 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> { None => return Err(format!("No parent for `{}`", rustc_path.display())), }; - let rustlib_dir = - parent - .join("../lib/rustlib/src/rust") - .canonicalize() - .map_err(|e| format!("Failed to canonicalize path: {e:?}"))?; + let rustlib_dir = parent + .join("../lib/rustlib/src/rust") + .canonicalize() + .map_err(|e| format!("Failed to canonicalize path: {e:?}"))?; if !rustlib_dir.is_dir() { return Err("Please install `rust-src` component".to_owned()); } @@ -27,18 +26,26 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> { let sysroot_dir = sysroot_path.join("sysroot_src"); if sysroot_dir.is_dir() { if let Err(e) = fs::remove_dir_all(&sysroot_dir) { - return Err(format!("Failed to remove `{}`: {:?}", sysroot_dir.display(), e)); + return Err(format!( + "Failed to remove `{}`: {:?}", + sysroot_dir.display(), + e + )); } } let sysroot_library_dir = sysroot_dir.join("library"); - fs::create_dir_all(&sysroot_library_dir) - .map_err(|e| format!( + fs::create_dir_all(&sysroot_library_dir).map_err(|e| { + format!( "Failed to create folder `{}`: {e:?}", sysroot_library_dir.display(), - ))?; + ) + })?; - run_command(&[&"cp", &"-r", &rustlib_dir.join("library"), &sysroot_dir], None)?; + run_command( + &[&"cp", &"-r", &rustlib_dir.join("library"), &sysroot_dir], + None, + )?; println!("[GIT] init (cwd): `{}`", sysroot_dir.display()); run_command(&[&"git", &"init"], Some(&sysroot_dir))?; @@ -49,26 +56,52 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> { // This is needed on systems where nothing is configured. // git really needs something here, or it will fail. // Even using --author is not enough. - run_command(&[&"git", &"config", &"user.email", &"none@example.com"], Some(&sysroot_dir))?; - run_command(&[&"git", &"config", &"user.name", &"None"], Some(&sysroot_dir))?; - run_command(&[&"git", &"config", &"core.autocrlf", &"false"], Some(&sysroot_dir))?; - run_command(&[&"git", &"config", &"commit.gpgSign", &"false"], Some(&sysroot_dir))?; - run_command(&[&"git", &"commit", &"-m", &"Initial commit", &"-q"], Some(&sysroot_dir))?; + run_command( + &[&"git", &"config", &"user.email", &"none@example.com"], + Some(&sysroot_dir), + )?; + run_command( + &[&"git", &"config", &"user.name", &"None"], + Some(&sysroot_dir), + )?; + run_command( + &[&"git", &"config", &"core.autocrlf", &"false"], + Some(&sysroot_dir), + )?; + run_command( + &[&"git", &"config", &"commit.gpgSign", &"false"], + Some(&sysroot_dir), + )?; + run_command( + &[&"git", &"commit", &"-m", &"Initial commit", &"-q"], + Some(&sysroot_dir), + )?; let mut patches = Vec::new(); - walk_dir("patches", |_| Ok(()), |file_path: &Path| { - patches.push(file_path.to_path_buf()); - Ok(()) - })?; + walk_dir( + "patches", + |_| Ok(()), + |file_path: &Path| { + patches.push(file_path.to_path_buf()); + Ok(()) + }, + )?; patches.sort(); for file_path in patches { println!("[GIT] apply `{}`", file_path.display()); let path = Path::new("../..").join(file_path); - run_command_with_output(&[&"git", &"apply", &path], Some(&sysroot_dir))?; - run_command_with_output(&[&"git", &"add", &"-A"], Some(&sysroot_dir))?; + run_command_with_output(&[&"git", &"apply", &path], Some(&sysroot_dir), None)?; + run_command_with_output(&[&"git", &"add", &"-A"], Some(&sysroot_dir), None)?; run_command_with_output( - &[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())], + &[ + &"git", + &"commit", + &"--no-gpg-sign", + &"-m", + &format!("Patch {}", path.display()), + ], Some(&sysroot_dir), + None, )?; } println!("Successfully prepared libcore for building"); @@ -83,7 +116,10 @@ fn build_raytracer(repo_dir: &Path) -> Result<(), String> { std::fs::remove_file(&mv_target) .map_err(|e| format!("Failed to remove file `{}`: {e:?}", mv_target.display()))?; } - run_command(&[&"mv", &"target/debug/main", &"raytracer_cg_llvm"], Some(repo_dir))?; + run_command( + &[&"mv", &"target/debug/main", &"raytracer_cg_llvm"], + Some(repo_dir), + )?; Ok(()) } @@ -99,16 +135,21 @@ where run_command(&[&"git", &"checkout", &"--", &"."], Some(&repo_path))?; run_command(&[&"git", &"checkout", &checkout_commit], Some(&repo_path))?; let filter = format!("-{}-", clone_result.repo_name); - walk_dir("crate_patches", |_| Ok(()), |file_path| { - let s = file_path.as_os_str().to_str().unwrap(); - if s.contains(&filter) && s.ends_with(".patch") { - run_command_with_output( - &[&"git", &"am", &file_path.canonicalize().unwrap()], - Some(&repo_path), - )?; - } - Ok(()) - })?; + walk_dir( + "crate_patches", + |_| Ok(()), + |file_path| { + let s = file_path.as_os_str().to_str().unwrap(); + if s.contains(&filter) && s.ends_with(".patch") { + run_command_with_output( + &[&"git", &"am", &file_path.canonicalize().unwrap()], + Some(&repo_path), + None, + )?; + } + Ok(()) + }, + )?; if let Some(extra) = extra { extra(&repo_path)?; } @@ -128,23 +169,23 @@ impl PrepareArg { "--only-libcore" => only_libcore = true, "--help" => { Self::usage(); - return Ok(None) + return Ok(None); } a => return Err(format!("Unknown argument `{a}`")), } } - Ok(Some(Self { - only_libcore, - })) + Ok(Some(Self { only_libcore })) } fn usage() { - println!(r#" + println!( + r#" `prepare` command help: --only-libcore : Only setup libcore and don't clone other repositories --help : Show this help -"#) +"# + ) } } @@ -160,9 +201,21 @@ pub fn run() -> Result<(), String> { cargo_install("hyperfine")?; let to_clone = &[ - ("https://github.com/rust-random/rand.git", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", None), - ("https://github.com/rust-lang/regex.git", "341f207c1071f7290e3f228c710817c280c8dca1", None), - ("https://github.com/ebobby/simple-raytracer", "804a7a21b9e673a482797aa289a18ed480e4d813", Some(build_raytracer)), + ( + "https://github.com/rust-random/rand.git", + "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", + None, + ), + ( + "https://github.com/rust-lang/regex.git", + "341f207c1071f7290e3f228c710817c280c8dca1", + None, + ), + ( + "https://github.com/ebobby/simple-raytracer", + "804a7a21b9e673a482797aa289a18ed480e4d813", + Some(build_raytracer), + ), ]; for (repo_url, checkout_commit, cb) in to_clone { diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index c350864dbd2..1724e275595 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -1,10 +1,15 @@ +use std::collections::HashMap; use std::ffi::OsStr; use std::fmt::Debug; use std::fs; use std::path::Path; use std::process::{Command, ExitStatus, Output}; -fn get_command_inner(input: &[&dyn AsRef], cwd: Option<&Path>) -> Command { +fn get_command_inner( + input: &[&dyn AsRef], + cwd: Option<&Path>, + env: Option<&HashMap>, +) -> Command { let (cmd, args) = match input { [] => panic!("empty command"), [cmd, args @ ..] => (cmd, args), @@ -14,6 +19,9 @@ fn get_command_inner(input: &[&dyn AsRef], cwd: Option<&Path>) -> Command if let Some(cwd) = cwd { command.current_dir(cwd); } + if let Some(env) = env { + command.envs(env.iter().map(|(k, v)| (k.as_str(), v.as_str()))); + } command } @@ -27,7 +35,8 @@ fn check_exit_status( } else { Err(format!( "Command `{}`{} exited with status {:?}", - input.iter() + input + .iter() .map(|s| s.as_ref().to_str().unwrap()) .collect::>() .join(" "), @@ -41,21 +50,27 @@ fn check_exit_status( fn command_error(input: &[&dyn AsRef], cwd: &Option<&Path>, error: D) -> String { format!( "Command `{}`{} failed to run: {error:?}", - input.iter() + input + .iter() .map(|s| s.as_ref().to_str().unwrap()) .collect::>() .join(" "), cwd.as_ref() - .map(|cwd| format!( - " (running in folder `{}`)", - cwd.display(), - )) + .map(|cwd| format!(" (running in folder `{}`)", cwd.display(),)) .unwrap_or_default(), ) } pub fn run_command(input: &[&dyn AsRef], cwd: Option<&Path>) -> Result { - let output = get_command_inner(input, cwd) + run_command_with_env(input, cwd, None) +} + +pub fn run_command_with_env( + input: &[&dyn AsRef], + cwd: Option<&Path>, + env: Option<&HashMap>, +) -> Result { + let output = get_command_inner(input, cwd, env) .output() .map_err(|e| command_error(input, &cwd, e))?; check_exit_status(input, cwd, output.status)?; @@ -65,8 +80,10 @@ pub fn run_command(input: &[&dyn AsRef], cwd: Option<&Path>) -> Result], cwd: Option<&Path>, + env: Option<&HashMap>, ) -> Result<(), String> { - let exit_status = get_command_inner(input, cwd).spawn() + let exit_status = get_command_inner(input, cwd, env) + .spawn() .map_err(|e| command_error(input, &cwd, e))? .wait() .map_err(|e| command_error(input, &cwd, e))?; @@ -94,12 +111,69 @@ pub fn cargo_install(to_install: &str) -> Result<(), String> { return Ok(()); } // We voluntarily ignore this error. - if run_command_with_output(&[&"cargo", &"install", &to_install], None).is_err() { + if run_command_with_output(&[&"cargo", &"install", &to_install], None, None).is_err() { println!("Skipping installation of `{to_install}`"); } Ok(()) } +pub fn get_os_name() -> Result { + let output = run_command(&[&"uname"], None)?; + let name = std::str::from_utf8(&output.stdout) + .unwrap_or("") + .trim() + .to_owned(); + if !name.is_empty() { + Ok(name) + } else { + Err(format!("Failed to retrieve the OS name")) + } +} + +pub fn get_rustc_host_triple() -> Result { + let output = run_command(&[&"rustc", &"-vV"], None)?; + let content = std::str::from_utf8(&output.stdout).unwrap_or(""); + + for line in content.split('\n').map(|line| line.trim()) { + if !line.starts_with("host:") { + continue; + } + return Ok(line.split(':').nth(1).unwrap().trim().to_owned()); + } + Err("Cannot find host triple".to_owned()) +} + +pub fn get_gcc_path() -> Result { + let content = match fs::read_to_string("gcc_path") { + Ok(c) => c, + Err(_) => { + return Err( + "Please put the path to your custom build of libgccjit in the file \ + `gcc_path`, see Readme.md for details" + .into(), + ) + } + }; + match content + .split('\n') + .map(|l| l.trim()) + .filter(|l| !l.is_empty()) + .next() + { + Some(gcc_path) => { + let path = Path::new(gcc_path); + if !path.exists() { + Err(format!( + "Path `{gcc_path}` contained in the `gcc_path` file doesn't exist" + )) + } else { + Ok(gcc_path.into()) + } + } + None => Err("No path found in `gcc_path` file".into()), + } +} + pub struct CloneResult { pub ran_clone: bool, pub repo_name: String, @@ -116,11 +190,17 @@ pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), String> @@ -130,8 +210,11 @@ where F: FnMut(&Path) -> Result<(), String>, { let dir = dir.as_ref(); - for entry in fs::read_dir(dir).map_err(|e| format!("Failed to read dir `{}`: {e:?}", dir.display()))? { - let entry = entry.map_err(|e| format!("Failed to read entry in `{}`: {e:?}", dir.display()))?; + for entry in + fs::read_dir(dir).map_err(|e| format!("Failed to read dir `{}`: {e:?}", dir.display()))? + { + let entry = + entry.map_err(|e| format!("Failed to read entry in `{}`: {e:?}", dir.display()))?; let entry_path = entry.path(); if entry_path.is_dir() { dir_cb(&entry_path)?; diff --git a/config.sh b/config.sh index ecc6d56b00e..c686df0c72a 100644 --- a/config.sh +++ b/config.sh @@ -48,7 +48,7 @@ fi export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS" # FIXME(antoyo): remove once the atomic shim is gone -if [[ `uname` == 'Darwin' ]]; then +if [[ unamestr == 'Darwin' ]]; then export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" fi From 33e1daa51b5e934675fe3ed2877db9456e8be625 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Oct 2023 16:01:02 +0200 Subject: [PATCH 093/103] Improve code --- build_system/src/build.rs | 105 +++++++++++++++++++-------------- build_system/src/config.rs | 84 +++++++++++++------------- build_system/src/prepare.rs | 25 ++++---- build_system/src/rustc_info.rs | 2 +- build_system/src/utils.rs | 46 ++++++++++----- 5 files changed, 147 insertions(+), 115 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 58c36412ea5..e2819c37ad9 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -1,5 +1,7 @@ use crate::config::set_config; -use crate::utils::{get_gcc_path, run_command_with_env, run_command_with_output, walk_dir}; +use crate::utils::{ + get_gcc_path, run_command, run_command_with_env, run_command_with_output_and_env, walk_dir, +}; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; @@ -9,7 +11,6 @@ use std::path::Path; struct BuildArg { codegen_release_channel: bool, sysroot_release_channel: bool, - no_default_features: bool, features: Vec, gcc_path: String, } @@ -21,27 +22,31 @@ impl BuildArg { gcc_path, ..Default::default() }; + // We skip binary name and the `build` command. let mut args = std::env::args().skip(2); while let Some(arg) = args.next() { match arg.as_str() { "--release" => build_arg.codegen_release_channel = true, "--release-sysroot" => build_arg.sysroot_release_channel = true, - "--no-default-features" => build_arg.no_default_features = true, + "--no-default-features" => { + build_arg.features.push("--no-default-features".to_string()); + } "--features" => { if let Some(arg) = args.next() { + build_arg.features.push("--features".to_string()); build_arg.features.push(arg.as_str().into()); } else { - return Err(format!( - "Expected a value after `--features`, found nothing" - )); + return Err( + "Expected a value after `--features`, found nothing".to_string() + ); } } "--help" => { Self::usage(); return Ok(None); } - a => return Err(format!("Unknown argument `{a}`")), + arg => return Err(format!("Unknown argument `{}`", arg)), } } Ok(Some(build_arg)) @@ -68,37 +73,37 @@ fn build_sysroot( target_triple: &str, ) -> Result<(), String> { std::env::set_current_dir("build_sysroot") - .map_err(|e| format!("Failed to go to `build_sysroot` directory: {e:?}"))?; + .map_err(|error| format!("Failed to go to `build_sysroot` directory: {:?}", error))?; // Cleanup for previous run - // v Clean target dir except for build scripts and incremental cache - let _e = walk_dir( + // Clean target dir except for build scripts and incremental cache + let _ = walk_dir( "target", |dir: &Path| { for top in &["debug", "release"] { - let _e = fs::remove_dir_all(dir.join(top).join("build")); - let _e = fs::remove_dir_all(dir.join(top).join("deps")); - let _e = fs::remove_dir_all(dir.join(top).join("examples")); - let _e = fs::remove_dir_all(dir.join(top).join("native")); + let _ = fs::remove_dir_all(dir.join(top).join("build")); + let _ = fs::remove_dir_all(dir.join(top).join("deps")); + let _ = fs::remove_dir_all(dir.join(top).join("examples")); + let _ = fs::remove_dir_all(dir.join(top).join("native")); - let _e = walk_dir( + let _ = walk_dir( dir.join(top), |sub_dir: &Path| { if sub_dir .file_name() - .map(|s| s.to_str().unwrap().starts_with("libsysroot")) + .map(|filename| filename.to_str().unwrap().starts_with("libsysroot")) .unwrap_or(false) { - let _e = fs::remove_dir_all(sub_dir); + let _ = fs::remove_dir_all(sub_dir); } Ok(()) }, |file: &Path| { if file .file_name() - .map(|s| s.to_str().unwrap().starts_with("libsysroot")) + .map(|filename| filename.to_str().unwrap().starts_with("libsysroot")) .unwrap_or(false) { - let _e = fs::remove_file(file); + let _ = fs::remove_file(file); } Ok(()) }, @@ -109,21 +114,21 @@ fn build_sysroot( |_| Ok(()), ); - let _e = fs::remove_file("Cargo.lock"); - let _e = fs::remove_file("test_target/Cargo.lock"); - let _e = fs::remove_dir_all("sysroot"); + let _ = fs::remove_file("Cargo.lock"); + let _ = fs::remove_file("test_target/Cargo.lock"); + let _ = fs::remove_dir_all("sysroot"); // Builds libs let channel = if release_mode { let rustflags = env - .get(&"RUSTFLAGS".to_owned()) + .get("RUSTFLAGS") .cloned() .unwrap_or_default(); env.insert( - "RUSTFLAGS".to_owned(), - format!("{rustflags} -Zmir-opt-level=3"), + "RUSTFLAGS".to_string(), + format!("{} -Zmir-opt-level=3", rustflags), ); - run_command_with_output( + run_command_with_output_and_env( &[ &"cargo", &"build", @@ -136,7 +141,7 @@ fn build_sysroot( )?; "release" } else { - run_command_with_output( + run_command_with_output_and_env( &[ &"cargo", &"build", @@ -152,12 +157,14 @@ fn build_sysroot( }; // Copy files to sysroot - let sysroot_path = format!("sysroot/lib/rustlib/{target_triple}/lib/"); + let sysroot_path = format!("sysroot/lib/rustlib/{}/lib/", target_triple); fs::create_dir_all(&sysroot_path) - .map_err(|e| format!("Failed to create directory `{sysroot_path}`: {e:?}"))?; - let copier = |d: &Path| run_command_with_output(&[&"cp", &"-r", &d, &sysroot_path], None, None); + .map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_path, error))?; + let copier = |dir_to_copy: &Path| { + run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ()) + }; walk_dir( - &format!("target/{target_triple}/{channel}/deps"), + &format!("target/{}/{}/deps", target_triple, channel), copier, copier, )?; @@ -169,21 +176,25 @@ fn build_codegen(args: &BuildArg) -> Result<(), String> { let mut env = HashMap::new(); let current_dir = - std::env::current_dir().map_err(|e| format!("`current_dir` failed: {e:?}"))?; - env.insert( - "RUST_COMPILER_RT_ROOT".to_owned(), - format!("{}", current_dir.join("llvm/compiler-rt").display()), - ); - env.insert("LD_LIBRARY_PATH".to_owned(), args.gcc_path.clone()); - env.insert("LIBRARY_PATH".to_owned(), args.gcc_path.clone()); + std::env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?; + if let Ok(rt_root) = std::env::var("RUST_COMPILER_RT_ROOT") { + env.insert("RUST_COMPILER_RT_ROOT".to_string(), rt_root); + } else { + env.insert( + "RUST_COMPILER_RT_ROOT".to_string(), + format!("{}", current_dir.join("llvm/compiler-rt").display()), + ); + } + env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone()); + env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone()); let mut command: Vec<&dyn AsRef> = vec![&"cargo", &"rustc"]; if args.codegen_release_channel { command.push(&"--release"); - env.insert("CHANNEL".to_owned(), "release".to_owned()); - env.insert("CARGO_INCREMENTAL".to_owned(), "1".to_owned()); + env.insert("CHANNEL".to_string(), "release".to_string()); + env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string()); } else { - env.insert("CHANNEL".to_owned(), "debug".to_owned()); + env.insert("CHANNEL".to_string(), "debug".to_string()); } let ref_features = args.features.iter().map(|s| s.as_str()).collect::>(); for feature in &ref_features { @@ -194,10 +205,14 @@ fn build_codegen(args: &BuildArg) -> Result<(), String> { let config = set_config(&mut env, &[], Some(&args.gcc_path))?; // We voluntarily ignore the error. - let _e = fs::remove_dir_all("target/out"); + let _ = fs::remove_dir_all("target/out"); let gccjit_target = "target/out/gccjit"; - fs::create_dir_all(gccjit_target) - .map_err(|e| format!("Failed to create directory `{gccjit_target}`: {e:?}"))?; + fs::create_dir_all(gccjit_target).map_err(|error| { + format!( + "Failed to create directory `{}`: {:?}", + gccjit_target, error + ) + })?; println!("[BUILD] sysroot"); build_sysroot( @@ -210,7 +225,7 @@ fn build_codegen(args: &BuildArg) -> Result<(), String> { pub fn run() -> Result<(), String> { let args = match BuildArg::new()? { - Some(a) => a, + Some(args) => args, None => return Ok(()), }; build_codegen(&args)?; diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 5160eb2ecae..4f2e33f0f99 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -14,19 +14,19 @@ pub fn set_config( test_flags: &[String], gcc_path: Option<&str>, ) -> Result { - env.insert("CARGO_INCREMENTAL".to_owned(), "0".to_owned()); + env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); let gcc_path = match gcc_path { - Some(g) => g.to_owned(), + Some(path) => path.to_string(), None => get_gcc_path()?, }; - env.insert("GCC_PATH".to_owned(), gcc_path.clone()); + env.insert("GCC_PATH".to_string(), gcc_path.clone()); let os_name = get_os_name()?; let dylib_ext = match os_name.as_str() { "Linux" => "so", "Darwin" => "dylib", - os => return Err(format!("unsupported OS `{os}`")), + os => return Err(format!("unsupported OS `{}`", os)), }; let host_triple = get_rustc_host_triple()?; let mut linker = None; @@ -44,77 +44,81 @@ pub fn set_config( linker = Some("-Clinker=aarch64-linux-gnu-gcc"); run_wrapper = Some("qemu-aarch64 -L /usr/aarch64-linux-gnu"); } else { - return Err(format!("unknown non-native platform `{target_triple}`")); + return Err(format!("unknown non-native platform `{}`", target_triple)); } } - // Since we don't support ThinLTO, disable LTO completely when not trying to do LTO. - // TODO(antoyo): remove when we can handle ThinLTO. - let disable_lto_lfags = "-Clto=off"; - let current_dir = std_env::current_dir().map_err(|e| format!("`current_dir` failed: {e:?}"))?; + let current_dir = + std_env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?; + let channel = if let Some(channel) = env.get("CHANNEL") { + channel.as_str() + } else { + "debug" + }; let cg_backend_path = current_dir .join("target") - .join(if let Some(channel) = env.get(&"CHANNEL".to_owned()) { - channel.as_str() - } else { - "debug" - }) - .join(&format!("librustc_codegen_gcc.{dylib_ext}")); + .join(channel) + .join(&format!("librustc_codegen_gcc.{}", dylib_ext)); let sysroot_path = current_dir.join("build_sysroot/sysroot"); let mut rustflags = Vec::new(); - if let Some(cg_rustflags) = env.get(&"CG_RUSTFLAGS".to_owned()) { + if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") { rustflags.push(cg_rustflags.clone()); } if let Some(linker) = linker { - rustflags.push(linker.to_owned()); + rustflags.push(linker.to_string()); } rustflags.extend_from_slice(&[ - "-Csymbol-mangling-version=v0".to_owned(), - "-Cdebuginfo=2".to_owned(), - disable_lto_lfags.to_owned(), + "-Csymbol-mangling-version=v0".to_string(), + "-Cdebuginfo=2".to_string(), format!("-Zcodegen-backend={}", cg_backend_path.display()), - "--sysroot".to_owned(), - format!("{}", sysroot_path.display()), + "--sysroot".to_string(), + sysroot_path.display().to_string(), ]); + + // Since we don't support ThinLTO, disable LTO completely when not trying to do LTO. + // TODO(antoyo): remove when we can handle ThinLTO. + if !env.contains_key(&"FAT_LTO".to_string()) { + rustflags.push("-Clto=off".to_string()); + } rustflags.extend_from_slice(test_flags); // FIXME(antoyo): remove once the atomic shim is gone if os_name == "Darwin" { rustflags.extend_from_slice(&[ - "-Clink-arg=-undefined".to_owned(), - "-Clink-arg=dynamic_lookup".to_owned(), + "-Clink-arg=-undefined".to_string(), + "-Clink-arg=dynamic_lookup".to_string(), ]); } - env.insert("RUSTFLAGS".to_owned(), rustflags.join(" ")); + env.insert("RUSTFLAGS".to_string(), rustflags.join(" ")); // display metadata load errors - env.insert("RUSTC_LOG".to_owned(), "warn".to_owned()); + env.insert("RUSTC_LOG".to_string(), "warn".to_string()); + let sysroot = current_dir.join(&format!( + "build_sysroot/sysroot/lib/rustlib/{}/lib", + target_triple + )); let ld_library_path = format!( "{target}:{sysroot}:{gcc_path}", target = current_dir.join("target/out").display(), - sysroot = current_dir - .join(&format!( - "build_sysroot/sysroot/lib/rustlib/{target_triple}/lib" - ),) - .display(), + sysroot = sysroot.display(), ); - env.insert("LD_LIBRARY_PATH".to_owned(), ld_library_path.clone()); - env.insert("DYLD_LIBRARY_PATH".to_owned(), ld_library_path); + env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone()); + env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path); // NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc. // To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH. // Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc let path = std::env::var("PATH").unwrap_or_default(); - env.insert("PATH".to_owned(), format!("/opt/gcc/bin:{path}")); + env.insert("PATH".to_string(), format!("/opt/gcc/bin:{}", path)); - let mut rustc_command = vec!["rustc".to_owned()]; + let mut rustc_command = vec!["rustc".to_string()]; rustc_command.extend_from_slice(&rustflags); rustc_command.extend_from_slice(&[ - "-L".to_owned(), - "crate=target/out".to_owned(), - "--out-dir".to_owned(), - "target/out".to_owned(), + "-L".to_string(), + "crate=target/out".to_string(), + "--out-dir".to_string(), + "target/out".to_string(), ]); Ok(ConfigInfo { - target_triple: target_triple.to_owned(), + target_triple: target_triple.to_string(), rustc_command, run_wrapper, }) diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index 6274628378e..b258ddf3664 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -7,7 +7,7 @@ use std::path::Path; fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> { let rustc_path = match get_rustc_path() { Some(path) => path, - None => return Err("`rustc` path not found".to_owned()), + None => return Err("`rustc` path not found".to_string()), }; let parent = match rustc_path.parent() { @@ -18,27 +18,28 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> { let rustlib_dir = parent .join("../lib/rustlib/src/rust") .canonicalize() - .map_err(|e| format!("Failed to canonicalize path: {e:?}"))?; + .map_err(|error| format!("Failed to canonicalize path: {:?}", error))?; if !rustlib_dir.is_dir() { - return Err("Please install `rust-src` component".to_owned()); + return Err("Please install `rust-src` component".to_string()); } let sysroot_dir = sysroot_path.join("sysroot_src"); if sysroot_dir.is_dir() { - if let Err(e) = fs::remove_dir_all(&sysroot_dir) { + if let Err(error) = fs::remove_dir_all(&sysroot_dir) { return Err(format!( "Failed to remove `{}`: {:?}", sysroot_dir.display(), - e + error, )); } } let sysroot_library_dir = sysroot_dir.join("library"); - fs::create_dir_all(&sysroot_library_dir).map_err(|e| { + fs::create_dir_all(&sysroot_library_dir).map_err(|error| { format!( - "Failed to create folder `{}`: {e:?}", + "Failed to create folder `{}`: {:?}", sysroot_library_dir.display(), + error, ) })?; @@ -90,8 +91,8 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> { for file_path in patches { println!("[GIT] apply `{}`", file_path.display()); let path = Path::new("../..").join(file_path); - run_command_with_output(&[&"git", &"apply", &path], Some(&sysroot_dir), None)?; - run_command_with_output(&[&"git", &"add", &"-A"], Some(&sysroot_dir), None)?; + run_command_with_output(&[&"git", &"apply", &path], Some(&sysroot_dir))?; + run_command_with_output(&[&"git", &"add", &"-A"], Some(&sysroot_dir))?; run_command_with_output( &[ &"git", @@ -101,7 +102,6 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> { &format!("Patch {}", path.display()), ], Some(&sysroot_dir), - None, )?; } println!("Successfully prepared libcore for building"); @@ -139,12 +139,11 @@ where "crate_patches", |_| Ok(()), |file_path| { - let s = file_path.as_os_str().to_str().unwrap(); - if s.contains(&filter) && s.ends_with(".patch") { + let patch = file_path.as_os_str().to_str().unwrap(); + if patch.contains(&filter) && patch.ends_with(".patch") { run_command_with_output( &[&"git", &"am", &file_path.canonicalize().unwrap()], Some(&repo_path), - None, )?; } Ok(()) diff --git a/build_system/src/rustc_info.rs b/build_system/src/rustc_info.rs index 38c0045c7b3..0988b56d81e 100644 --- a/build_system/src/rustc_info.rs +++ b/build_system/src/rustc_info.rs @@ -8,5 +8,5 @@ pub fn get_rustc_path() -> Option { } run_command(&[&"rustup", &"which", &"rustc"], None) .ok() - .map(|out| Path::new(String::from_utf8(out.stdout).unwrap().trim()).to_owned()) + .map(|out| Path::new(String::from_utf8(out.stdout).unwrap().trim()).to_path_buf()) } diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 1724e275595..536f33a8029 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -80,6 +80,19 @@ pub fn run_command_with_env( pub fn run_command_with_output( input: &[&dyn AsRef], cwd: Option<&Path>, +) -> Result<(), String> { + let exit_status = get_command_inner(input, cwd, None) + .spawn() + .map_err(|e| command_error(input, &cwd, e))? + .wait() + .map_err(|e| command_error(input, &cwd, e))?; + check_exit_status(input, cwd, exit_status)?; + Ok(()) +} + +pub fn run_command_with_output_and_env( + input: &[&dyn AsRef], + cwd: Option<&Path>, env: Option<&HashMap>, ) -> Result<(), String> { let exit_status = get_command_inner(input, cwd, env) @@ -111,7 +124,7 @@ pub fn cargo_install(to_install: &str) -> Result<(), String> { return Ok(()); } // We voluntarily ignore this error. - if run_command_with_output(&[&"cargo", &"install", &to_install], None, None).is_err() { + if run_command_with_output(&[&"cargo", &"install", &to_install], None).is_err() { println!("Skipping installation of `{to_install}`"); } Ok(()) @@ -122,11 +135,11 @@ pub fn get_os_name() -> Result { let name = std::str::from_utf8(&output.stdout) .unwrap_or("") .trim() - .to_owned(); + .to_string(); if !name.is_empty() { Ok(name) } else { - Err(format!("Failed to retrieve the OS name")) + Err("Failed to retrieve the OS name".to_string()) } } @@ -138,14 +151,14 @@ pub fn get_rustc_host_triple() -> Result { if !line.starts_with("host:") { continue; } - return Ok(line.split(':').nth(1).unwrap().trim().to_owned()); + return Ok(line.split(':').nth(1).unwrap().trim().to_string()); } - Err("Cannot find host triple".to_owned()) + Err("Cannot find host triple".to_string()) } pub fn get_gcc_path() -> Result { let content = match fs::read_to_string("gcc_path") { - Ok(c) => c, + Ok(content) => content, Err(_) => { return Err( "Please put the path to your custom build of libgccjit in the file \ @@ -156,15 +169,16 @@ pub fn get_gcc_path() -> Result { }; match content .split('\n') - .map(|l| l.trim()) - .filter(|l| !l.is_empty()) + .map(|line| line.trim()) + .filter(|line| !line.is_empty()) .next() { Some(gcc_path) => { let path = Path::new(gcc_path); if !path.exists() { Err(format!( - "Path `{gcc_path}` contained in the `gcc_path` file doesn't exist" + "Path `{}` contained in the `gcc_path` file doesn't exist", + gcc_path, )) } else { Ok(gcc_path.into()) @@ -182,8 +196,8 @@ pub struct CloneResult { pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result { let repo_name = to_clone.split('/').last().unwrap(); let repo_name = match repo_name.strip_suffix(".git") { - Some(n) => n.to_owned(), - None => repo_name.to_owned(), + Some(n) => n.to_string(), + None => repo_name.to_string(), }; let dest = dest @@ -196,7 +210,7 @@ pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result Result<(), String>, { let dir = dir.as_ref(); - for entry in - fs::read_dir(dir).map_err(|e| format!("Failed to read dir `{}`: {e:?}", dir.display()))? + for entry in fs::read_dir(dir) + .map_err(|error| format!("Failed to read dir `{}`: {:?}", dir.display(), error))? { - let entry = - entry.map_err(|e| format!("Failed to read entry in `{}`: {e:?}", dir.display()))?; + let entry = entry + .map_err(|error| format!("Failed to read entry in `{}`: {:?}", dir.display(), error))?; let entry_path = entry.path(); if entry_path.is_dir() { dir_cb(&entry_path)?; From b3fecae7d736eeb9e4170563b1bc0f4511e58125 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 7 Oct 2023 15:14:54 -0400 Subject: [PATCH 094/103] Fix 128-bit non-native integers comparison --- Readme.md | 2 ++ src/int.rs | 68 +++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/Readme.md b/Readme.md index 060f7c0326d..78a7b2d75d5 100644 --- a/Readme.md +++ b/Readme.md @@ -113,6 +113,8 @@ $ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) rustc +$(cat $CG_
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 diff --git a/src/int.rs b/src/int.rs index 2a6b1d17a3e..4422162828d 100644 --- a/src/int.rs +++ b/src/int.rs @@ -353,23 +353,63 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { (res.dereference(None).to_rvalue(), overflow) } - pub fn gcc_icmp(&self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> { + pub fn gcc_icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> { let a_type = lhs.get_type(); let b_type = rhs.get_type(); if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) { - let signed = a_type.is_compatible_with(self.i128_type); - let sign = - if signed { - "" - } - else { - "u" - }; - let func_name = format!("__{}cmpti2", sign); - let param_a = self.context.new_parameter(None, a_type, "a"); - let param_b = self.context.new_parameter(None, b_type, "b"); - let func = self.context.new_function(None, FunctionType::Extern, self.int_type, &[param_a, param_b], func_name, false); - let cmp = self.context.new_call(None, func, &[lhs, rhs]); + // This algorithm is based on compiler-rt's __cmpti2: + // https://github.com/llvm-mirror/compiler-rt/blob/f0745e8476f069296a7c71accedd061dce4cdf79/lib/builtins/cmpti2.c#L21 + let result = self.current_func().new_local(None, self.int_type, "icmp_result"); + let block1 = self.current_func().new_block("block1"); + let block2 = self.current_func().new_block("block2"); + let block3 = self.current_func().new_block("block3"); + let block4 = self.current_func().new_block("block4"); + let block5 = self.current_func().new_block("block5"); + let block6 = self.current_func().new_block("block6"); + let block7 = self.current_func().new_block("block7"); + let block8 = self.current_func().new_block("block8"); + let after = self.current_func().new_block("after"); + + let native_int_type = a_type.dyncast_array().expect("get element type"); + // NOTE: cast low to its unsigned type in order to perform a comparison correctly (e.g. + // the sign is only on high). + let unsigned_type = native_int_type.to_unsigned(&self.cx); + + let lhs_low = self.context.new_cast(None, self.low(lhs), unsigned_type); + let rhs_low = self.context.new_cast(None, self.low(rhs), unsigned_type); + + let condition = self.context.new_comparison(None, ComparisonOp::LessThan, self.high(lhs), self.high(rhs)); + self.llbb().end_with_conditional(None, condition, block1, block2); + + block1.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type)); + block1.end_with_jump(None, after); + + let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, self.high(lhs), self.high(rhs)); + block2.end_with_conditional(None, condition, block3, block4); + + block3.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2)); + block3.end_with_jump(None, after); + + let condition = self.context.new_comparison(None, ComparisonOp::LessThan, lhs_low, rhs_low); + block4.end_with_conditional(None, condition, block5, block6); + + block5.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type)); + block5.end_with_jump(None, after); + + let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, lhs_low, rhs_low); + block6.end_with_conditional(None, condition, block7, block8); + + block7.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2)); + block7.end_with_jump(None, after); + + block8.add_assignment(None, result, self.context.new_rvalue_one(self.int_type)); + block8.end_with_jump(None, after); + + // NOTE: since jumps were added in a place rustc does not expect, the current block in the + // state need to be updated. + self.switch_to_block(after); + + let cmp = result.to_rvalue(); let (op, limit) = match op { IntPredicate::IntEQ => { From b3c10d4a7d01e46f609a1eb8b133d9985329a987 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 7 Oct 2023 15:15:02 -0400 Subject: [PATCH 095/103] Fix 128-bit non-native integers negation --- src/int.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/int.rs b/src/int.rs index 4422162828d..58e0dd56f38 100644 --- a/src/int.rs +++ b/src/int.rs @@ -36,7 +36,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.cx.context.new_unary_op(None, operation, typ, a) } else { - // TODO(antoyo): use __negdi2 and __negti2 instead? let element_type = typ.dyncast_array().expect("element type"); let values = [ self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.low(a)), @@ -52,9 +51,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a) } else { - let param_a = self.context.new_parameter(None, a_type, "a"); - let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a], "__negti2", false); - self.context.new_call(None, func, &[a]) + self.gcc_add(self.gcc_not(a), self.gcc_int(a_type, 1)) } } From 237be9e0cb83101ba910a1fd62b3a56277cbfcd2 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 8 Oct 2023 11:32:07 -0400 Subject: [PATCH 096/103] Update to nightly-2023-10-08 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 1b60d708007..25a1cea98cc 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-08-12" +channel = "nightly-2023-10-08" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From bd7e5b9d4e58c6926b280c0657a9c723be25f4ed Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 9 Oct 2023 08:28:06 -0400 Subject: [PATCH 097/103] Fix bitcast with different sizes --- src/type_of.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/type_of.rs b/src/type_of.rs index cc467801beb..c2eab295acd 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -182,6 +182,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { /// of that field's type - this is useful for taking the address of /// that field and ensuring the struct has the right alignment. fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { + use crate::rustc_middle::ty::layout::FnAbiOf; // This must produce the same result for `repr(transparent)` wrappers as for the inner type! // In other words, this should generally not look at the type at all, but only at the // layout. @@ -191,7 +192,14 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) { return ty; } - let ty = self.scalar_gcc_type_at(cx, scalar, Size::ZERO); + let ty = + match *self.ty.kind() { + // NOTE: we cannot remove this match like in the LLVM codegen because the call + // to fn_ptr_backend_type handle the on-stack attribute. + // TODO(antoyo): find a less hackish way to hande the on-stack attribute. + ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())), + _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO), + }; cx.scalar_types.borrow_mut().insert(self.ty, ty); return ty; } From e7f7fb87ddd9ddfa4c52c6b683a501a9ab3eba8b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 9 Oct 2023 10:55:25 -0400 Subject: [PATCH 098/103] Fix tests --- tests/run/abort1.rs | 2 +- tests/run/abort2.rs | 2 +- tests/run/array.rs | 2 +- tests/run/assign.rs | 2 +- tests/run/closure.rs | 2 +- tests/run/condition.rs | 2 +- tests/run/fun_ptr.rs | 2 +- tests/run/int_overflow.rs | 2 +- tests/run/mut_ref.rs | 2 +- tests/run/operations.rs | 2 +- tests/run/ptr_cast.rs | 2 +- tests/run/slice.rs | 2 +- tests/run/static.rs | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/run/abort1.rs b/tests/run/abort1.rs index 6cb3dd90203..44297e12779 100644 --- a/tests/run/abort1.rs +++ b/tests/run/abort1.rs @@ -3,7 +3,7 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] diff --git a/tests/run/abort2.rs b/tests/run/abort2.rs index b7a928166b8..ce816927123 100644 --- a/tests/run/abort2.rs +++ b/tests/run/abort2.rs @@ -3,7 +3,7 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] diff --git a/tests/run/array.rs b/tests/run/array.rs index d2d60b75e63..afd0eed8200 100644 --- a/tests/run/array.rs +++ b/tests/run/array.rs @@ -7,7 +7,7 @@ // 5 // 10 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] diff --git a/tests/run/assign.rs b/tests/run/assign.rs index 241acea5e49..5b0db2da294 100644 --- a/tests/run/assign.rs +++ b/tests/run/assign.rs @@ -6,7 +6,7 @@ // 10 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, track_caller)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] #![no_std] #![no_core] diff --git a/tests/run/closure.rs b/tests/run/closure.rs index 764c5b34426..4ce528f8680 100644 --- a/tests/run/closure.rs +++ b/tests/run/closure.rs @@ -9,7 +9,7 @@ // Both args: 11 #![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, - unboxed_closures)] + unboxed_closures, rustc_attrs)] #![allow(internal_features)] #![no_std] diff --git a/tests/run/condition.rs b/tests/run/condition.rs index ed17c19409e..1b3ae6dc004 100644 --- a/tests/run/condition.rs +++ b/tests/run/condition.rs @@ -5,7 +5,7 @@ // stdout: true // 1 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] diff --git a/tests/run/fun_ptr.rs b/tests/run/fun_ptr.rs index e0c30cada6b..96030359772 100644 --- a/tests/run/fun_ptr.rs +++ b/tests/run/fun_ptr.rs @@ -4,7 +4,7 @@ // status: 0 // stdout: 1 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] diff --git a/tests/run/int_overflow.rs b/tests/run/int_overflow.rs index badcc0f7699..08fa087fccd 100644 --- a/tests/run/int_overflow.rs +++ b/tests/run/int_overflow.rs @@ -5,7 +5,7 @@ // status: signal #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] #![no_std] #![no_core] diff --git a/tests/run/mut_ref.rs b/tests/run/mut_ref.rs index e843e298537..194e55a3dea 100644 --- a/tests/run/mut_ref.rs +++ b/tests/run/mut_ref.rs @@ -8,7 +8,7 @@ // 11 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, track_caller)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] #![no_std] #![no_core] diff --git a/tests/run/operations.rs b/tests/run/operations.rs index cac6fdfca4a..2d781670873 100644 --- a/tests/run/operations.rs +++ b/tests/run/operations.rs @@ -6,7 +6,7 @@ // 10 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types, rustc_attrs)] #![no_std] #![no_core] diff --git a/tests/run/ptr_cast.rs b/tests/run/ptr_cast.rs index 41866179828..09d77abe27c 100644 --- a/tests/run/ptr_cast.rs +++ b/tests/run/ptr_cast.rs @@ -4,7 +4,7 @@ // status: 0 // stdout: 1 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] diff --git a/tests/run/slice.rs b/tests/run/slice.rs index 25ff72549d4..1262c86c810 100644 --- a/tests/run/slice.rs +++ b/tests/run/slice.rs @@ -4,7 +4,7 @@ // status: 0 // stdout: 5 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] diff --git a/tests/run/static.rs b/tests/run/static.rs index 2457bb1f443..0b933754c29 100644 --- a/tests/run/static.rs +++ b/tests/run/static.rs @@ -9,7 +9,7 @@ // 12 // 1 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] From ad5637468e8cc1e3de1c8b9454dec01ae5b2b60a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 9 Oct 2023 11:08:42 -0400 Subject: [PATCH 099/103] Add missing panic_in_cleanup --- example/mini_core.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/example/mini_core.rs b/example/mini_core.rs index 58df29bb625..34328520343 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -429,6 +429,15 @@ fn panic_cannot_unwind() -> ! { } } +#[lang = "panic_in_cleanup"] +#[rustc_nounwind] +fn panic_in_cleanup() -> ! { + unsafe { + libc::printf("panic in a destructor during cleanup\n\0" as *const str as *const i8); + intrinsics::abort(); + } +} + #[lang = "panic_bounds_check"] #[track_caller] fn panic_bounds_check(index: usize, len: usize) -> ! { From 3fe53587e428751d11a78247776768f90f6f4127 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 9 Oct 2023 11:09:53 -0400 Subject: [PATCH 100/103] Add missing comma in alloc_system --- example/alloc_system.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/alloc_system.rs b/example/alloc_system.rs index 3deef419f42..56ff84e4bdf 100644 --- a/example/alloc_system.rs +++ b/example/alloc_system.rs @@ -12,7 +12,7 @@ target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc", - target_arch = "csky" + target_arch = "csky", target_arch = "powerpc64"))] const MIN_ALIGN: usize = 8; #[cfg(any(target_arch = "x86_64", From 70834391ae427eb1870f2a9a09bce90a8f3b7ea7 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 9 Oct 2023 11:27:43 -0400 Subject: [PATCH 101/103] Fix UI tests --- failing-ui-tests.txt | 3 +++ test.sh | 1 + 2 files changed, 4 insertions(+) diff --git a/failing-ui-tests.txt b/failing-ui-tests.txt index 8ec151f7838..ed56a11a170 100644 --- a/failing-ui-tests.txt +++ b/failing-ui-tests.txt @@ -68,3 +68,6 @@ tests/ui/lto/thin-lto-global-allocator.rs tests/ui/lto/msvc-imp-present.rs tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs tests/ui/lto/all-crates.rs +tests/ui/async-await/deep-futures-are-freeze.rs +tests/ui/closures/capture-unsized-by-ref.rs +tests/ui/generator/resume-after-return.rs diff --git a/test.sh b/test.sh index 4655c920d2e..e4cbd6fbcaf 100755 --- a/test.sh +++ b/test.sh @@ -359,6 +359,7 @@ function test_rustc() { git checkout tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs git checkout tests/ui/imports/ambiguous-1.rs git checkout tests/ui/imports/ambiguous-4-extern.rs + git checkout tests/ui/entry-point/auxiliary/bad_main_functions.rs RUSTC_ARGS="$TEST_FLAGS -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot" From a00ea0bf986be52723a7e8b47c444d281955ce28 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 9 Oct 2023 13:03:23 -0400 Subject: [PATCH 102/103] Fix unchecked_sadd --- src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index 02d46654f04..62bce7eb78c 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -656,7 +656,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - a + b + self.gcc_add(a, b) } fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { From a7532daa76f4e3f79957862ee5e466dd2233d86d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 9 Oct 2023 13:16:47 -0400 Subject: [PATCH 103/103] Fix unchecked_ssub, unchecked_smul, and unchecked_umul --- src/builder.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 62bce7eb78c..b7841808934 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -664,7 +664,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - a - b + self.gcc_sub(a, b) } fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -673,11 +673,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - a * b + self.gcc_mul(a, b) } fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - a * b + self.gcc_mul(a, b) } fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {