From be2f12821121e5d2af61f16580fb53bf5da2a182 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 26 Jan 2026 16:58:31 -0800 Subject: [PATCH 001/166] Fix: On wasm targets, call `panic_in_cleanup` if panic occurs in cleanup Previously this was not correctly implemented. Each funclet may need its own terminate block, so this changes the `terminate_block` into a `terminate_blocks` `IndexVec` which can have a terminate_block for each funclet. We key on the first basic block of the funclet -- in particular, this is the start block for the old case of the top level terminate function. Rather than using a catchswitch/catchpad pair, I used a cleanuppad. The reason for the pair is to avoid catching foreign exceptions on MSVC. On wasm, it seems that the catchswitch/catchpad pair is optimized back into a single cleanuppad and a catch_all instruction is emitted which will catch foreign exceptions. Because the new logic is only used on wasm, it seemed better to take the simpler approach seeing as they do the same thing. --- src/builder.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/builder.rs b/src/builder.rs index 3cffd862b9b98..08964113b944a 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1657,6 +1657,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { unimplemented!(); } + fn get_funclet_cleanuppad(&self, _funclet: &Funclet) -> RValue<'gcc> { + unimplemented!(); + } + // Atomic Operations fn atomic_cmpxchg( &mut self, From 062e9f351a64ee727b9fad1af6343d3d2b17db31 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 12 Apr 2026 10:46:11 +0200 Subject: [PATCH 002/166] simd_reduce_min/max: remove float support --- src/builder.rs | 57 ------------------------------------------- src/intrinsic/simd.rs | 7 +++--- 2 files changed, 3 insertions(+), 61 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 3cffd862b9b98..065ed43be8cfe 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -2313,67 +2313,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.vector_extremum(a, b, ExtremumOperation::Min) } - #[cfg(feature = "master")] - pub fn vector_reduce_fmin(&mut self, src: RValue<'gcc>) -> RValue<'gcc> { - let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type"); - let element_count = vector_type.get_num_units(); - let mut acc = self - .context - .new_vector_access(self.location, src, self.context.new_rvalue_zero(self.int_type)) - .to_rvalue(); - for i in 1..element_count { - let elem = self - .context - .new_vector_access( - self.location, - src, - self.context.new_rvalue_from_int(self.int_type, i as _), - ) - .to_rvalue(); - let cmp = self.context.new_comparison(self.location, ComparisonOp::LessThan, acc, elem); - acc = self.select(cmp, acc, elem); - } - acc - } - - #[cfg(not(feature = "master"))] - pub fn vector_reduce_fmin(&mut self, _src: RValue<'gcc>) -> RValue<'gcc> { - unimplemented!(); - } - pub fn vector_maximum_number_nsz(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { self.vector_extremum(a, b, ExtremumOperation::Max) } - #[cfg(feature = "master")] - pub fn vector_reduce_fmax(&mut self, src: RValue<'gcc>) -> RValue<'gcc> { - let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type"); - let element_count = vector_type.get_num_units(); - let mut acc = self - .context - .new_vector_access(self.location, src, self.context.new_rvalue_zero(self.int_type)) - .to_rvalue(); - for i in 1..element_count { - let elem = self - .context - .new_vector_access( - self.location, - src, - self.context.new_rvalue_from_int(self.int_type, i as _), - ) - .to_rvalue(); - let cmp = - self.context.new_comparison(self.location, ComparisonOp::GreaterThan, acc, elem); - acc = self.select(cmp, acc, elem); - } - acc - } - - #[cfg(not(feature = "master"))] - pub fn vector_reduce_fmax(&mut self, _src: RValue<'gcc>) -> RValue<'gcc> { - unimplemented!(); - } - pub fn vector_select( &mut self, cond: RValue<'gcc>, diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 6fd19c4f82c37..bdb8316f3965d 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -1422,7 +1422,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ); macro_rules! minmax_red { - ($name:ident: $int_red:ident, $float_red:ident) => { + ($name:ident: $int_red:ident) => { if name == sym::$name { require!( ret_ty == in_elem, @@ -1430,7 +1430,6 @@ 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, name, @@ -1444,8 +1443,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( }; } - minmax_red!(simd_reduce_min: vector_reduce_min, vector_reduce_fmin); - minmax_red!(simd_reduce_max: vector_reduce_max, vector_reduce_fmax); + minmax_red!(simd_reduce_min: vector_reduce_min); + minmax_red!(simd_reduce_max: vector_reduce_max); macro_rules! bitwise_red { ($name:ident : $op:expr, $boolean:expr) => { From e001838589f9c41e258917bbb9622656f743cd8f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 29 Apr 2026 23:12:39 +0200 Subject: [PATCH 003/166] Merge commit 'd189e9f23c4c971546cb59bf43ab4df0e5552770' into subtree-update_cg_gcc_2026-04-29 --- .github/workflows/ci.yml | 4 +- .github/workflows/failures.yml | 4 +- .github/workflows/gcc12.yml | 4 +- .github/workflows/m68k.yml | 4 +- .github/workflows/stdarch.yml | 6 +- Cargo.toml | 8 +- build_system/src/test.rs | 61 +++++ example/mini_core.rs | 56 ++++- libgccjit.version | 2 +- rust-toolchain | 2 +- src/abi.rs | 11 +- src/asm.rs | 22 +- src/base.rs | 14 +- src/builder.rs | 34 +-- src/context.rs | 7 +- src/errors.rs | 7 + src/intrinsic/llvm.rs | 4 + src/intrinsic/mod.rs | 207 +++++++-------- tests/compile/asm_nul_byte.rs | 15 ++ .../{run => compile}/call-llvm-intrinsics.rs | 8 +- tests/compile/fn_ptr_transmute_ignored_arg.rs | 12 + tests/compile/global_asm_nul_byte.rs | 13 + tests/compile/log.rs | 12 + tests/compile/naked_asm_nul_byte.rs | 17 ++ tests/{run => compile}/simd-ffi.rs | 12 +- tests/failing-lto-tests.txt | 1 - tests/failing-ui-tests.txt | 14 +- tests/lang_tests.rs | 237 ++++++++++++++++++ tests/lang_tests_debug.rs | 5 - tests/lang_tests_release.rs | 5 - tests/no_builtins/no_builtins.rs | 24 ++ tests/no_builtins/with_builtins.rs | 21 ++ tests/run/asm.rs | 1 - tests/run/core-float.rs | 78 ++++++ 34 files changed, 726 insertions(+), 206 deletions(-) create mode 100644 tests/compile/asm_nul_byte.rs rename tests/{run => compile}/call-llvm-intrinsics.rs (91%) create mode 100644 tests/compile/fn_ptr_transmute_ignored_arg.rs create mode 100644 tests/compile/global_asm_nul_byte.rs create mode 100644 tests/compile/log.rs create mode 100644 tests/compile/naked_asm_nul_byte.rs rename tests/{run => compile}/simd-ffi.rs (92%) create mode 100644 tests/lang_tests.rs delete mode 100644 tests/lang_tests_debug.rs delete mode 100644 tests/lang_tests_release.rs create mode 100644 tests/no_builtins/no_builtins.rs create mode 100644 tests/no_builtins/with_builtins.rs create mode 100644 tests/run/core-float.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 840c09409bba9..fa9535a3729c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,7 +101,7 @@ jobs: - name: Run y.sh cargo build run: | - ./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml + CARGO_PROFILE_DEV_LTO=no ./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml - name: Clean run: | @@ -119,7 +119,7 @@ jobs: - name: Run tests run: | - ./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} + ./y.sh test --release --clean --build-sysroot --no-builtins-tests ${{ matrix.commands }} duplicates: runs-on: ubuntu-24.04 diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index a2a932893054d..2c9e4950706b2 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -48,7 +48,9 @@ jobs: - name: Install libgccjit12 if: matrix.libgccjit_version.gcc == 'libgccjit12.so' - run: sudo apt-get install libgccjit-12-dev + run: | + sudo apt-get update + sudo apt-get install libgccjit-12-dev - name: Setup path to libgccjit if: matrix.libgccjit_version.gcc == 'libgccjit12.so' diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index 55b090894b4af..51b06039c885f 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -46,7 +46,9 @@ jobs: - name: Install packages # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. - run: sudo apt-get install ninja-build ripgrep llvm-14-tools libgccjit-12-dev + run: | + sudo apt-get update + sudo apt-get install ninja-build ripgrep llvm-14-tools libgccjit-12-dev - name: Setup path to libgccjit run: echo 'gcc-path = "/usr/lib/gcc/x86_64-linux-gnu/12"' > config.toml diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index c36db18ed4aaa..8ed3545ee7d3d 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -83,7 +83,7 @@ jobs: run: | ./y.sh prepare --only-libcore --cross ./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json - CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build -Zjson-target-spec --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json + CARGO_PROFILE_DEV_LTO=no CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build -Zjson-target-spec --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json ./y.sh clean all - name: Build @@ -110,7 +110,7 @@ jobs: vm_dir=$(pwd)/vm cd tests/hello-world - CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu + CARGO_PROFILE_DEV_LTO=no CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu sudo cp target/m68k-unknown-linux-gnu/debug/hello_world $vm_dir/home/ sudo chroot $vm_dir qemu-m68k-static /home/hello_world > hello_world_stdout expected_output="40" diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index a58728573168b..66f30b147b4c0 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -50,9 +50,11 @@ jobs: run: | mkdir intel-sde cd intel-sde - dir=sde-external-9.33.0-2024-01-07-lin + version=10.8.0-2026-03-15 + url_path=915934 + dir=sde-external-$version-lin file=$dir.tar.xz - wget https://downloadmirror.intel.com/813591/$file + wget https://downloadmirror.intel.com/$url_path/$file tar xvf $file sudo mkdir /usr/share/intel-sde sudo cp -r $dir/* /usr/share/intel-sde diff --git a/Cargo.toml b/Cargo.toml index 29af6a1fc4344..8956bd6948979 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,12 +9,8 @@ license = "MIT OR Apache-2.0" crate-type = ["dylib"] [[test]] -name = "lang_tests_debug" -path = "tests/lang_tests_debug.rs" -harness = false -[[test]] -name = "lang_tests_release" -path = "tests/lang_tests_release.rs" +name = "lang_tests" +path = "tests/lang_tests.rs" harness = false [features] diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 8189e6b39747a..3f02df8399554 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -43,6 +43,7 @@ fn get_runners() -> Runners { runners.insert("--extended-regex-tests", ("Run extended regex tests", extended_regex_tests)); runners.insert("--mini-tests", ("Run mini tests", mini_tests)); runners.insert("--cargo-tests", ("Run cargo tests", cargo_tests)); + runners.insert("--no-builtins-tests", ("Test #![no_builtins] attribute", no_builtins_tests)); runners } @@ -317,6 +318,65 @@ fn maybe_run_command_in_vm( Ok(()) } +/// Compile a source file to an object file and check if it contains a memset reference. +fn object_has_memset( + env: &Env, + args: &TestArg, + src_file: &str, + obj_file_name: &str, +) -> Result { + let cargo_target_dir = Path::new(&args.config_info.cargo_target_dir); + let obj_file = cargo_target_dir.join(obj_file_name); + let obj_file_str = obj_file.to_str().expect("obj_file to_str"); + + let mut command = args.config_info.rustc_command_vec(); + command.extend_from_slice(&[ + &src_file, + &"--emit", + &"obj", + &"-O", + &"--target", + &args.config_info.target_triple, + &"-o", + ]); + command.push(&obj_file_str); + run_command_with_env(&command, None, Some(env))?; + + let nm_output = run_command_with_env(&[&"nm", &obj_file_str], None, Some(env))?; + let nm_stdout = String::from_utf8_lossy(&nm_output.stdout); + + Ok(nm_stdout.contains("memset")) +} + +fn no_builtins_tests(env: &Env, args: &TestArg) -> Result<(), String> { + // Test that the #![no_builtins] attribute prevents GCC from replacing + // code patterns (like loops) with calls to builtins (like memset). + // See https://github.com/rust-lang/rustc_codegen_gcc/issues/570 + + // Test 1: WITH #![no_builtins] - memset should NOT be present + println!("[TEST] no_builtins attribute (with #![no_builtins])"); + let has_memset = + object_has_memset(env, args, "tests/no_builtins/no_builtins.rs", "no_builtins_test.o")?; + if has_memset { + return Err("no_builtins test FAILED: Found 'memset' in object file.\n\ + The #![no_builtins] attribute should prevent GCC from replacing \n\ + code patterns with builtin calls." + .to_string()); + } + + // Test 2: WITHOUT #![no_builtins] - memset SHOULD be present + println!("[TEST] no_builtins attribute (without #![no_builtins])"); + let has_memset = + object_has_memset(env, args, "tests/no_builtins/with_builtins.rs", "with_builtins_test.o")?; + if !has_memset { + return Err("no_builtins test FAILED: 'memset' NOT found in object file.\n\ + Without #![no_builtins], GCC should replace the loop with memset." + .to_string()); + } + + Ok(()) +} + fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { let cargo_target_dir = Path::new(&args.config_info.cargo_target_dir); // FIXME: create a function "display_if_not_quiet" or something along the line. @@ -1248,6 +1308,7 @@ fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { test_libcore(env, args)?; extended_sysroot_tests(env, args)?; cargo_tests(env, args)?; + no_builtins_tests(env, args)?; test_rustc(env, args)?; Ok(()) diff --git a/example/mini_core.rs b/example/mini_core.rs index 87b059526ea0e..481fe5387e149 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -15,6 +15,30 @@ #![no_core] #![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)] +#[lang = "pointee_trait"] +pub trait Pointee: PointeeSized { + #[lang = "metadata_type"] + // needed so that layout_of will return `TooGeneric` instead of `Unknown` + // when asked for the layout of `*const T`. Which is important for making + // transmutes between raw pointers (and especially pattern types of raw pointers) + // work. + type Metadata: Copy + Sync + Unpin + Freeze; +} + +#[lang = "dyn_metadata"] +pub struct DynMetadata { + _vtable_ptr: NonNull, + _phantom: PhantomData, +} + +unsafe extern "C" { + /// Opaque type for accessing vtables. + /// + /// Private implementation detail of `DynMetadata::size_of` etc. + /// There is conceptually not actually any Abstract Machine memory behind this pointer. + type VTable; +} + #[no_mangle] unsafe extern "C" fn _Unwind_Resume() { intrinsics::unreachable(); @@ -113,7 +137,7 @@ unsafe impl<'a, T: PointeeSized> Sync for &'a T {} unsafe impl Sync for [u8; 16] {} #[lang = "freeze"] -unsafe auto trait Freeze {} +pub unsafe auto trait Freeze {} unsafe impl Freeze for PhantomData {} unsafe impl Freeze for *const T {} @@ -592,6 +616,13 @@ macro_rules! pattern_type { }; } +impl CoerceUnsized for pattern_type!(*const T is !null) where + T: Unsize +{ +} + +impl, U> DispatchFromDyn for pattern_type!(T is !null) {} + impl CoerceUnsized> for NonNull where T: Unsize {} impl DispatchFromDyn> for NonNull where T: Unsize {} @@ -604,9 +635,9 @@ impl CoerceUnsized> for Unique wh impl DispatchFromDyn> for Unique where T: Unsize {} #[lang = "owned_box"] -pub struct Box(Unique, A); +pub struct Box(Unique, A); -impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} +impl, U: ?Sized> CoerceUnsized> for Box {} impl Box { pub fn new(val: T) -> Box { @@ -614,16 +645,27 @@ impl Box { let size = 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) + Box( + Unique { + pointer: NonNull(intrinsics::transmute::< + *mut u8, + pattern_type!(*const T is !null), + >(ptr)), + _marker: PhantomData, + }, + Global, + ) } } } -impl Drop for Box { +impl Drop for Box { fn drop(&mut self) { - // inner value is dropped by compiler. + // inner value is dropped by compiler unsafe { - libc::free(self.0.pointer.0 as *mut u8); + libc::free(intrinsics::transmute::( + self.0.pointer.0, + ) as *mut u8); } } } diff --git a/libgccjit.version b/libgccjit.version index abc967702fb0e..5eef70260466f 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -efdd0a7290c22f5438d7c5380105d353ee3e8518 +6f155cc3f5a2dff33afe6cc3ed6c2e0e605ae6a3 diff --git a/rust-toolchain b/rust-toolchain index 655fa6abbab2b..56fcfdff1c719 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-02-14" +channel = "nightly-2026-04-29" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/abi.rs b/src/abi.rs index 8277231f16a54..2f5c555b702a4 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -224,15 +224,8 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { // FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`? - let FnAbiGcc { return_type, arguments_type, is_c_variadic, on_stack_param_indices, .. } = - self.gcc_type(cx); - let pointer_type = - cx.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic); - cx.on_stack_params.borrow_mut().insert( - pointer_type.dyncast_function_ptr_type().expect("function ptr type"), - on_stack_param_indices, - ); - pointer_type + let FnAbiGcc { return_type, arguments_type, is_c_variadic, .. } = self.gcc_type(cx); + cx.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic) } #[cfg(feature = "master")] diff --git a/src/asm.rs b/src/asm.rs index 1443aa925f741..5bb65365ad6ad 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -12,13 +12,13 @@ use rustc_codegen_ssa::traits::{ }; use rustc_middle::bug; use rustc_middle::ty::Instance; -use rustc_span::Span; +use rustc_span::{DUMMY_SP, Span}; use rustc_target::asm::*; use crate::builder::Builder; use crate::callee::get_fn; use crate::context::CodegenCx; -use crate::errors::UnwindingInlineAsm; +use crate::errors::{NulBytesInAsm, UnwindingInlineAsm}; use crate::type_of::LayoutGccExt; // Rust asm! and GCC Extended Asm semantics differ substantially. @@ -530,8 +530,15 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { template_str.push_str(INTEL_SYNTAX_INS); } - // 4. Generate Extended Asm block + // NOTE: GCC's extended asm uses CString which cannot contain nul bytes. + // Emit an error if there are any nul bytes in the template string. + if template_str.contains('\0') { + let err_sp = span.first().copied().unwrap_or(DUMMY_SP); + self.sess().dcx().emit_err(NulBytesInAsm { span: err_sp }); + return; + } + // 4. Generate Extended Asm block let block = self.llbb(); let extended_asm = if let Some(dest) = dest { assert!(!labels.is_empty()); @@ -875,7 +882,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, - _line_spans: &[Span], + line_spans: &[Span], ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -942,6 +949,13 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } // NOTE: seems like gcc will put the asm in the wrong section, so set it to .text manually. template_str.push_str("\n.popsection"); + // NOTE: GCC's add_top_level_asm uses CString which cannot contain nul bytes. + // Emit an error if there are any nul bytes in the template string. + if template_str.contains('\0') { + let span = line_spans.first().copied().unwrap_or(DUMMY_SP); + self.tcx.dcx().emit_err(NulBytesInAsm { span }); + return; + } self.context.add_top_level_asm(None, &template_str); } diff --git a/src/base.rs b/src/base.rs index 7d63f430af685..7658b86a3a200 100644 --- a/src/base.rs +++ b/src/base.rs @@ -8,7 +8,8 @@ use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::DebugInfoCodegenMethods; -use rustc_hir::attrs::Linkage; +use rustc_hir::attrs::{AttributeKind, Linkage}; +use rustc_hir::find_attr; use rustc_middle::dep_graph; #[cfg(feature = "master")] use rustc_middle::mono::Visibility; @@ -137,6 +138,17 @@ pub fn compile_codegen_unit( // NOTE: Rust relies on LLVM doing wrapping on overflow. context.add_command_line_option("-fwrapv"); + // NOTE: We need to honor the `#![no_builtins]` attribute to prevent GCC from + // replacing code patterns (like loops) with calls to builtins (like memset). + // The `-fno-tree-loop-distribute-patterns` flag disables the loop distribution pass + // that transforms loops into calls to library functions (memset, memcpy, etc.). + // See GCC handling for more details: + // https://github.com/rust-lang/gcc/blob/efdd0a7290c22f5438d7c5380105d353ee3e8518/gcc/c-family/c-opts.cc#L953 + let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID); + if find_attr!(crate_attrs, AttributeKind::NoBuiltins) { + context.add_command_line_option("-fno-tree-loop-distribute-patterns"); + } + if let Some(model) = tcx.sess.code_model() { use rustc_target::spec::CodeModel; diff --git a/src/builder.rs b/src/builder.rs index 3cffd862b9b98..459f623a7c881 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -33,6 +33,7 @@ use rustc_span::def_id::DefId; use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; +use crate::abi::FnAbiGccExt; use crate::common::{SignType, TypeReflection, type_is_pointer}; use crate::context::CodegenCx; use crate::errors; @@ -213,6 +214,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { _typ: &str, func_ptr: RValue<'gcc>, args: &'b [RValue<'gcc>], + on_stack_param_indices: &FxHashSet, ) -> Cow<'b, [RValue<'gcc>]> { let mut all_args_match = true; let mut param_types = vec![]; @@ -225,11 +227,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { param_types.push(param); } - let mut on_stack_param_indices = FxHashSet::default(); - if let Some(indices) = self.on_stack_params.borrow().get(&gcc_func) { - on_stack_param_indices.clone_from(indices); - } - if all_args_match { return Cow::Borrowed(args); } @@ -351,19 +348,24 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn function_ptr_call( &mut self, typ: Type<'gcc>, + fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, 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"); + let func_ptr_type = { + let func_ptr_type = func_ptr.get_type(); + if func_ptr_type != typ { func_ptr = self.context.new_cast(self.location, func_ptr, typ); - new_func_type + typ + } else { + func_ptr_type } }; + let gcc_func = func_ptr_type.dyncast_function_ptr_type().expect("function ptr"); + let on_stack_param_indices = fn_abi + .map(|fn_abi| fn_abi.gcc_type(self.cx).on_stack_param_indices) + .unwrap_or_default(); let func_name = format!("{:?}", func_ptr); let previous_arg_count = args.len(); let orig_args = args; @@ -372,7 +374,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { llvm::adjust_intrinsic_arguments(self, gcc_func, args.into(), &func_name) }; let args_adjusted = args.len() != previous_arg_count; - let args = self.check_ptr_call("call", func_ptr, &args); + let args = self.check_ptr_call("call", func_ptr, &args, &on_stack_param_indices); // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). @@ -599,7 +601,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { &mut self, typ: Type<'gcc>, fn_attrs: Option<&CodegenFnAttrs>, - _fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, + fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, @@ -611,7 +613,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let current_block = self.block; self.block = try_block; - let call = self.call(typ, fn_attrs, None, func, args, None, instance); // FIXME(antoyo): use funclet here? + let call = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); // FIXME(antoyo): use funclet here? self.block = current_block; let return_value = @@ -645,7 +647,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _funclet: Option<&Funclet>, instance: Option>, ) -> RValue<'gcc> { - let call_site = self.call(typ, fn_attrs, None, func, args, None, instance); + let call_site = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); let condition = self.context.new_rvalue_from_int(self.bool_type, 1); self.llbb().end_with_conditional(self.location, condition, then, catch); if let Some(_fn_abi) = fn_abi { @@ -1773,7 +1775,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.function_call(func, args, funclet) } else { // If it's a not function that was defined, it's a function pointer. - self.function_ptr_call(typ, func, args, funclet) + self.function_ptr_call(typ, fn_abi, func, args, funclet) }; if let Some(_fn_abi) = fn_abi { // FIXME(bjorn3): Apply function attributes diff --git a/src/context.rs b/src/context.rs index c7a2b92ac139c..e0810a35b040b 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,9 +1,7 @@ use std::cell::{Cell, RefCell}; use std::collections::HashMap; -use gccjit::{ - Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, Location, RValue, Type, -}; +use gccjit::{Block, CType, Context, Function, FunctionType, LValue, Location, RValue, Type}; use rustc_abi::{Align, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::errors as ssa_errors; @@ -100,8 +98,6 @@ pub struct CodegenCx<'gcc, 'tcx> { RefCell, Option>), RValue<'gcc>>>, // FIXME(antoyo): improve the SSA API to not require those. - /// Mapping from function pointer type to indexes of on stack parameters. - pub on_stack_params: RefCell, FxHashSet>>, /// Mapping from function to indexes of on stack parameters. pub on_stack_function_params: RefCell, FxHashSet>>, @@ -289,7 +285,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { instances: Default::default(), function_instances: Default::default(), intrinsic_instances: Default::default(), - on_stack_params: Default::default(), on_stack_function_params: Default::default(), vtables: Default::default(), const_globals: Default::default(), diff --git a/src/errors.rs b/src/errors.rs index f5815e7233928..de633d3bdde79 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -23,3 +23,10 @@ pub(crate) struct LtoBitcodeFromRlib { #[derive(Diagnostic)] #[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")] pub(crate) struct ExplicitTailCallsUnsupported; + +#[derive(Diagnostic)] +#[diag("asm contains a NUL byte")] +pub(crate) struct NulBytesInAsm { + #[primary_span] + pub span: Span, +} diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 60e007a25c68e..d58697f1bf270 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1589,6 +1589,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.tileloaddrst164" => "__builtin_trap", "llvm.x86.tilezero" => "__builtin_trap", "llvm.x86.tilemovrow" => "__builtin_trap", + "llvm.x86.tilemovrowi" => "__builtin_trap", "llvm.x86.tdpbhf8ps" => "__builtin_trap", "llvm.x86.tdphbf8ps" => "__builtin_trap", "llvm.x86.tdpbf8ps" => "__builtin_trap", @@ -1603,6 +1604,9 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.tcvtrowps2phh" => "__builtin_trap", "llvm.x86.tcvtrowps2phl" => "__builtin_trap", "llvm.x86.tcvtrowd2ps" => "__builtin_trap", + "llvm.x86.tcvtrowd2psi" => "__builtin_trap", + "llvm.x86.tcvtrowps2phhi" => "__builtin_trap", + "llvm.x86.tcvtrowps2phli" => "__builtin_trap", "llvm.x86.tcmmimfp16ps" => "__builtin_trap", "llvm.x86.tcmmrlfp16ps" => "__builtin_trap", diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 2a7c88afe17dd..da0ef42ed894a 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,9 +4,7 @@ mod simd; #[cfg(feature = "master")] use std::iter; -#[cfg(feature = "master")] -use gccjit::Type; -use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; +use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; @@ -38,6 +36,22 @@ use crate::context::CodegenCx; use crate::intrinsic::simd::generic_simd_intrinsic; use crate::type_of::LayoutGccExt; +fn float_intrinsic<'gcc, 'tcx>( + cx: &CodegenCx<'gcc, 'tcx>, + typ: Type<'gcc>, + name: &str, +) -> Option> { + // GCC doesn't have the intrinsic we want so we use the compiler-builtins one + Some(cx.context.new_function( + None, + FunctionType::Extern, + typ, + &[cx.context.new_parameter(None, typ, "a"), cx.context.new_parameter(None, typ, "b")], + name, + false, + )) +} + fn get_simple_intrinsic<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, name: Symbol, @@ -68,48 +82,19 @@ fn get_simple_intrinsic<'gcc, 'tcx>( // FIXME: calling `fma` from libc without FMA target feature uses expensive software emulation sym::fmuladdf32 => "fmaf", // FIXME: use gcc intrinsic analogous to llvm.fmuladd.f32 sym::fmuladdf64 => "fma", // FIXME: use gcc intrinsic analogous to llvm.fmuladd.f64 - sym::minimumf32 => "fminimumf", - sym::minimumf64 => "fminimum", - sym::minimumf128 => { - // GCC doesn't have the intrinsic we want so we use the compiler-builtins one - // https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fminimumf128.html - let f128_type = cx.type_f128(); - return Some(cx.context.new_function( - None, - FunctionType::Extern, - f128_type, - &[ - cx.context.new_parameter(None, f128_type, "a"), - cx.context.new_parameter(None, f128_type, "b"), - ], - "fminimumf128", - false, - )); - } - sym::maximumf32 => "fmaximumf", - sym::maximumf64 => "fmaximum", - sym::maximumf128 => { - // GCC doesn't have the intrinsic we want so we use the compiler-builtins one - // https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fmaximumf128.html - let f128_type = cx.type_f128(); - return Some(cx.context.new_function( - None, - FunctionType::Extern, - f128_type, - &[ - cx.context.new_parameter(None, f128_type, "a"), - cx.context.new_parameter(None, f128_type, "b"), - ], - "fmaximumf128", - false, - )); - } + sym::minimumf32 => return float_intrinsic(cx, cx.type_f32(), "fminimumf"), + sym::minimumf64 => return float_intrinsic(cx, cx.type_f64(), "fminimum"), + sym::minimumf128 => return float_intrinsic(cx, cx.type_f128(), "fminimumf128"), + sym::maximumf32 => return float_intrinsic(cx, cx.type_f32(), "fmaximumf"), + sym::maximumf64 => return float_intrinsic(cx, cx.type_f64(), "fmaximum"), + sym::maximumf128 => return float_intrinsic(cx, cx.type_f128(), "fmaximumf128"), sym::copysignf32 => "copysignf", sym::copysignf64 => "copysign", sym::floorf32 => "floorf", sym::floorf64 => "floor", sym::ceilf32 => "ceilf", sym::ceilf64 => "ceil", + sym::powf128 => return float_intrinsic(cx, cx.type_f128(), "powf128"), sym::truncf32 => "truncf", sym::truncf64 => "trunc", // We match the LLVM backend and lower this to `rint`. @@ -123,72 +108,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>( Some(cx.context.get_builtin_function(gcc_name)) } -// FIXME(antoyo): We can probably remove these and use the fallback intrinsic implementation. -fn get_simple_function<'gcc, 'tcx>( - cx: &CodegenCx<'gcc, 'tcx>, - name: Symbol, -) -> Option> { - let (return_type, parameters, func_name) = match name { - sym::minimumf32 => { - let parameters = [ - cx.context.new_parameter(None, cx.float_type, "a"), - cx.context.new_parameter(None, cx.float_type, "b"), - ]; - (cx.float_type, parameters, "fminimumf") - } - sym::minimumf64 => { - let parameters = [ - cx.context.new_parameter(None, cx.double_type, "a"), - cx.context.new_parameter(None, cx.double_type, "b"), - ]; - (cx.double_type, parameters, "fminimum") - } - sym::minimumf128 => { - let f128_type = cx.type_f128(); - // GCC doesn't have the intrinsic we want so we use the compiler-builtins one - // https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fminimumf128.html - let parameters = [ - cx.context.new_parameter(None, f128_type, "a"), - cx.context.new_parameter(None, f128_type, "b"), - ]; - (f128_type, parameters, "fminimumf128") - } - sym::maximumf32 => { - let parameters = [ - cx.context.new_parameter(None, cx.float_type, "a"), - cx.context.new_parameter(None, cx.float_type, "b"), - ]; - (cx.float_type, parameters, "fmaximumf") - } - sym::maximumf64 => { - let parameters = [ - cx.context.new_parameter(None, cx.double_type, "a"), - cx.context.new_parameter(None, cx.double_type, "b"), - ]; - (cx.double_type, parameters, "fmaximum") - } - sym::maximumf128 => { - let f128_type = cx.type_f128(); - // GCC doesn't have the intrinsic we want so we use the compiler-builtins one - // https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fmaximumf128.html - let parameters = [ - cx.context.new_parameter(None, f128_type, "a"), - cx.context.new_parameter(None, f128_type, "b"), - ]; - (f128_type, parameters, "fmaximumf128") - } - _ => return None, - }; - Some(cx.context.new_function( - None, - FunctionType::Extern, - return_type, - ¶meters, - func_name, - false, - )) -} - fn get_simple_function_f128<'gcc, 'tcx>( span: Span, cx: &CodegenCx<'gcc, 'tcx>, @@ -198,7 +117,12 @@ fn get_simple_function_f128<'gcc, 'tcx>( let func_name = match name { sym::ceilf128 => "ceilf128", sym::fabs => "fabsf128", + sym::expf128 => "expf128", + sym::exp2f128 => "exp2f128", sym::floorf128 => "floorf128", + sym::logf128 => "logf128", + sym::log2f128 => "log2f128", + sym::log10f128 => "log10f128", sym::truncf128 => "truncf128", sym::roundf128 => "roundf128", sym::round_ties_even_f128 => "roundevenf128", @@ -215,6 +139,24 @@ fn get_simple_function_f128<'gcc, 'tcx>( ) } +fn generic_f16_builtin<'gcc, 'tcx>( + cx: &CodegenCx<'gcc, 'tcx>, + name: Symbol, + args: &[OperandRef<'tcx, RValue<'gcc>>], +) -> RValue<'gcc> { + let f32_type = cx.type_f32(); + let builtin_name = match name { + sym::fabs => "fabsf", + _ => unreachable!(), + }; + + let func = cx.context.get_builtin_function(builtin_name); + let args: Vec<_> = + args.iter().map(|arg| cx.context.new_cast(None, arg.immediate(), f32_type)).collect(); + let result = cx.context.new_call(None, func, &args); + cx.context.new_cast(None, result, cx.type_f16()) +} + fn f16_builtin<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, name: Symbol, @@ -224,17 +166,15 @@ fn f16_builtin<'gcc, 'tcx>( let builtin_name = match name { sym::ceilf16 => "__builtin_ceilf", sym::copysignf16 => "__builtin_copysignf", + sym::expf16 => "expf", + sym::exp2f16 => "exp2f", sym::fabs => "fabsf", sym::floorf16 => "__builtin_floorf", sym::fmaf16 => "fmaf", + sym::logf16 => "logf", + sym::log2f16 => "log2f", + sym::log10f16 => "log10f", sym::powf16 => "__builtin_powf", - sym::powif16 => { - let func = cx.context.get_builtin_function("__builtin_powif"); - let arg0 = cx.context.new_cast(None, args[0].immediate(), f32_type); - let args = [arg0, args[1].immediate()]; - let result = cx.context.new_call(None, func, &args); - return cx.context.new_cast(None, result, cx.type_f16()); - } sym::roundf16 => "__builtin_roundf", sym::round_ties_even_f16 => "__builtin_rintf", sym::sqrtf16 => "__builtin_sqrtf", @@ -264,7 +204,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let fn_args = instance.args; let simple = get_simple_intrinsic(self, name); - let simple_func = get_simple_function(self, name); let value = match name { _ if simple.is_some() => { @@ -275,8 +214,26 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc &args.iter().map(|arg| arg.immediate()).collect::>(), ) } - _ if simple_func.is_some() => { - let func = simple_func.expect("simple function"); + // TODO(antoyo): We can probably remove these and use the fallback intrinsic implementation. + sym::minimumf32 | sym::minimumf64 | sym::maximumf32 | sym::maximumf64 => { + let (ty, func_name) = match name { + sym::minimumf32 => (self.cx.float_type, "fminimumf"), + sym::maximumf32 => (self.cx.float_type, "fmaximumf"), + sym::minimumf64 => (self.cx.double_type, "fminimum"), + sym::maximumf64 => (self.cx.double_type, "fmaximum"), + _ => unreachable!(), + }; + let func = self.cx.context.new_function( + None, + FunctionType::Extern, + ty, + &[ + self.cx.context.new_parameter(None, ty, "a"), + self.cx.context.new_parameter(None, ty, "b"), + ], + func_name, + false, + ); self.cx.context.new_call( self.location, func, @@ -285,10 +242,14 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::ceilf16 | sym::copysignf16 + | sym::expf16 + | sym::exp2f16 | sym::floorf16 | sym::fmaf16 + | sym::logf16 + | sym::log2f16 + | sym::log10f16 | sym::powf16 - | sym::powif16 | sym::roundf16 | sym::round_ties_even_f16 | sym::sqrtf16 @@ -299,6 +260,11 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc | sym::roundf128 | sym::round_ties_even_f128 | sym::sqrtf128 + | sym::expf128 + | sym::exp2f128 + | sym::logf128 + | sym::log2f128 + | sym::log10f128 if self.cx.supports_f128_type => { let func = get_simple_function_f128(span, self, name); @@ -347,6 +313,13 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc &args.iter().map(|arg| arg.immediate()).collect::>(), ) } + sym::powif16 => { + let func = self.cx.context.get_builtin_function("__builtin_powif"); + let arg0 = self.cx.context.new_cast(None, args[0].immediate(), self.cx.type_f32()); + let args = [arg0, args[1].immediate()]; + let result = self.cx.context.new_call(None, func, &args); + self.cx.context.new_cast(None, result, self.cx.type_f16()) + } sym::powif128 => { let f128_type = self.cx.type_f128(); let func = self.cx.context.new_function( @@ -490,7 +463,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc span_bug!(span, "expected float type for fabs intrinsic: {:?}", ty); }; let func = match float_ty { - ty::FloatTy::F16 => break 'fabs f16_builtin(self, name, args), + ty::FloatTy::F16 => break 'fabs generic_f16_builtin(self, name, args), ty::FloatTy::F32 => self.context.get_builtin_function("fabsf"), ty::FloatTy::F64 => self.context.get_builtin_function("fabs"), ty::FloatTy::F128 => get_simple_function_f128(span, self, name), diff --git a/tests/compile/asm_nul_byte.rs b/tests/compile/asm_nul_byte.rs new file mode 100644 index 0000000000000..fd5a4f98aa27f --- /dev/null +++ b/tests/compile/asm_nul_byte.rs @@ -0,0 +1,15 @@ +// Compiler: +// status: error +// stderr: +// error: asm contains a NUL byte +// ... + +// Test that inline asm containing a NUL byte emits an error. + +use std::arch::asm; + +fn main() { + unsafe { + asm!("\0"); + } +} diff --git a/tests/run/call-llvm-intrinsics.rs b/tests/compile/call-llvm-intrinsics.rs similarity index 91% rename from tests/run/call-llvm-intrinsics.rs rename to tests/compile/call-llvm-intrinsics.rs index 86e041c3a2fbe..4c790994c777e 100644 --- a/tests/run/call-llvm-intrinsics.rs +++ b/tests/compile/call-llvm-intrinsics.rs @@ -1,12 +1,10 @@ // Compiler: -// -// Run-time: -// status: 0 // FIXME: Remove this test once rustc's `./tests/codegen/riscv-abi/call-llvm-intrinsics.rs` // stops ignoring GCC backend. #![feature(link_llvm_intrinsics)] +#![crate_type = "lib"] #![allow(internal_features)] struct A; @@ -32,7 +30,3 @@ pub fn do_call() { sqrt(4.0); } } - -fn main() { - do_call(); -} diff --git a/tests/compile/fn_ptr_transmute_ignored_arg.rs b/tests/compile/fn_ptr_transmute_ignored_arg.rs new file mode 100644 index 0000000000000..a4947da248e29 --- /dev/null +++ b/tests/compile/fn_ptr_transmute_ignored_arg.rs @@ -0,0 +1,12 @@ +// Compiler: + +// Regression test for + +#![crate_type = "lib"] + +#[unsafe(no_mangle)] +extern "C" fn third(_a: usize, b: usize, c: usize) { + let throw_away_f: fn((), usize, usize) = + unsafe { std::mem::transmute(third as extern "C" fn(_, _, _)) }; + throw_away_f((), 2, 3) +} diff --git a/tests/compile/global_asm_nul_byte.rs b/tests/compile/global_asm_nul_byte.rs new file mode 100644 index 0000000000000..12d647c733f21 --- /dev/null +++ b/tests/compile/global_asm_nul_byte.rs @@ -0,0 +1,13 @@ +// Compiler: +// status: error +// stderr: +// error: asm contains a NUL byte +// ... + +// Test that global_asm containing a NUL byte emits an error. + +#![crate_type = "lib"] + +use std::arch::global_asm; + +global_asm!("\0"); diff --git a/tests/compile/log.rs b/tests/compile/log.rs new file mode 100644 index 0000000000000..56758b0d3e53f --- /dev/null +++ b/tests/compile/log.rs @@ -0,0 +1,12 @@ +// Compiler: + +extern "C" { + fn log(message_data: u32, message_size: u32); +} + +pub fn main() { + let message = "Hello, world!"; + unsafe { + log(message.as_ptr() as u32, message.len() as u32); + } +} diff --git a/tests/compile/naked_asm_nul_byte.rs b/tests/compile/naked_asm_nul_byte.rs new file mode 100644 index 0000000000000..85be3704a5e05 --- /dev/null +++ b/tests/compile/naked_asm_nul_byte.rs @@ -0,0 +1,17 @@ +// Compiler: +// status: error +// stderr: +// ... +// error: asm contains a NUL byte +// ... + +// Test that naked_asm containing a NUL byte emits an error. + +#![crate_type = "lib"] + +use std::arch::naked_asm; + +#[unsafe(naked)] +pub extern "C" fn nul_byte_naked() { + naked_asm!("\0") +} diff --git a/tests/run/simd-ffi.rs b/tests/compile/simd-ffi.rs similarity index 92% rename from tests/run/simd-ffi.rs rename to tests/compile/simd-ffi.rs index 67cc2e5b96e3f..56172ddc7c643 100644 --- a/tests/run/simd-ffi.rs +++ b/tests/compile/simd-ffi.rs @@ -1,12 +1,11 @@ // Compiler: -// -// Run-time: -// status: 0 // FIXME: Remove this test once stops // ignoring GCC backend. #![allow(internal_features, non_camel_case_types)] +#![crate_type = "lib"] + // we can compile to a variety of platforms, because we don't need // cross-compiled standard libraries. #![feature(no_core, auto_traits)] @@ -93,10 +92,3 @@ macro_rules! Copy { macro_rules! derive { () => {}; } - -#[lang = "start"] -fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { - 0 -} - -fn main() {} diff --git a/tests/failing-lto-tests.txt b/tests/failing-lto-tests.txt index c45fc0776588e..4c62c35a512c1 100644 --- a/tests/failing-lto-tests.txt +++ b/tests/failing-lto-tests.txt @@ -1,4 +1,3 @@ -tests/ui/lto/all-crates.rs tests/ui/lto/debuginfo-lto-alloc.rs tests/ui/panic-runtime/lto-unwind.rs tests/ui/uninhabited/uninhabited-transparent-return-abi.rs diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 8589929d2fbc3..e8a26a90890c1 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -47,7 +47,6 @@ tests/ui/sanitizer/cfi/virtual-auto.rs tests/ui/sanitizer/cfi/sized-associated-ty.rs tests/ui/sanitizer/cfi/can-reveal-opaques.rs tests/ui/sanitizer/kcfi-mangling.rs -tests/ui/backtrace/dylib-dep.rs tests/ui/delegation/fn-header.rs tests/ui/consts/const-eval/parse_ints.rs tests/ui/simd/intrinsic/generic-as.rs @@ -99,3 +98,16 @@ tests/ui/eii/privacy1.rs tests/ui/eii/default/call_impl.rs tests/ui/c-variadic/copy.rs tests/ui/asm/x86_64/global_asm_escape.rs +tests/ui/lto/all-crates.rs +tests/ui/consts/const-eval/c-variadic.rs +tests/ui/eii/default/call_default_panics.rs +tests/ui/explicit-tail-calls/indirect.rs +tests/ui/traits/inheritance/self-in-supertype.rs +tests/ui/fmt/fmt_debug/shallow.rs +tests/ui/c-variadic/roundtrip.rs +tests/ui/eii/eii_impl_with_contract.rs +tests/ui/eii/static/cross_crate_decl.rs +tests/ui/eii/static/cross_crate_def.rs +tests/ui/eii/static/same_address.rs +tests/ui/eii/static/simple.rs +tests/ui/explicit-tail-calls/default-trait-method.rs diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs new file mode 100644 index 0000000000000..3d1d04661c8ca --- /dev/null +++ b/tests/lang_tests.rs @@ -0,0 +1,237 @@ +#![allow(clippy::uninlined_format_args)] + +use std::env::current_dir; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use lang_tester::LangTester; +use tempfile::TempDir; + +fn compile_and_run_cmds( + compiler_args: Vec, + test_target: &Option, + exe: &Path, + test_mode: TestMode, +) -> Vec<(&'static str, Command)> { + let mut compiler = Command::new("rustc"); + compiler.args(compiler_args); + + // Test command 2: run `tempdir/x`. + if test_target.is_some() { + let mut env_path = std::env::var("PATH").unwrap_or_default(); + // TODO(antoyo): find a better way to add the PATH necessary locally. + env_path = format!("/opt/m68k-unknown-linux-gnu/bin:{}", env_path); + compiler.env("PATH", env_path); + + let mut commands = vec![("Compiler", compiler)]; + if test_mode.should_run() { + let vm_parent_dir = std::env::var("CG_GCC_VM_DIR") + .map(PathBuf::from) + .unwrap_or_else(|_| std::env::current_dir().unwrap()); + let vm_dir = "vm"; + let exe_filename = exe.file_name().unwrap(); + let vm_home_dir = vm_parent_dir.join(vm_dir).join("home"); + let vm_exe_path = vm_home_dir.join(exe_filename); + // FIXME(antoyo): panicking here makes the test pass. + let inside_vm_exe_path = PathBuf::from("/home").join(exe_filename); + + let mut copy = Command::new("sudo"); + copy.arg("cp"); + copy.args([exe, &vm_exe_path]); + + let mut runtime = Command::new("sudo"); + runtime.args(["chroot", vm_dir, "qemu-m68k-static"]); + runtime.arg(inside_vm_exe_path); + runtime.current_dir(vm_parent_dir); + + commands.push(("Copy", copy)); + commands.push(("Run-time", runtime)); + } + commands + } else { + let mut commands = vec![("Compiler", compiler)]; + if test_mode.should_run() { + let runtime = Command::new(exe); + commands.push(("Run-time", runtime)); + } + commands + } +} + +#[derive(Clone, Copy)] +enum BuildMode { + Debug, + Release, +} + +impl BuildMode { + fn is_debug(self) -> bool { + matches!(self, Self::Debug) + } +} + +#[derive(Clone, Copy)] +enum TestMode { + Compile, + CompileAndRun, +} + +impl TestMode { + fn should_run(self) -> bool { + matches!(self, Self::CompileAndRun) + } +} + +fn build_test_runner( + tempdir: PathBuf, + current_dir: String, + build_mode: BuildMode, + test_kind: &str, + test_dir: &str, + test_mode: TestMode, + files_to_ignore_on_m68k: &'static [&'static str], +) { + fn rust_filter(path: &Path) -> bool { + path.is_file() && path.extension().expect("extension").to_str().expect("to_str") == "rs" + } + + #[cfg(feature = "master")] + fn filter(filename: &Path) -> bool { + rust_filter(filename) + } + + #[cfg(not(feature = "master"))] + fn filter(filename: &Path) -> bool { + if let Some(filename) = filename.to_str() + && filename.ends_with("gep.rs") + { + return false; + } + rust_filter(filename) + } + + println!("=== {test_kind} tests ==="); + + // TODO(antoyo): find a way to send this via a cli argument. + let test_target = std::env::var("CG_GCC_TEST_TARGET").ok(); + let test_target_filter = test_target.clone(); + + LangTester::new() + .test_dir(test_dir) + .test_path_filter(move |filename| { + if !filter(filename) { + return false; + } + if test_target_filter.is_some() + && let Some(filename) = filename.file_name() + && let Some(filename) = filename.to_str() + && files_to_ignore_on_m68k.contains(&filename) + { + return false; + } + true + }) + .test_extract(|path| { + std::fs::read_to_string(path) + .expect("read file") + .lines() + .skip_while(|l| !l.starts_with("//")) + .take_while(|l| l.starts_with("//")) + .map(|l| &l[2..]) + .collect::>() + .join("\n") + }) + .test_cmds(move |path| { + // Test command 1: Compile `x.rs` into `tempdir/x`. + let mut exe = PathBuf::new(); + exe.push(&tempdir); + exe.push(path.file_stem().expect("file_stem")); + let mut compiler_args = vec![ + format!("-Zcodegen-backend={}/target/debug/librustc_codegen_gcc.so", current_dir), + "--sysroot".into(), + format!("{}/build/build_sysroot/sysroot/", current_dir), + "-C".into(), + "link-arg=-lc".into(), + "--extern".into(), + "mini_core=target/out/libmini_core.rlib".into(), + "-o".into(), + exe.to_str().expect("to_str").into(), + path.to_str().expect("to_str").into(), + ]; + + if let Some(ref target) = test_target { + compiler_args.extend_from_slice(&["--target".into(), target.into()]); + + let linker = format!("{}-gcc", target); + compiler_args.push(format!("-Clinker={}", linker)); + } + + if let Some(flags) = option_env!("TEST_FLAGS") { + for flag in flags.split_whitespace() { + compiler_args.push(flag.into()); + } + } + + if build_mode.is_debug() { + compiler_args + .extend_from_slice(&["-C".to_string(), "llvm-args=sanitize-undefined".into()]); + if test_target.is_none() { + // m68k doesn't have lubsan for now + compiler_args.extend_from_slice(&["-C".into(), "link-args=-lubsan".into()]); + } + } else { + compiler_args.extend_from_slice(&[ + "-C".into(), + "opt-level=3".into(), + "-C".into(), + "lto=no".into(), + ]); + } + + compile_and_run_cmds(compiler_args, &test_target, &exe, test_mode) + }) + .run(); +} + +fn compile_tests(tempdir: PathBuf, current_dir: String) { + build_test_runner( + tempdir, + current_dir, + BuildMode::Debug, + "lang compile", + "tests/compile", + TestMode::Compile, + &["simd-ffi.rs", "asm_nul_byte.rs", "global_asm_nul_byte.rs", "naked_asm_nul_byte.rs"], + ); +} + +fn run_tests(tempdir: PathBuf, current_dir: String) { + build_test_runner( + tempdir.clone(), + current_dir.clone(), + BuildMode::Debug, + "[DEBUG] lang run", + "tests/run", + TestMode::CompileAndRun, + &[], + ); + build_test_runner( + tempdir, + current_dir.to_string(), + BuildMode::Release, + "[RELEASE] lang run", + "tests/run", + TestMode::CompileAndRun, + &[], + ); +} + +fn main() { + let tempdir = TempDir::new().expect("temp dir"); + let current_dir = current_dir().expect("current dir"); + let current_dir = current_dir.to_str().expect("current dir").to_string(); + + let tempdir_path: PathBuf = tempdir.as_ref().into(); + compile_tests(tempdir_path.clone(), current_dir.clone()); + run_tests(tempdir_path, current_dir); +} diff --git a/tests/lang_tests_debug.rs b/tests/lang_tests_debug.rs deleted file mode 100644 index 96bd74883ff0a..0000000000000 --- a/tests/lang_tests_debug.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod lang_tests_common; - -fn main() { - lang_tests_common::main_inner(lang_tests_common::Profile::Debug); -} diff --git a/tests/lang_tests_release.rs b/tests/lang_tests_release.rs deleted file mode 100644 index 35d5d60c33ee3..0000000000000 --- a/tests/lang_tests_release.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod lang_tests_common; - -fn main() { - lang_tests_common::main_inner(lang_tests_common::Profile::Release); -} diff --git a/tests/no_builtins/no_builtins.rs b/tests/no_builtins/no_builtins.rs new file mode 100644 index 0000000000000..c332581d93753 --- /dev/null +++ b/tests/no_builtins/no_builtins.rs @@ -0,0 +1,24 @@ +// Test that the #![no_builtins] attribute is honored. +// When this attribute is present, GCC should not replace code patterns +// (like loops) with calls to builtins (like memset). +// See https://github.com/rust-lang/rustc_codegen_gcc/issues/570 +// +// This test is verified by the build system test `--no-builtins-tests` which +// compiles this file and checks that `memset` is not referenced in the object file. + +#![no_std] +#![no_builtins] +#![crate_type = "lib"] + +// This function implements a byte-setting loop that GCC would typically +// optimize into a memset call. With #![no_builtins], GCC should preserve +// the loop instead of replacing it with a builtin call. +#[no_mangle] +#[inline(never)] +pub unsafe fn set_bytes(mut s: *mut u8, c: u8, n: usize) { + let end = s.add(n); + while s < end { + *s = c; + s = s.add(1); + } +} diff --git a/tests/no_builtins/with_builtins.rs b/tests/no_builtins/with_builtins.rs new file mode 100644 index 0000000000000..30271978a1b60 --- /dev/null +++ b/tests/no_builtins/with_builtins.rs @@ -0,0 +1,21 @@ +// Test that without #![no_builtins], GCC DOES replace code patterns with builtins. +// This is the counterpart to no_builtins.rs - we verify that memset IS emitted +// when the no_builtins attribute is NOT present. +// +// This test is verified by the build system test `--no-builtins-tests` which +// compiles this file and checks that `memset` IS referenced in the object file. + +#![no_std] +#![crate_type = "lib"] + +// This function implements a byte-setting loop that GCC should optimize +// into a memset call when no_builtins is NOT set. +#[no_mangle] +#[inline(never)] +pub unsafe fn set_bytes(mut s: *mut u8, c: u8, n: usize) { + let end = s.add(n); + while s < end { + *s = c; + s = s.add(1); + } +} diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 9b15a28d82988..01775c92ffc8a 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -213,7 +213,6 @@ fn asm() { core::arch::asm!( "", out("al") _, - out("bl") _, out("cl") _, out("dl") _, out("sil") _, diff --git a/tests/run/core-float.rs b/tests/run/core-float.rs new file mode 100644 index 0000000000000..195378b9d3c84 --- /dev/null +++ b/tests/run/core-float.rs @@ -0,0 +1,78 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// TODO: remove these tests (extracted from libcore) when we run the libcore tests in the CI of the +// Rust repo. + +#![feature(core_intrinsics)] + +use std::f32::consts; +use std::intrinsics; + +const EXP_APPROX: Float = 1e-6; +const ZERO: Float = 0.0; +const ONE: Float = 1.0; + +macro_rules! assert_biteq { + ($left:expr, $right:expr $(,)?) => {{ + let l = $left; + let r = $right; + + // Hack to coerce left and right to the same type + let mut _eq_ty = l; + _eq_ty = r; + + // Hack to get the width from a value + assert!(l.to_bits() == r.to_bits()); + }}; +} + +macro_rules! assert_approx_eq { + ($a:expr, $b:expr $(,)?) => {{ assert_approx_eq!($a, $b, $crate::num::floats::lim_for_ty($a)) }}; + ($a:expr, $b:expr, $lim:expr) => {{ + let (a, b) = (&$a, &$b); + let diff = (*a - *b).abs(); + assert!(diff <= $lim,); + }}; +} + +type Float = f32; +const fn flt(x: Float) -> Float { + x +} + +fn test_exp() { + assert_biteq!(1.0, flt(0.0).exp()); + assert_approx_eq!(consts::E, flt(1.0).exp(), EXP_APPROX); + assert_approx_eq!(148.41315910257660342111558004055227962348775, flt(5.0).exp(), EXP_APPROX); + + let inf: Float = Float::INFINITY; + let neg_inf: Float = Float::NEG_INFINITY; + let nan: Float = Float::NAN; + assert_biteq!(inf, inf.exp()); + assert_biteq!(0.0, neg_inf.exp()); + assert!(nan.exp().is_nan()); +} + +#[inline(never)] +fn my_abs(num: f32) -> f32 { + unsafe { intrinsics::fabs(num) } +} + +fn test_abs() { + assert_biteq!(Float::INFINITY.abs(), Float::INFINITY); + assert_biteq!(ONE.abs(), ONE); + assert_biteq!(ZERO.abs(), ZERO); + assert_biteq!((-ZERO).abs(), ZERO); + assert_biteq!((-ONE).abs(), ONE); + assert_biteq!(Float::NEG_INFINITY.abs(), Float::INFINITY); + assert_biteq!((ONE / Float::NEG_INFINITY).abs(), ZERO); + assert!(Float::NAN.abs().is_nan()); +} + +fn main() { + test_abs(); + test_exp(); +} From f81e070c6991742479381511300e259eb304d311 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 29 Apr 2026 23:41:56 +0200 Subject: [PATCH 004/166] Fix tidy errors in cg_gcc --- src/intrinsic/mod.rs | 2 +- tests/lang_tests.rs | 4 ++-- tests/run/core-float.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index da0ef42ed894a..d823e209fd7d9 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -214,7 +214,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc &args.iter().map(|arg| arg.immediate()).collect::>(), ) } - // TODO(antoyo): We can probably remove these and use the fallback intrinsic implementation. + // FIXME(antoyo): We can probably remove these and use the fallback intrinsic implementation. sym::minimumf32 | sym::minimumf64 | sym::maximumf32 | sym::maximumf64 => { let (ty, func_name) = match name { sym::minimumf32 => (self.cx.float_type, "fminimumf"), diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index 3d1d04661c8ca..6afd54e1c3fe0 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -19,7 +19,7 @@ fn compile_and_run_cmds( // Test command 2: run `tempdir/x`. if test_target.is_some() { let mut env_path = std::env::var("PATH").unwrap_or_default(); - // TODO(antoyo): find a better way to add the PATH necessary locally. + // FIXME(antoyo): find a better way to add the PATH necessary locally. env_path = format!("/opt/m68k-unknown-linux-gnu/bin:{}", env_path); compiler.env("PATH", env_path); @@ -112,7 +112,7 @@ fn build_test_runner( println!("=== {test_kind} tests ==="); - // TODO(antoyo): find a way to send this via a cli argument. + // FIXME(antoyo): find a way to send this via a cli argument. let test_target = std::env::var("CG_GCC_TEST_TARGET").ok(); let test_target_filter = test_target.clone(); diff --git a/tests/run/core-float.rs b/tests/run/core-float.rs index 195378b9d3c84..38fa11a69b681 100644 --- a/tests/run/core-float.rs +++ b/tests/run/core-float.rs @@ -3,7 +3,7 @@ // Run-time: // status: 0 -// TODO: remove these tests (extracted from libcore) when we run the libcore tests in the CI of the +// FIXME: remove these tests (extracted from libcore) when we run the libcore tests in the CI of the // Rust repo. #![feature(core_intrinsics)] From 68fc1e299760d3381dcbbf4593f57587ccb0a9f4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:55:07 +0200 Subject: [PATCH 005/166] Move most flags from module_codegen to new_context This way they also apply to the allocator shim. --- src/back/write.rs | 2 +- src/base.rs | 123 ++--------------------------------------- src/gcc_util.rs | 136 +++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 29 ++-------- 4 files changed, 143 insertions(+), 147 deletions(-) diff --git a/src/back/write.rs b/src/back/write.rs index 64674423de2c6..5862a0d9acce6 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -11,8 +11,8 @@ use rustc_log::tracing::debug; use rustc_session::config::OutputType; use rustc_target::spec::SplitDebuginfo; -use crate::base::add_pic_option; use crate::errors::CopyBitcode; +use crate::gcc_util::add_pic_option; use crate::{GccContext, LtoMode}; pub(crate) fn codegen( diff --git a/src/base.rs b/src/base.rs index 7658b86a3a200..78c49efb27473 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,9 +1,7 @@ -use std::collections::HashSet; -use std::env; use std::sync::Arc; use std::time::Instant; -use gccjit::{CType, Context, FunctionType, GlobalKind}; +use gccjit::{CType, FunctionType, GlobalKind}; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; @@ -18,11 +16,11 @@ use rustc_session::config::DebugInfo; use rustc_span::Symbol; #[cfg(feature = "master")] use rustc_target::spec::SymbolVisibility; -use rustc_target::spec::{Arch, RelocModel}; use crate::builder::Builder; use crate::context::CodegenCx; -use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext, gcc_util, new_context}; +use crate::gcc_util::new_context; +use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext}; #[cfg(feature = "master")] pub fn visibility_to_gcc(visibility: Visibility) -> gccjit::Visibility { @@ -102,41 +100,7 @@ pub fn compile_codegen_unit( ) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... - let context = new_context(tcx); - - if tcx.sess.panic_strategy().unwinds() { - 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(); - - if !disabled_features.contains("avx") && tcx.sess.target.arch == Arch::X86_64 { - // 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); - } - // NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc. - context.add_command_line_option("-fno-var-tracking-assignments"); - // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). - context.add_command_line_option("-fno-semantic-interposition"); - // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). - context.add_command_line_option("-fno-strict-aliasing"); - // NOTE: Rust relies on LLVM doing wrapping on overflow. - context.add_command_line_option("-fwrapv"); + let context = new_context(tcx.sess); // NOTE: We need to honor the `#![no_builtins]` attribute to prevent GCC from // replacing code patterns (like loops) with calls to builtins (like memset). @@ -149,64 +113,6 @@ pub fn compile_codegen_unit( context.add_command_line_option("-fno-tree-loop-distribute-patterns"); } - if let Some(model) = tcx.sess.code_model() { - use rustc_target::spec::CodeModel; - - context.add_command_line_option(match model { - CodeModel::Tiny => "-mcmodel=tiny", - CodeModel::Small => "-mcmodel=small", - CodeModel::Kernel => "-mcmodel=kernel", - CodeModel::Medium => "-mcmodel=medium", - CodeModel::Large => "-mcmodel=large", - }); - } - - add_pic_option(&context, tcx.sess.relocation_model()); - - 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"); - } - - 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-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); - } - if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") { - context.set_dump_initial_gimple(true); - } - if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") { - context.set_dump_everything(true); - } - if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") { - context.set_keep_intermediates(true); - } - if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") { - context.add_driver_option("-v"); - } - // NOTE: The codegen generates unreachable blocks. context.set_allow_unreachable_blocks(true); @@ -270,24 +176,3 @@ pub fn compile_codegen_unit( (module, cost) } - -pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) { - match relocation_model { - rustc_target::spec::RelocModel::Static => { - context.add_command_line_option("-fno-pie"); - context.add_driver_option("-fno-pie"); - } - rustc_target::spec::RelocModel::Pic => { - context.add_command_line_option("-fPIC"); - // NOTE: we use both add_command_line_option and add_driver_option because the usage in - // this module (compile_codegen_unit) requires add_command_line_option while the usage - // in the back::write module (codegen) requires add_driver_option. - context.add_driver_option("-fPIC"); - } - rustc_target::spec::RelocModel::Pie => { - context.add_command_line_option("-fPIE"); - context.add_driver_option("-fPIE"); - } - model => eprintln!("Unsupported relocation model: {:?}", model), - } -} diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 330b5ff6828d5..64150ea21f761 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -1,9 +1,13 @@ -#[cfg(feature = "master")] +use std::collections::HashSet; +use std::env; + use gccjit::Context; +#[cfg(feature = "master")] +use gccjit::Version; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; use rustc_session::Session; -use rustc_target::spec::Arch; +use rustc_target::spec::{Arch, RelocModel}; fn gcc_features_by_flags(sess: &Session, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); @@ -135,3 +139,131 @@ pub fn target_cpu(sess: &Session) -> &str { None => handle_native(sess.target.cpu.as_ref()), } } + +pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { + let context = Context::default(); + if matches!(sess.target.arch, Arch::X86 | Arch::X86_64) { + context.add_command_line_option("-masm=intel"); + } + #[cfg(feature = "master")] + { + context.set_special_chars_allowed_in_func_names("$.*"); + let version = Version::get(); + let version = format!("{}.{}.{}", version.major, version.minor, version.patch); + context.set_output_ident(&format!( + "rustc version {} with libgccjit {}", + rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), + version, + )); + } + // FIXME(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. + context.add_command_line_option("-fno-asynchronous-unwind-tables"); + + if sess.panic_strategy().unwinds() { + context.add_command_line_option("-fexceptions"); + context.add_driver_option("-fexceptions"); + } + + let disabled_features: HashSet<_> = sess + .opts + .cg + .target_feature + .split(',') + .filter(|feature| feature.starts_with('-')) + .map(|string| &string[1..]) + .collect(); + + if !disabled_features.contains("avx") && sess.target.arch == Arch::X86_64 { + // 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 &sess.opts.cg.llvm_args { + context.add_command_line_option(arg); + } + // NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc. + context.add_command_line_option("-fno-var-tracking-assignments"); + // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). + context.add_command_line_option("-fno-semantic-interposition"); + // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). + context.add_command_line_option("-fno-strict-aliasing"); + // NOTE: Rust relies on LLVM doing wrapping on overflow. + context.add_command_line_option("-fwrapv"); + + if let Some(model) = sess.code_model() { + use rustc_target::spec::CodeModel; + + context.add_command_line_option(match model { + CodeModel::Tiny => "-mcmodel=tiny", + CodeModel::Small => "-mcmodel=small", + CodeModel::Kernel => "-mcmodel=kernel", + CodeModel::Medium => "-mcmodel=medium", + CodeModel::Large => "-mcmodel=large", + }); + } + + add_pic_option(&context, sess.relocation_model()); + + let target_cpu = target_cpu(sess); + if target_cpu != "generic" { + context.add_command_line_option(format!("-march={}", target_cpu)); + } + + if sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections) { + context.add_command_line_option("-ffunction-sections"); + context.add_command_line_option("-fdata-sections"); + } + + 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-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); + } + if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") { + context.set_dump_initial_gimple(true); + } + if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") { + context.set_dump_everything(true); + } + if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") { + context.set_keep_intermediates(true); + } + if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") { + context.add_driver_option("-v"); + } + + context +} + +pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) { + match relocation_model { + rustc_target::spec::RelocModel::Static => { + context.add_command_line_option("-fno-pie"); + context.add_driver_option("-fno-pie"); + } + rustc_target::spec::RelocModel::Pic => { + context.add_command_line_option("-fPIC"); + // NOTE: we use both add_command_line_option and add_driver_option because the usage in + // this module (compile_codegen_unit) requires add_command_line_option while the usage + // in the back::write module (codegen) requires add_driver_option. + context.add_driver_option("-fPIC"); + } + rustc_target::spec::RelocModel::Pie => { + context.add_command_line_option("-fPIE"); + context.add_driver_option("-fPIE"); + } + model => eprintln!("Unsupported relocation model: {:?}", model), + } +} diff --git a/src/lib.rs b/src/lib.rs index d50968bad2501..f84e3c402b6a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,9 +77,9 @@ use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; -use gccjit::{CType, Context, OptimizationLevel}; #[cfg(feature = "master")] -use gccjit::{TargetInfo, Version}; +use gccjit::TargetInfo; +use gccjit::{CType, Context, OptimizationLevel}; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::ThinModule; use rustc_codegen_ssa::back::write::{ @@ -99,7 +99,7 @@ use rustc_middle::util::Providers; use rustc_session::Session; use rustc_session::config::{OptLevel, OutputFilenames}; use rustc_span::Symbol; -use rustc_target::spec::{Arch, RelocModel}; +use rustc_target::spec::RelocModel; use tempfile::TempDir; use crate::back::lto::ModuleBuffer; @@ -312,27 +312,6 @@ impl CodegenBackend for GccCodegenBackend { } } -fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { - let context = Context::default(); - if matches!(tcx.sess.target.arch, Arch::X86 | Arch::X86_64) { - context.add_command_line_option("-masm=intel"); - } - #[cfg(feature = "master")] - { - context.set_special_chars_allowed_in_func_names("$.*"); - let version = Version::get(); - let version = format!("{}.{}.{}", version.major, version.minor, version.patch); - context.set_output_ident(&format!( - "rustc version {} with libgccjit {}", - rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), - version, - )); - } - // FIXME(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. - context.add_command_line_option("-fno-asynchronous-unwind-tables"); - context -} - impl ExtraBackendMethods for GccCodegenBackend { fn supports_parallel(&self) -> bool { false @@ -346,7 +325,7 @@ impl ExtraBackendMethods for GccCodegenBackend { ) -> Self::Module { let lto_supported = self.lto_supported.load(Ordering::SeqCst); let mut mods = GccContext { - context: Arc::new(SyncContext::new(new_context(tcx))), + context: Arc::new(SyncContext::new(gcc_util::new_context(tcx.sess))), relocation_model: tcx.sess.relocation_model(), lto_mode: LtoMode::None, lto_supported, From 6b0348dd77b206ef2c57d5c2abdb1c046b7dd13b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:13:03 +0200 Subject: [PATCH 006/166] Remove a fixme Submission to the Apple App Store for iOS no longer requires embedding bitcode, but even back when it did, it needed LLVM bitcode, so GCC wouldn't work anyway. --- src/back/write.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/back/write.rs b/src/back/write.rs index 5862a0d9acce6..3ef24783c0b1c 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -68,9 +68,6 @@ pub(crate) fn codegen( let _timer = prof .generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name); if lto_supported { - // FIXME(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"); From 1ab95d4a915c6ec4bc88977e81d116fc7b6e27f6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:29:41 +0200 Subject: [PATCH 007/166] Update comment --- src/gcc_util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 64150ea21f761..2615d93e427d4 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -256,7 +256,7 @@ pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocMode rustc_target::spec::RelocModel::Pic => { context.add_command_line_option("-fPIC"); // NOTE: we use both add_command_line_option and add_driver_option because the usage in - // this module (compile_codegen_unit) requires add_command_line_option while the usage + // base (compile_codegen_unit) requires add_command_line_option while the usage // in the back::write module (codegen) requires add_driver_option. context.add_driver_option("-fPIC"); } From f992a3d28240740858674ecdabf40cd41c3f801f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:18:33 +0000 Subject: [PATCH 008/166] Pass Session to optimize_and_codegen_fat_lto This is necessary to fix incremental LTO in cg_gcc as well as to do some LTO refactorings I want to do. The actual fix for cg_gcc will be done on the cg_gcc repo to test it in CI. --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d50968bad2501..4be25b3fb0934 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -430,8 +430,8 @@ impl WriteBackendMethods for GccCodegenBackend { } fn optimize_and_codegen_fat_lto( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, _tm_factory: TargetMachineFactoryFn, // FIXME(bjorn3): Limit LTO exports to these symbols @@ -439,7 +439,7 @@ impl WriteBackendMethods for GccCodegenBackend { each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> CompiledModule { - back::lto::run_fat(cgcx, prof, shared_emitter, each_linked_rlib_for_lto, modules) + back::lto::run_fat(cgcx, &sess.prof, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( From 6ecabe8fadb056fe97b9f74833f0c26adcca8362 Mon Sep 17 00:00:00 2001 From: Uni Hikousen <32487868+cijiugechu@users.noreply.github.com> Date: Fri, 1 May 2026 01:15:29 +0800 Subject: [PATCH 009/166] Fix asm pointer inputs (#874) --- src/asm.rs | 9 ++++++++- tests/run/asm.rs | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/asm.rs b/src/asm.rs index 5bb65365ad6ad..f4b2934178a2c 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -362,7 +362,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let ty = value.layout.gcc_type(self.cx); let reg_var = self.current_func().new_local(None, ty, "input_register"); reg_var.set_register_name(reg_name); - self.llbb().add_assignment(None, reg_var, value.immediate()); + // FIXME: We should remove this when switching to "untyped" pointers + let value = value.immediate(); + let value = if value.get_type() != ty { + self.context.new_cast(None, value, ty) + } else { + value + }; + self.llbb().add_assignment(None, reg_var, value); inputs.push(AsmInOperand { constraint: "r".into(), diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 01775c92ffc8a..2d78f5ad5f99c 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -190,6 +190,14 @@ fn asm() { } assert_eq!((x, y), (8, 8)); + // Regression test for + // typed pointer inputs to explicit registers need a cast. + let mut x = 123_i32; + unsafe { + asm!("", in("rdi") &mut x, options(nostack, preserves_flags)); + } + assert_eq!(x, 123); + // sysv64 is the default calling convention on unix systems. The rdi register is // used to pass arguments in the sysv64 calling convention, so this register will be clobbered #[cfg(unix)] From 3d74e8587afb2ac59dde995230cd336297030aef Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Apr 2026 14:40:23 +1000 Subject: [PATCH 010/166] Invert dependency between `rustc_error_messages` and `rustc_ast*`. `rustc_error_messages` currently depends on `rustc_ast`/`rustc_ast_pretty`. This is odd, because `rustc_error_messages` feels like a very low-level module but `rustc_ast`/`rustc_ast_pretty` do not. The reason is that a few AST types impl `IntoDiagArg` via pretty-printing. `rustc_error_messages` can define `IntoDiagArg` and then impl it for the AST types. But if we invert the dependency we hit a problem with the orphan rule: `rustc_ast` must impl `IntoDiagArg` for the AST types, but that requires calling pretty-printing code which is in `rustc_ast_pretty`, a downstream crate. This commit avoids this problem by just removing the `IntoDiagArg` impls for these AST types. There aren't that many of them, and we can just use `String` in the relevant error structs and use the pretty printer in the downstream crates that construct the error structs. There are plenty of existing examples where `String` is used in error structs. There is now no dependency between `rustc_ast*` and `rustc_error_messages`. --- src/intrinsic/simd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index bdb8316f3965d..a32592b45e5ea 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -828,7 +828,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return_error!(InvalidMonomorphization::FloatingPointVector { span, name, - f_ty: *f, + f_ty: f.name_str().to_string(), in_ty }); } From c32743a96b3d1d5dd948c43050420c0aafea3e36 Mon Sep 17 00:00:00 2001 From: mehdiakiki Date: Sun, 5 Apr 2026 19:59:30 -0400 Subject: [PATCH 011/166] Add rlib digest to identify Rust object files --- src/back/lto.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 401d4c244d5a0..4a46c59e81f0c 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -24,9 +24,10 @@ use std::path::{Path, PathBuf}; use gccjit::OutputKind; use object::read::archive::ArchiveFile; use rustc_codegen_ssa::back::lto::SerializedModule; +use rustc_codegen_ssa::back::rmeta_link; use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter}; use rustc_codegen_ssa::traits::*; -use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind, looks_like_rust_object_file}; +use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; @@ -63,6 +64,7 @@ fn prepare_lto(each_linked_rlib_for_lto: &[PathBuf], dcx: DiagCtxtHandle<'_>) -> let archive_data = unsafe { Mmap::map(File::open(path).expect("couldn't open rlib")).expect("couldn't map rlib") }; + let metadata_link = rmeta_link::read_from_data(&archive_data, path).unwrap(); let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib"); let obj_files = archive .members() @@ -71,7 +73,7 @@ fn prepare_lto(each_linked_rlib_for_lto: &[PathBuf], dcx: DiagCtxtHandle<'_>) -> .ok() .and_then(|c| std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c))) }) - .filter(|&(name, _)| looks_like_rust_object_file(name)); + .filter(|&(name, _)| metadata_link.rust_object_files.iter().any(|f| f == name)); for (name, child) in obj_files { info!("adding bitcode from {}", name); let path = tmp_path.path().join(name); From 43cdcebc8a47898f4339e18d5cc51f56f51e63d0 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Fri, 3 Apr 2026 21:07:17 +0200 Subject: [PATCH 012/166] rename `drop_in_place` lang item to `drop_glue` --- example/mini_core.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 481fe5387e149..2d5a29ceb8191 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -577,12 +577,10 @@ fn eh_personality() -> ! { loop {} } -#[lang = "drop_in_place"] -#[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { +#[lang = "drop_glue"] +pub unsafe fn drop_glue(_to_drop: &mut T) { // Code here does not matter - this is replaced by the // real drop glue by the compiler. - drop_in_place(to_drop); } #[lang = "unpin"] From fbf722a310e81b09ee39f10e44b4cbe021cb57a6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 6 May 2026 13:44:29 +0200 Subject: [PATCH 013/166] Rustup to rustc 1.97.0-nightly (e95e73209 2026-05-05) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 56fcfdff1c719..02c9b54898adf 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-04-29" +channel = "nightly-2026-05-06" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From b69d0746bbbd56116bbdce4f2874d409098d2fa6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 6 May 2026 14:07:08 +0200 Subject: [PATCH 014/166] Stop cspell from complaining about rmeta --- tools/cspell_dicts/rust.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/cspell_dicts/rust.txt b/tools/cspell_dicts/rust.txt index 379cbd77eef01..15faacd53d5a0 100644 --- a/tools/cspell_dicts/rust.txt +++ b/tools/cspell_dicts/rust.txt @@ -1,2 +1,3 @@ lateout repr +rmeta From 50056a88993230df012e4578bee4a22f3d7ae5be Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 6 May 2026 14:25:50 +0200 Subject: [PATCH 015/166] Add failing run-make test --- tests/failing-run-make-tests.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/failing-run-make-tests.txt b/tests/failing-run-make-tests.txt index 528ee1df9f583..1feb2c7cc6edc 100644 --- a/tests/failing-run-make-tests.txt +++ b/tests/failing-run-make-tests.txt @@ -12,3 +12,4 @@ tests/run-make/glibc-staticlib-args/ tests/run-make/lto-smoke-c/ tests/run-make/return-non-c-like-enum/ tests/run-make/short-ice +tests/run-make/embed-source-dwarf From da9e1aa356f83e7ac879f46ed9b1174b1f18c853 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:56:53 +0200 Subject: [PATCH 016/166] Handle all modules being serialized during LTO --- src/back/lto.rs | 40 +++++++++++++++++++++------------------- src/lib.rs | 2 +- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 7166ad8b1f17f..e78a0d7fdd5e3 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -20,6 +20,7 @@ use std::ffi::CString; use std::fs::{self, File}; use std::path::{Path, PathBuf}; +use std::sync::Arc; use gccjit::OutputKind; use object::read::archive::ArchiveFile; @@ -29,14 +30,15 @@ use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter} use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind}; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_log::tracing::info; +use rustc_session::Session; use tempfile::{TempDir, tempdir}; use crate::back::write::{codegen, save_temp_bitcode}; use crate::errors::LtoBitcodeFromRlib; -use crate::{GccCodegenBackend, GccContext, LtoMode, to_gcc_opt_level}; +use crate::gcc_util::new_context; +use crate::{GccCodegenBackend, GccContext, LtoMode, SyncContext, to_gcc_opt_level}; struct LtoData { // FIXME(antoyo): use symbols_below_threshold. @@ -102,8 +104,8 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { /// Performs fat LTO by merging all modules into a single one and returning it /// for further optimization. pub(crate) fn run_fat( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -114,8 +116,8 @@ pub(crate) fn run_fat( /*let symbols_below_threshold = lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ fat_lto( + sess, cgcx, - prof, dcx, modules, lto_data.upstream_modules, @@ -125,15 +127,15 @@ pub(crate) fn run_fat( } fn fat_lto( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, modules: Vec>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, //symbols_below_threshold: &[String], ) -> CompiledModule { - let _timer = prof.generic_activity("GCC_fat_lto_build_monolithic_module"); + let _timer = sess.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. @@ -183,17 +185,16 @@ fn fat_lto( // 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(), dcx)?, - name: name.into_string().unwrap(), - kind: ModuleKind::Regular, - }*/ - } + None => ModuleCodegen::new_regular( + "lto_module".to_string(), + GccContext { + context: Arc::new(SyncContext::new(new_context(sess))), + relocation_model: sess.relocation_model(), + lto_supported: true, + lto_mode: LtoMode::None, + temp_dir: None, + }, + ), }; { info!("using {:?} as a base module", module.name); @@ -220,7 +221,8 @@ fn fat_lto( // 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 = prof + let _timer = sess + .prof .generic_activity_with_arg_recorder("GCC_fat_lto_link_module", |recorder| { recorder.record_arg(format!("{:?}", name)) }); @@ -258,7 +260,7 @@ fn fat_lto( // of now. module.module_llvm.temp_dir = Some(tmp_path); - codegen(cgcx, prof, dcx, module, &cgcx.module_config) + codegen(cgcx, &sess.prof, dcx, module, &cgcx.module_config) } pub struct ModuleBuffer(PathBuf); diff --git a/src/lib.rs b/src/lib.rs index ac9452306aa3e..89f045812164e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -418,7 +418,7 @@ impl WriteBackendMethods for GccCodegenBackend { each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> CompiledModule { - back::lto::run_fat(cgcx, &sess.prof, shared_emitter, each_linked_rlib_for_lto, modules) + back::lto::run_fat(sess, cgcx, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( From d2a379f94afa9ce32ab7215bddef0e938248b7c5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:23:52 +0000 Subject: [PATCH 017/166] Move CrateInfo computation after codegen_crate CrateInfo is only necessary during linking and non-local LTO. --- src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4be25b3fb0934..6ca2ef88ef291 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -291,8 +291,8 @@ impl CodegenBackend for GccCodegenBackend { target_cpu(sess).to_owned() } - fn codegen_crate(&self, tcx: TyCtxt<'_>, crate_info: &CrateInfo) -> Box { - Box::new(codegen_crate(self.clone(), tcx, crate_info)) + fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { + Box::new(codegen_crate(self.clone(), tcx)) } fn join_codegen( @@ -300,11 +300,12 @@ impl CodegenBackend for GccCodegenBackend { ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames, + crate_info: &CrateInfo, ) -> (CompiledModules, FxIndexMap) { ongoing_codegen .downcast::>() .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") - .join(sess) + .join(sess, crate_info) } fn target_config(&self, sess: &Session) -> TargetConfig { From 3ce0567a426be2c95241145965045eb04d572c76 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 6 May 2026 14:18:13 +0000 Subject: [PATCH 018/166] Move invocation_temp into OutputFilenames While it was previously defined in Session, it is only ever used with OutputFilenames methods. --- src/back/write.rs | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/src/back/write.rs b/src/back/write.rs index 64674423de2c6..8fd38a2efd600 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -29,16 +29,8 @@ pub(crate) fn codegen( let lto_mode = module.module_llvm.lto_mode; let lto_supported = module.module_llvm.lto_supported; - let bc_out = cgcx.output_filenames.temp_path_for_cgu( - OutputType::Bitcode, - &module.name, - cgcx.invocation_temp.as_deref(), - ); - let obj_out = cgcx.output_filenames.temp_path_for_cgu( - OutputType::Object, - &module.name, - cgcx.invocation_temp.as_deref(), - ); + let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name); + let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name); if config.bitcode_needed() { let _timer = @@ -82,22 +74,15 @@ pub(crate) fn codegen( } if config.emit_ir { - let out = cgcx.output_filenames.temp_path_for_cgu( - OutputType::LlvmAssembly, - &module.name, - cgcx.invocation_temp.as_deref(), - ); + let out = + cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name); std::fs::write(out, "").expect("write file"); } if config.emit_asm { let _timer = prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name); - let path = cgcx.output_filenames.temp_path_for_cgu( - OutputType::Assembly, - &module.name, - cgcx.invocation_temp.as_deref(), - ); + let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name); context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str")); } @@ -215,7 +200,6 @@ pub(crate) fn codegen( config.emit_asm, config.emit_ir, &cgcx.output_filenames, - cgcx.invocation_temp.as_deref(), ) } From 86bb28c55aae97f1092d4df46991dfa9a18457df Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 10 May 2026 11:59:35 +0200 Subject: [PATCH 019/166] Update a bunch of dependencies to remove windows-targets --- Cargo.lock | 92 ++++++++++-------------------------------------------- 1 file changed, 17 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a283ea4cb0b05..b984e66531e60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,9 +31,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.168" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "memchr" @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", @@ -216,9 +216,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", "getrandom", @@ -311,78 +311,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.59.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-targets" -version = "0.52.6" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "wit-bindgen-rt" version = "0.39.0" From 6f525503efbc1cbeb485a9375db856bf57f0747c Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sun, 26 Apr 2026 12:09:05 +0200 Subject: [PATCH 020/166] Add Swift function call ABI Adds an unstable `extern "Swift"` ABI behind the `abi_swift` feature gate, mapping to LLVM's `swiftcc` calling convention. Cranelift and GCC backends fall back to the platform default since they have no equivalent. --- src/abi.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/abi.rs b/src/abi.rs index 2f5c555b702a4..7239a5bcb0413 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -245,6 +245,8 @@ pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &Arch) -> Option return None, + // gcc/gccjit does not have anything for Swift's calling convention. + CanonAbi::Swift => panic!("gcc/gccjit backend does not support Swift calling convention"), CanonAbi::Arm(arm_call) => match arm_call { ArmCall::CCmseNonSecureCall => FnAttribute::ArmCmseNonsecureCall, ArmCall::CCmseNonSecureEntry => FnAttribute::ArmCmseNonsecureEntry, From 2f4c35e1582a675488b1d3f0b2ac83ac16170e64 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Wed, 6 May 2026 09:32:56 +0200 Subject: [PATCH 021/166] Unnormalized migration: struct_tail takes fn taking Unnormalized --- src/intrinsic/simd.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index a32592b45e5ea..ff5155f9f7776 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -16,7 +16,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; use rustc_hir as hir; use rustc_middle::mir::BinOp; use rustc_middle::ty::layout::HasTyCtxt; -use rustc_middle::ty::{self, Ty, Unnormalized}; +use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, Symbol, sym}; use crate::builder::Builder; @@ -539,10 +539,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *in_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { - bx.tcx.normalize_erasing_regions( - ty::TypingEnv::fully_monomorphized(), - Unnormalized::new_wip(ty), - ) + bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); require!( metadata.is_unit(), @@ -556,10 +553,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *out_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { - bx.tcx.normalize_erasing_regions( - ty::TypingEnv::fully_monomorphized(), - Unnormalized::new_wip(ty), - ) + bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); require!( metadata.is_unit(), From 8474bb0758bad292de97d6c87b74c2e7da1b81ac Mon Sep 17 00:00:00 2001 From: Ian McCormack Date: Thu, 30 Apr 2026 19:49:04 -0400 Subject: [PATCH 022/166] Add trait methods for experimental retags to cg. --- src/intrinsic/mod.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index d823e209fd7d9..6fb25174bf1e0 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -6,7 +6,6 @@ use std::iter; use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; -use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; use rustc_codegen_ssa::errors::InvalidMonomorphization; @@ -18,6 +17,7 @@ use rustc_codegen_ssa::traits::{ ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, }; +use rustc_codegen_ssa::{MemFlags, RetagInfo}; use rustc_data_structures::fx::FxHashSet; #[cfg(feature = "master")] use rustc_middle::ty::layout::FnAbiOf; @@ -702,6 +702,14 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc // FIXME(antoyo): implement. self.context.new_rvalue_from_int(self.int_type, 0) } + + fn retag_reg(&mut self, _ptr: Self::Value, _info: &RetagInfo) -> Self::Value { + unimplemented!() + } + + fn retag_mem(&mut self, _ptr: Self::Value, _info: &RetagInfo) { + unimplemented!() + } } impl<'a, 'gcc, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { From 5e72aee9b8faeec262897c9a30d5576863fa9ae7 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 3 May 2026 12:01:22 -0700 Subject: [PATCH 023/166] Let intrinsics use the SSA operand path --- src/context.rs | 6 +++++- src/intrinsic/mod.rs | 34 ++++++++++++++++++++-------------- src/intrinsic/simd.rs | 14 +++++++------- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/context.rs b/src/context.rs index e0810a35b040b..ed313859aeafa 100644 --- a/src/context.rs +++ b/src/context.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; use rustc_session::Session; #[cfg(feature = "master")] use rustc_session::config::DebugInfo; -use rustc_span::{DUMMY_SP, Span, respan}; +use rustc_span::{DUMMY_SP, Span, Symbol, respan}; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; #[cfg(feature = "master")] @@ -497,6 +497,10 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { None } } + + fn intrinsic_call_expects_place_always(&self, _name: Symbol) -> bool { + true + } } impl<'gcc, 'tcx> HasTyCtxt<'tcx> for CodegenCx<'gcc, 'tcx> { diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 6fb25174bf1e0..f56cec6ce227e 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -9,6 +9,7 @@ use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; use rustc_codegen_ssa::errors::InvalidMonomorphization; +use rustc_codegen_ssa::mir::IntrinsicResult; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; #[cfg(feature = "master")] @@ -194,11 +195,14 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc &mut self, instance: Instance<'tcx>, args: &[OperandRef<'tcx, RValue<'gcc>>], - result: PlaceRef<'tcx, RValue<'gcc>>, + result_layout: ty::layout::TyAndLayout<'tcx>, + result_place: Option>>, span: Span, - ) -> Result<(), Instance<'tcx>> { + ) -> IntrinsicResult<'tcx, RValue<'gcc>> { let tcx = self.tcx; + let result = PlaceRef { val: result_place.unwrap(), layout: result_layout }; + let name = tcx.item_name(instance.def_id()); let name_str = name.as_str(); let fn_args = instance.args; @@ -353,7 +357,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc args[2].immediate(), result, ); - return Ok(()); + return IntrinsicResult::WroteIntoPlace; } sym::breakpoint => { unimplemented!(); @@ -375,12 +379,12 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc sym::volatile_store => { let dst = args[0].deref(self.cx()); args[1].val.volatile_store(self, dst); - return Ok(()); + return IntrinsicResult::WroteIntoPlace; } sym::unaligned_volatile_store => { let dst = args[0].deref(self.cx()); args[1].val.unaligned_volatile_store(self, dst); - return Ok(()); + return IntrinsicResult::WroteIntoPlace; } sym::prefetch_read_data | sym::prefetch_write_data @@ -448,12 +452,12 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc _ => bug!(), }, None => { - tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { + let err = tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty: args[0].layout.ty, }); - return Ok(()); + return IntrinsicResult::Err(err); } } } @@ -544,7 +548,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc extended_asm.set_volatile_flag(true); // We have copied the value to `result` already. - return Ok(()); + return IntrinsicResult::WroteIntoPlace; } sym::ptr_mask => { @@ -569,12 +573,15 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc span, ) { Ok(value) => value, - Err(()) => return Ok(()), + Err(err) => return IntrinsicResult::Err(err), } } // Fall back to default body - _ => return Err(Instance::new_raw(instance.def_id(), instance.args)), + _ => { + let fallback = Instance::new_raw(instance.def_id(), instance.args); + return IntrinsicResult::Fallback(fallback); + } }; if result.layout.ty.is_bool() { @@ -583,7 +590,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } else if !result.layout.ty.is_unit() { self.store_to_place(value, result.val); } - Ok(()) + IntrinsicResult::WroteIntoPlace } fn codegen_llvm_intrinsic_call( @@ -694,13 +701,12 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.context.new_rvalue_from_int(self.int_type, 0) } - fn va_start(&mut self, _va_list: RValue<'gcc>) -> RValue<'gcc> { + fn va_start(&mut self, _va_list: RValue<'gcc>) { unimplemented!(); } - fn va_end(&mut self, _va_list: RValue<'gcc>) -> RValue<'gcc> { + fn va_end(&mut self, _va_list: RValue<'gcc>) { // FIXME(antoyo): implement. - self.context.new_rvalue_from_int(self.int_type, 0) } fn retag_reg(&mut self, _ptr: Self::Value, _info: &RetagInfo) -> Self::Value { diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index ff5155f9f7776..82ef99703b253 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -17,7 +17,7 @@ use rustc_hir as hir; use rustc_middle::mir::BinOp; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, Ty}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use crate::builder::Builder; #[cfg(not(feature = "master"))] @@ -32,12 +32,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ret_ty: Ty<'tcx>, llret_ty: Type<'gcc>, span: Span, -) -> Result, ()> { +) -> Result, ErrorGuaranteed> { // macros for error handling: macro_rules! return_error { ($err:expr) => {{ - bx.tcx.dcx().emit_err($err); - return Err(()); + let err = bx.tcx.dcx().emit_err($err); + return Err(err); }}; } macro_rules! require { @@ -803,11 +803,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( bx: &mut Builder<'_, 'gcc, 'tcx>, span: Span, args: &[OperandRef<'tcx, RValue<'gcc>>], - ) -> Result, ()> { + ) -> Result, ErrorGuaranteed> { macro_rules! return_error { ($err:expr) => {{ - bx.tcx.dcx().emit_err($err); - return Err(()); + let err = bx.tcx.dcx().emit_err($err); + return Err(err); }}; } let ty::Float(ref f) = *in_elem.kind() else { From 0a4077f57236a94a24a21658f718ab71671ae044 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 23 May 2026 12:22:43 +0200 Subject: [PATCH 024/166] Fix invalid cg_gcc `panic` function cast --- src/intrinsic/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 6fb25174bf1e0..a244a9c493ad8 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -1352,7 +1352,10 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>( dest: PlaceRef<'tcx, RValue<'gcc>>, ) { if !bx.sess().panic_strategy().unwinds() { - bx.call(bx.type_void(), None, None, try_func, &[data], None, None); + let param_type = bx.u8_type.make_pointer(); + let fn_type = + bx.context.new_function_pointer_type(None, bx.type_void(), &[param_type], false); + bx.call(fn_type, None, None, try_func, &[data], None, None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. OperandValue::Immediate(bx.const_i32(0)).store(bx, dest); From 2ad24e164046d5be695a21f41b48ce77228a8fd5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 10 May 2026 17:02:34 +0200 Subject: [PATCH 025/166] MIR inlining: allow backends to opt-in to inlining intrinsics --- src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6ca2ef88ef291..8e7611ed4939c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,7 +98,7 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; use rustc_session::config::{OptLevel, OutputFilenames}; -use rustc_span::Symbol; +use rustc_span::{Symbol, sym}; use rustc_target::spec::{Arch, RelocModel}; use tempfile::TempDir; @@ -311,6 +311,10 @@ impl CodegenBackend for GccCodegenBackend { fn target_config(&self, sess: &Session) -> TargetConfig { target_config(sess, &self.target_info) } + + fn fallback_intrinsics(&self) -> Vec { + vec![sym::type_id_eq] + } } fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { From 8959aa40d654b172b7cc7e4d9d0f8825034d963c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 May 2026 09:00:36 +0000 Subject: [PATCH 026/166] Support implementing ExtraBackendMethods and WriteBackendMethods independently --- src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6ca2ef88ef291..50f10947c6aed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -335,9 +335,7 @@ fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { } impl ExtraBackendMethods for GccCodegenBackend { - fn supports_parallel(&self) -> bool { - false - } + type Module = GccContext; fn codegen_allocator( &self, @@ -420,6 +418,10 @@ impl WriteBackendMethods for GccCodegenBackend { type ModuleBuffer = ModuleBuffer; type ThinData = (); + fn supports_parallel(&self) -> bool { + false + } + fn target_machine_factory( &self, _sess: &Session, From cf570452c6063e38f6246150a55e5d035963a617 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 28 May 2026 17:38:11 -0400 Subject: [PATCH 027/166] Update to nightly-2026-05-28 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 02c9b54898adf..7860423093bc5 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-05-06" +channel = "nightly-2026-05-28" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From a291dd0c80afc20858f676ab535de1cd07298fbc Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 23 May 2026 16:28:57 -0700 Subject: [PATCH 028/166] Stop needing an alloca for `catch_unwind` Turns out these were all making `OperandValue::Immediate`s already -- the intrinsic always returns a primitive scalar -- so pretty easy to handle. While I was looking at it, I also "rustified" the intrinsic signature a bit: returning a `bool` and taking a generic pointee and `unsafe fn`s cleans up the call in `std` a bit without making the implementation in the backend any harder. --- src/intrinsic/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index f56cec6ce227e..2aabbbd762838 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -1361,7 +1361,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>( bx.call(bx.type_void(), None, None, try_func, &[data], None, None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. - OperandValue::Immediate(bx.const_i32(0)).store(bx, dest); + OperandValue::Immediate(bx.const_bool(false)).store(bx, dest); } else { if wants_msvc_seh(bx.sess()) { unimplemented!(); @@ -1418,7 +1418,7 @@ fn codegen_gnu_try<'gcc, 'tcx>( let current_block = bx.block; bx.switch_to_block(then); - bx.ret(bx.const_i32(0)); + bx.ret(bx.const_bool(false)); // Type indicator for the exception being thrown. // @@ -1432,7 +1432,7 @@ fn codegen_gnu_try<'gcc, 'tcx>( let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]); let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void()); bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, None); - bx.ret(bx.const_i32(1)); + bx.ret(bx.const_bool(true)); // NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not // generate a try/catch. @@ -1465,7 +1465,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( // Define the type up front for the signature of the rust_try function. let tcx = cx.tcx; let i8p = Ty::new_mut_ptr(tcx, tcx.types.i8); - // `unsafe fn(*mut i8) -> ()` + // `unsafe fn(*mut Data) -> ()` let try_fn_ty = Ty::new_fn_ptr( tcx, ty::Binder::dummy(tcx.mk_fn_sig_rust_abi( @@ -1474,7 +1474,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( rustc_hir::Safety::Unsafe, )), ); - // `unsafe fn(*mut i8, *mut i8) -> ()` + // `unsafe fn(*mut Data, *mut i8) -> ()` let catch_fn_ty = Ty::new_fn_ptr( tcx, ty::Binder::dummy(tcx.mk_fn_sig_rust_abi( @@ -1483,10 +1483,10 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( rustc_hir::Safety::Unsafe, )), ); - // `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32` + // `unsafe fn(unsafe fn(*mut Data) -> (), *mut Data, unsafe fn(*mut Data, *mut i8) -> ()) -> bool` let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig_rust_abi( [try_fn_ty, i8p, catch_fn_ty], - tcx.types.i32, + tcx.types.bool, rustc_hir::Safety::Unsafe, )); let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen); From 07ba76745bf660ef08c928a8336300934442b756 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 29 May 2026 07:53:23 -0400 Subject: [PATCH 029/166] Ignore spelling --- tools/cspell_dicts/rustc_codegen_gcc.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/cspell_dicts/rustc_codegen_gcc.txt b/tools/cspell_dicts/rustc_codegen_gcc.txt index 4fb018b3ecd87..619221d5260cf 100644 --- a/tools/cspell_dicts/rustc_codegen_gcc.txt +++ b/tools/cspell_dicts/rustc_codegen_gcc.txt @@ -60,6 +60,7 @@ nvptx pointee powitf reassoc +retag riscv rlib roundevenf From e2ae9ad50f4bca05878b39e1080b0795051b8d40 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 29 May 2026 09:00:32 -0400 Subject: [PATCH 030/166] Add missing LLVM intrinsic mapping --- src/intrinsic/llvm.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index d58697f1bf270..b7495e0e4c43b 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -489,6 +489,19 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1); args = vec![new_args[1], new_args[0], new_args[2], minus_one].into(); } + "__builtin_ia32_fpclassph128_mask" + | "__builtin_ia32_fpclassph256_mask" + | "__builtin_ia32_fpclassph512_mask" + | "__builtin_ia32_fpclasspd128_mask" + | "__builtin_ia32_fpclassps128_mask" + | "__builtin_ia32_fpclasspd256_mask" + | "__builtin_ia32_fpclassps256_mask" + | "__builtin_ia32_fpclasspd512_mask" => { + let new_args = args.to_vec(); + let arg3_type = gcc_func.get_param_type(2); + let minus_one = builder.context.new_rvalue_from_int(arg3_type, -1); + args = vec![new_args[0], new_args[1], minus_one].into(); + } "__builtin_ia32_xrstor" | "__builtin_ia32_xrstor64" | "__builtin_ia32_xsavec" @@ -1577,6 +1590,17 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.uitofp.round.v4f64.v4i64" => "__builtin_ia32_cvtuqq2pd256_mask", "llvm.x86.avx512.uitofp.round.v8f32.v8i64" => "__builtin_ia32_cvtuqq2ps512_mask", "llvm.x86.avx512.uitofp.round.v4f32.v4i64" => "__builtin_ia32_cvtuqq2ps256_mask", + "llvm.x86.avx512fp16.fpclass.ph.128" => "__builtin_ia32_fpclassph128_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.128" => "__builtin_ia32_cmpph128_mask", + "llvm.x86.avx512fp16.fpclass.ph.256" => "__builtin_ia32_fpclassph256_mask", + "llvm.x86.avx512fp16.fpclass.ph.512" => "__builtin_ia32_fpclassph512_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.256" => "__builtin_ia32_cmpph256_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.512" => "__builtin_ia32_cmpph512_mask_round", + "llvm.x86.avx512.fpclass.pd.128" => "__builtin_ia32_fpclasspd128_mask", + "llvm.x86.avx512.fpclass.ps.128" => "__builtin_ia32_fpclassps128_mask", + "llvm.x86.avx512.fpclass.pd.256" => "__builtin_ia32_fpclasspd256_mask", + "llvm.x86.avx512.fpclass.ps.256" => "__builtin_ia32_fpclassps256_mask", + "llvm.x86.avx512.fpclass.pd.512" => "__builtin_ia32_fpclasspd512_mask", // FIXME: support the tile builtins: "llvm.x86.ldtilecfg" => "__builtin_trap", From 418adda25171b737cc6f17381ea5b79afccf1dd3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 21 Nov 2025 21:58:09 +0300 Subject: [PATCH 031/166] resolve: Partially convert `ambiguous_glob_imports` lint into a hard error --- build_system/src/test.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 3f02df8399554..2475a3a6a7155 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -886,8 +886,6 @@ fn valid_ui_error_pattern_test(file: &str) -> bool { "type-alias-impl-trait/auxiliary/cross_crate_ice.rs", "type-alias-impl-trait/auxiliary/cross_crate_ice2.rs", "macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs", - "imports/ambiguous-1.rs", - "imports/ambiguous-4-extern.rs", "entry-point/auxiliary/bad_main_functions.rs", ] .iter() From f775c8179b8c0fe717d8375daf382f1a42d499c9 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 29 May 2026 11:17:14 -0400 Subject: [PATCH 032/166] Add more missing LLVM intrinsic mapping --- src/builder.rs | 12 +++++++-- src/intrinsic/llvm.rs | 62 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 33f0f6fc2f809..4a5fbfee2ca75 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -418,8 +418,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.location, self.cx.context.new_call_through_ptr(self.location, func_ptr, &args), ); - // Return dummy value when not having return value. - self.context.new_rvalue_zero(self.isize_type) + // Return dummy value when not having return value, unless the intrinsic adapter + // needs to synthesize a non-void LLVM-level result from out-parameters. + llvm::adjust_intrinsic_return_value( + self, + self.context.new_rvalue_zero(self.isize_type), + &func_name, + &args, + args_adjusted, + orig_args, + ) } } diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index b7495e0e4c43b..b19f63dd077d5 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -478,6 +478,26 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( new_args.push(variable.get_address(None)); args = new_args.into(); } + "__builtin_ia32_2intersectd128" + | "__builtin_ia32_2intersectq128" + | "__builtin_ia32_2intersectd256" + | "__builtin_ia32_2intersectq256" + | "__builtin_ia32_2intersectd512" + | "__builtin_ia32_2intersectq512" => { + let old_args = args.to_vec(); + let mut new_args = vec![]; + let arg1_type = gcc_func.get_param_type(0); + let first_mask = + builder.current_func().new_local(None, arg1_type, "return_2intersect_arg1"); + let arg2_type = gcc_func.get_param_type(1); + let second_mask = + builder.current_func().new_local(None, arg2_type, "return_2intersect_arg2"); + new_args.push(first_mask.get_address(None)); + new_args.push(second_mask.get_address(None)); + new_args.push(old_args[0]); + new_args.push(old_args[1]); + args = new_args.into(); + } "__builtin_ia32_vpermt2varqi512_mask" | "__builtin_ia32_vpermt2varqi256_mask" | "__builtin_ia32_vpermt2varqi128_mask" @@ -496,7 +516,11 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( | "__builtin_ia32_fpclassps128_mask" | "__builtin_ia32_fpclasspd256_mask" | "__builtin_ia32_fpclassps256_mask" - | "__builtin_ia32_fpclasspd512_mask" => { + | "__builtin_ia32_fpclasspd512_mask" + | "__builtin_ia32_fpclassps512_mask" + | "__builtin_ia32_vpshufbitqmb128_mask" + | "__builtin_ia32_vpshufbitqmb256_mask" + | "__builtin_ia32_vpshufbitqmb512_mask" => { let new_args = args.to_vec(); let arg3_type = gcc_func.get_param_type(2); let minus_one = builder.context.new_rvalue_from_int(arg3_type, -1); @@ -867,6 +891,25 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( &[random_number, success_variable.to_rvalue()], ); } + "__builtin_ia32_2intersectd128" + | "__builtin_ia32_2intersectq128" + | "__builtin_ia32_2intersectd256" + | "__builtin_ia32_2intersectq256" + | "__builtin_ia32_2intersectd512" + | "__builtin_ia32_2intersectq512" => { + let first_mask = args[0].dereference(None).to_rvalue(); + let second_mask = args[1].dereference(None).to_rvalue(); + let field1 = builder.context.new_field(None, first_mask.get_type(), "first_mask"); + let field2 = builder.context.new_field(None, second_mask.get_type(), "second_mask"); + let struct_type = + builder.context.new_struct_type(None, "vp2intersect_result", &[field1, field2]); + return_value = builder.context.new_struct_constructor( + None, + struct_type.as_type(), + None, + &[first_mask, second_mask], + ); + } "fma" => { let f16_type = builder.context.new_c_type(CType::Float16); return_value = builder.context.new_cast(None, return_value, f16_type); @@ -1195,6 +1238,9 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.mask.vpshufbitqmb.512" => "__builtin_ia32_vpshufbitqmb512_mask", "llvm.x86.avx512.mask.vpshufbitqmb.256" => "__builtin_ia32_vpshufbitqmb256_mask", "llvm.x86.avx512.mask.vpshufbitqmb.128" => "__builtin_ia32_vpshufbitqmb128_mask", + "llvm.x86.avx512.vpshufbitqmb.512" => "__builtin_ia32_vpshufbitqmb512_mask", + "llvm.x86.avx512.vpshufbitqmb.256" => "__builtin_ia32_vpshufbitqmb256_mask", + "llvm.x86.avx512.vpshufbitqmb.128" => "__builtin_ia32_vpshufbitqmb128_mask", "llvm.x86.avx512.mask.ucmp.w.512" => "__builtin_ia32_ucmpw512_mask", "llvm.x86.avx512.mask.ucmp.w.256" => "__builtin_ia32_ucmpw256_mask", "llvm.x86.avx512.mask.ucmp.w.128" => "__builtin_ia32_ucmpw128_mask", @@ -1352,11 +1398,20 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512bf16.cvtne2ps2bf16.128" => "__builtin_ia32_cvtne2ps2bf16_v8bf", "llvm.x86.avx512bf16.cvtne2ps2bf16.256" => "__builtin_ia32_cvtne2ps2bf16_v16bf", "llvm.x86.avx512bf16.cvtne2ps2bf16.512" => "__builtin_ia32_cvtne2ps2bf16_v32bf", + "llvm.x86.vcvtneps2bf16128" => "__builtin_ia32_cvtneps2bf16_v4sf", + "llvm.x86.vcvtneps2bf16256" => "__builtin_ia32_cvtneps2bf16_v8sf", + "llvm.x86.avx512bf16.mask.cvtneps2bf16.128" => "__builtin_ia32_cvtneps2bf16_v4sf_mask", "llvm.x86.avx512bf16.cvtneps2bf16.256" => "__builtin_ia32_cvtneps2bf16_v8sf", "llvm.x86.avx512bf16.cvtneps2bf16.512" => "__builtin_ia32_cvtneps2bf16_v16sf", "llvm.x86.avx512bf16.dpbf16ps.128" => "__builtin_ia32_dpbf16ps_v4sf", "llvm.x86.avx512bf16.dpbf16ps.256" => "__builtin_ia32_dpbf16ps_v8sf", "llvm.x86.avx512bf16.dpbf16ps.512" => "__builtin_ia32_dpbf16ps_v16sf", + "llvm.x86.avx512.vp2intersect.d.128" => "__builtin_ia32_2intersectd128", + "llvm.x86.avx512.vp2intersect.q.128" => "__builtin_ia32_2intersectq128", + "llvm.x86.avx512.vp2intersect.d.256" => "__builtin_ia32_2intersectd256", + "llvm.x86.avx512.vp2intersect.q.256" => "__builtin_ia32_2intersectq256", + "llvm.x86.avx512.vp2intersect.d.512" => "__builtin_ia32_2intersectd512", + "llvm.x86.avx512.vp2intersect.q.512" => "__builtin_ia32_2intersectq512", "llvm.x86.pclmulqdq.512" => "__builtin_ia32_vpclmulqdq_v8di", "llvm.x86.pclmulqdq.256" => "__builtin_ia32_vpclmulqdq_v4di", "llvm.x86.avx512.pmulhu.w.512" => "__builtin_ia32_pmulhuw512_mask", @@ -1601,6 +1656,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.fpclass.pd.256" => "__builtin_ia32_fpclasspd256_mask", "llvm.x86.avx512.fpclass.ps.256" => "__builtin_ia32_fpclassps256_mask", "llvm.x86.avx512.fpclass.pd.512" => "__builtin_ia32_fpclasspd512_mask", + "llvm.x86.avx512.fpclass.ps.512" => "__builtin_ia32_fpclassps512_mask", // FIXME: support the tile builtins: "llvm.x86.ldtilecfg" => "__builtin_trap", @@ -1631,6 +1687,10 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.tcvtrowd2psi" => "__builtin_trap", "llvm.x86.tcvtrowps2phhi" => "__builtin_trap", "llvm.x86.tcvtrowps2phli" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16h" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16hi" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16l" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16li" => "__builtin_trap", "llvm.x86.tcmmimfp16ps" => "__builtin_trap", "llvm.x86.tcmmrlfp16ps" => "__builtin_trap", From d865ac7edc44b73722f60d602ca65b6bd8e3f9cb Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Fri, 29 May 2026 13:30:41 -0300 Subject: [PATCH 033/166] Emit a plain jump for a switch with no cases A `SwitchInt` with only an `otherwise` target reaches the backend as a switch with an empty case list. `gcc_jit_block_end_with_switch` requires an integer discriminant, so it rejects the `bool` discriminant produced by a range-pattern comparison under `-Zmir-preserve-ub`, which keeps the otherwise-simplified switch instead of lowering it to a `goto`. Such a switch is equivalent to an unconditional jump to the default block, so emit that instead. --- src/builder.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/builder.rs b/src/builder.rs index 33f0f6fc2f809..8d047dcfa5a71 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -570,6 +570,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { default_block: Block<'gcc>, cases: impl ExactSizeIterator)>, ) { + // A switch with no cases is equivalent to an unconditional jump to the + // default block. Such a `SwitchInt` (one with only an `otherwise` target) + // is normally simplified into a `goto`, but `-Z mir-preserve-ub` keeps it, + // so it can reach here with e.g. the `bool` discriminant produced by a + // range-pattern comparison. `gcc_jit_block_end_with_switch` rejects a + // discriminant that is not of integer type, so emit a plain jump instead + // of a (pointless) switch. + if cases.len() == 0 { + self.block.end_with_jump(self.location, default_block); + return; + } + let mut gcc_cases = vec![]; let typ = self.val_ty(value); // FIXME(FractalFir): This is a workaround for a libgccjit limitation. From 5dad41cef0341db45fc8bf08bbd3723da6b2026d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 29 May 2026 13:40:25 -0400 Subject: [PATCH 034/166] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index 5eef70260466f..104e5c7e2a0e9 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -6f155cc3f5a2dff33afe6cc3ed6c2e0e605ae6a3 +d98bd412c7fb6bf8f2258e75f2e2b42f56a06bc1 From 86a4fa09969d349a7f6e688101809ed0d1ae6a56 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 29 May 2026 14:32:32 -0400 Subject: [PATCH 035/166] Add cpuid.def to enable the feature AVX512_VP2INTERSECT --- .github/workflows/stdarch.yml | 2 +- tests/cpuid.def | 62 +++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/cpuid.def diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 66f30b147b4c0..34438a097c642 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: cargo_runner: [ - "sde -future -rtm_mode full --", + "sde -cpuid-in /home/runner/work/rustc_codegen_gcc/rustc_codegen_gcc/tests/cpuid.def -rtm_mode full --", "", ] diff --git a/tests/cpuid.def b/tests/cpuid.def new file mode 100644 index 0000000000000..342f7d83a63e3 --- /dev/null +++ b/tests/cpuid.def @@ -0,0 +1,62 @@ +# Copyright (C) 2017-2025 Intel Corporation. +# +# This software and the related documents are Intel copyrighted materials, and your +# use of them is governed by the express license under which they were provided to +# you ("License"). Unless the License provides otherwise, you may not use, modify, +# copy, publish, distribute, disclose or transmit this software or the related +# documents without Intel's prior written permission. +# +# This software and the related documents are provided as is, with no express or +# implied warranties, other than those that are expressly stated in the License. +# +# CPUID_VERSION = 1.0 +# Input => Output +# EAX ECX => EAX EBX ECX EDX +00000000 ******** => 00000024 756e6547 6c65746e 49656e69 +00000001 ******** => 00400f10 00100800 7ffaf3ff bfebfbff +00000002 ******** => 76035a01 00f0b6ff 00000000 00c10000 +00000003 ******** => 00000000 00000000 00000000 00000000 +00000004 00000000 => 7c004121 01c0003f 0000003f 00000000 #Deterministic Cache +00000004 00000001 => 7c004122 01c0003f 0000003f 00000000 +00000004 00000002 => 7c004143 03c0003f 000003ff 00000000 +00000004 00000003 => 7c0fc163 0280003f 0000dfff 00000004 +00000004 00000004 => 00000000 00000000 00000000 00000000 +00000005 ******** => 00000040 00000040 00000003 00042120 #MONITOR/MWAIT +00000006 ******** => 00000077 00000002 00000001 00000000 #Thermal and Power +00000007 00000000 => 00000001 f3bfbfbf bac05ffe 03d54130 #Extended Features +00000007 00000001 => 98ee00bf 00000002 00000020 1d29cd3e +00000008 ******** => 00000000 00000000 00000000 00000000 +00000009 ******** => 00000000 00000000 00000000 00000000 #Direct Cache +0000000a ******** => 07300403 00000000 00000000 00000603 +0000000b 00000000 => 00000001 00000002 00000100 00000000 #Extended Topology +0000000b 00000001 => 00000004 00000002 00000201 00000000 +0000000c ******** => 00000000 00000000 00000000 00000000 +0000000d 00000000 => 000e02e7 00002b00 00002b00 00000000 #xcr0 +0000000d 00000001 => 0000001f 00000240 00000100 00000000 +0000000d 00000002 => 00000100 00000240 00000000 00000000 +0000000d 00000005 => 00000040 00000440 00000000 00000000 #zmasks +0000000d 00000006 => 00000200 00000480 00000000 00000000 #zmmh +0000000d 00000007 => 00000400 00000680 00000000 00000000 #zmm +0000000d 00000011 => 00000040 00000ac0 00000002 00000000 #tileconfig +0000000d 00000012 => 00002000 00000b00 00000006 00000000 #tiles +0000000d 00000013 => 00000080 000003c0 00000000 00000000 #APX +00000014 00000000 => 00000000 00000010 00000000 00000000 #ptwrite +00000019 ******** => 00000000 00000005 00000000 00000000 #Key Locker +0000001d 00000000 => 00000001 00000000 00000000 00000000 #AMX Tile +0000001d 00000001 => 04002000 00080040 00000010 00000000 #AMX Palette1 +0000001e 00000000 => 00000001 00004010 00000000 00000000 #AMX Tmul +0000001e 00000001 => 000001ff 00000000 00000000 00000000 +00000024 00000000 => 00000001 00070002 00000000 00000000 #AVX10 +00000024 00000001 => 00000000 00000000 00000004 00000000 +80000000 ******** => 80000008 00000000 00000000 00000000 +80000001 ******** => 00000000 00000000 00000121 2c100000 +80000002 ******** => 00000000 00000000 00000000 00000000 +80000003 ******** => 00000000 00000000 00000000 00000000 +80000004 ******** => 00000000 00000000 00000000 00000000 +80000005 ******** => 00000000 00000000 00000000 00000000 +80000006 ******** => 00000000 00000000 01006040 00000000 +80000007 ******** => 00000000 00000000 00000000 00000100 +80000008 ******** => 00003028 00000200 00000200 00000000 + +# This file was copied from intel-sde/misc/cpuid/future/cpuid.def, and modified to +# add support for `AVX512_VP2INTERSECT` From 60006c311dd5204b6b3b66728f3b39540e7b9d80 Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Fri, 29 May 2026 16:04:37 -0300 Subject: [PATCH 036/166] Add CARGO_TEST_FLAGS for run-time lang test flags Unlike the compile-time TEST_FLAGS, this is read at run time so a single test can opt into flags such as -Zmir-preserve-ub through an ignore-if directive that checks whether the variable is set. --- tests/lang_tests.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index 6afd54e1c3fe0..e3baf1e038ffc 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -172,6 +172,16 @@ fn build_test_runner( } } + // Extra flags passed at run time (as opposed to the compile-time + // `TEST_FLAGS`). This lets a single test opt into flags like + // `-Zmir-preserve-ub` via an `ignore-if` directive that checks + // whether `CARGO_TEST_FLAGS` is set. + if let Ok(flags) = std::env::var("CARGO_TEST_FLAGS") { + for flag in flags.split_whitespace() { + compiler_args.push(flag.into()); + } + } + if build_mode.is_debug() { compiler_args .extend_from_slice(&["-C".to_string(), "llvm-args=sanitize-undefined".into()]); From fdd3536ce6084ad1d106dbb20c11d04e0b17409d Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Fri, 29 May 2026 16:04:43 -0300 Subject: [PATCH 037/166] Add regression test for empty switch under mir-preserve-ub A range-pattern match compiled with -Zmir-preserve-ub leaves a SwitchInt with no cases whose discriminant is a bool comparison result. The test is skipped unless CARGO_TEST_FLAGS is set so it only runs when that flag is passed. --- tests/run/mir_preserve_ub_empty_switch.rs | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/run/mir_preserve_ub_empty_switch.rs diff --git a/tests/run/mir_preserve_ub_empty_switch.rs b/tests/run/mir_preserve_ub_empty_switch.rs new file mode 100644 index 0000000000000..26056360b9212 --- /dev/null +++ b/tests/run/mir_preserve_ub_empty_switch.rs @@ -0,0 +1,35 @@ +// ignore-if: test -z "$CARGO_TEST_FLAGS" +// Compiler: +// +// Run-time: +// status: 0 + +// Regression test for https://github.com/rust-lang/rustc_codegen_gcc/issues/881 +// +// This needs `-Zmir-preserve-ub`, so it is skipped unless that flag is passed +// through `CARGO_TEST_FLAGS` (see the `ignore-if` directive above). Run it with: +// CARGO_TEST_FLAGS="-Zmir-preserve-ub" ./y.sh test --cargo-tests -- mir_preserve_ub_empty_switch + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use intrinsics::black_box; +use mini_core::*; + +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { + // With `-Zmir-preserve-ub`, the range pattern below is lowered to a pair of + // comparisons and the second one becomes a `SwitchInt` with no cases (only + // an `otherwise` target) whose discriminant is the `bool` comparison + // result. `gcc_jit_block_end_with_switch` rejects a non-integer + // discriminant, so the backend must emit a plain jump for it instead. + let value = black_box(argc); + match value { + 0..=9 => (), + _ => (), + } + 0 +} From a4a9a38d8a0d4164bd40cf5bd6cf7a9b4e63962c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 29 May 2026 14:37:22 +0200 Subject: [PATCH 038/166] Regen intrinsics --- src/intrinsic/archs.rs | 81 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 15 deletions(-) diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 3c1698df6dec2..1f0c1c25ff758 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -24,6 +24,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "gcsss" => "__builtin_arm_gcsss", "isb" => "__builtin_arm_isb", "prefetch" => "__builtin_arm_prefetch", + "prefetch.ir" => "__builtin_arm_prefetch_ir", "range.prefetch" => "__builtin_arm_range_prefetch", "sme.in.streaming.mode" => "__builtin_arm_in_streaming_mode", "sve.aesd" => "__builtin_sve_svaesd_u8", @@ -53,6 +54,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "alignbyte" => "__builtin_amdgcn_alignbyte", "ashr.pk.i8.i32" => "__builtin_amdgcn_ashr_pk_i8_i32", "ashr.pk.u8.i32" => "__builtin_amdgcn_ashr_pk_u8_i32", + "asyncmark" => "__builtin_amdgcn_asyncmark", "buffer.wbinvl1" => "__builtin_amdgcn_buffer_wbinvl1", "buffer.wbinvl1.sc" => "__builtin_amdgcn_buffer_wbinvl1_sc", "buffer.wbinvl1.vol" => "__builtin_amdgcn_buffer_wbinvl1_vol", @@ -270,6 +272,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fdot2c.f32.bf16" => "__builtin_amdgcn_fdot2c_f32_bf16", "flat.prefetch" => "__builtin_amdgcn_flat_prefetch", "fmul.legacy" => "__builtin_amdgcn_fmul_legacy", + "global.load.async.lds" => "__builtin_amdgcn_global_load_async_lds", "global.load.async.to.lds.b128" => { "__builtin_amdgcn_global_load_async_to_lds_b128" } @@ -361,11 +364,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "perm.pk16.b4.u4" => "__builtin_amdgcn_perm_pk16_b4_u4", "perm.pk16.b6.u4" => "__builtin_amdgcn_perm_pk16_b6_u4", "perm.pk16.b8.u4" => "__builtin_amdgcn_perm_pk16_b8_u4", - "permlane.bcast" => "__builtin_amdgcn_permlane_bcast", - "permlane.down" => "__builtin_amdgcn_permlane_down", "permlane.idx.gen" => "__builtin_amdgcn_permlane_idx_gen", - "permlane.up" => "__builtin_amdgcn_permlane_up", - "permlane.xor" => "__builtin_amdgcn_permlane_xor", "permlane16.var" => "__builtin_amdgcn_permlane16_var", "permlanex16.var" => "__builtin_amdgcn_permlanex16_var", "pk.add.max.i16" => "__builtin_amdgcn_pk_add_max_i16", @@ -375,6 +374,9 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "prng.b32" => "__builtin_amdgcn_prng_b32", "qsad.pk.u16.u8" => "__builtin_amdgcn_qsad_pk_u16_u8", "queue.ptr" => "__builtin_amdgcn_queue_ptr", + "raw.ptr.buffer.load.async.lds" => { + "__builtin_amdgcn_raw_ptr_buffer_load_async_lds" + } "raw.ptr.buffer.load.lds" => "__builtin_amdgcn_raw_ptr_buffer_load_lds", "rcp.legacy" => "__builtin_amdgcn_rcp_legacy", "rsq.legacy" => "__builtin_amdgcn_rsq_legacy", @@ -412,6 +414,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.ttracedata" => "__builtin_amdgcn_s_ttracedata", "s.ttracedata.imm" => "__builtin_amdgcn_s_ttracedata_imm", "s.wait.asynccnt" => "__builtin_amdgcn_s_wait_asynccnt", + "s.wait.event" => "__builtin_amdgcn_s_wait_event", "s.wait.event.export.ready" => "__builtin_amdgcn_s_wait_event_export_ready", "s.wait.tensorcnt" => "__builtin_amdgcn_s_wait_tensorcnt", "s.waitcnt" => "__builtin_amdgcn_s_waitcnt", @@ -462,16 +465,18 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "smfmac.i32.16x16x64.i8" => "__builtin_amdgcn_smfmac_i32_16x16x64_i8", "smfmac.i32.32x32x32.i8" => "__builtin_amdgcn_smfmac_i32_32x32x32_i8", "smfmac.i32.32x32x64.i8" => "__builtin_amdgcn_smfmac_i32_32x32x64_i8", + "struct.ptr.buffer.load.async.lds" => { + "__builtin_amdgcn_struct_ptr_buffer_load_async_lds" + } "struct.ptr.buffer.load.lds" => "__builtin_amdgcn_struct_ptr_buffer_load_lds", "sudot4" => "__builtin_amdgcn_sudot4", "sudot8" => "__builtin_amdgcn_sudot8", "tensor.load.to.lds" => "__builtin_amdgcn_tensor_load_to_lds", - "tensor.load.to.lds.d2" => "__builtin_amdgcn_tensor_load_to_lds_d2", "tensor.store.from.lds" => "__builtin_amdgcn_tensor_store_from_lds", - "tensor.store.from.lds.d2" => "__builtin_amdgcn_tensor_store_from_lds_d2", "udot2" => "__builtin_amdgcn_udot2", "udot4" => "__builtin_amdgcn_udot4", "udot8" => "__builtin_amdgcn_udot8", + "wait.asyncmark" => "__builtin_amdgcn_wait_asyncmark", "wave.barrier" => "__builtin_amdgcn_wave_barrier", "wavefrontsize" => "__builtin_amdgcn_wavefrontsize", "workgroup.id.x" => "__builtin_amdgcn_workgroup_id_x", @@ -4844,7 +4849,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "add.rn.f" => "__nvvm_add_rn_f", "add.rn.ftz.f" => "__nvvm_add_rn_ftz_f", "add.rn.ftz.sat.f" => "__nvvm_add_rn_ftz_sat_f", + "add.rn.ftz.sat.f16" => "__nvvm_add_rn_ftz_sat_f16", + "add.rn.ftz.sat.v2f16" => "__nvvm_add_rn_ftz_sat_v2f16", "add.rn.sat.f" => "__nvvm_add_rn_sat_f", + "add.rn.sat.f16" => "__nvvm_add_rn_sat_f16", + "add.rn.sat.v2f16" => "__nvvm_add_rn_sat_v2f16", "add.rp.d" => "__nvvm_add_rp_d", "add.rp.f" => "__nvvm_add_rp_f", "add.rp.ftz.f" => "__nvvm_add_rp_ftz_f", @@ -5063,18 +5072,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fma.rn.bf16x2" => "__nvvm_fma_rn_bf16x2", "fma.rn.d" => "__nvvm_fma_rn_d", "fma.rn.f" => "__nvvm_fma_rn_f", - "fma.rn.ftz.bf16" => "__nvvm_fma_rn_ftz_bf16", - "fma.rn.ftz.bf16x2" => "__nvvm_fma_rn_ftz_bf16x2", "fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f", - "fma.rn.ftz.relu.bf16" => "__nvvm_fma_rn_ftz_relu_bf16", - "fma.rn.ftz.relu.bf16x2" => "__nvvm_fma_rn_ftz_relu_bf16x2", - "fma.rn.ftz.sat.bf16" => "__nvvm_fma_rn_ftz_sat_bf16", - "fma.rn.ftz.sat.bf16x2" => "__nvvm_fma_rn_ftz_sat_bf16x2", "fma.rn.ftz.sat.f" => "__nvvm_fma_rn_ftz_sat_f", "fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16", "fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2", - "fma.rn.sat.bf16" => "__nvvm_fma_rn_sat_bf16", - "fma.rn.sat.bf16x2" => "__nvvm_fma_rn_sat_bf16x2", "fma.rn.sat.f" => "__nvvm_fma_rn_sat_f", "fma.rp.d" => "__nvvm_fma_rp_d", "fma.rp.f" => "__nvvm_fma_rp_f", @@ -5195,6 +5196,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "mul.rn.d" => "__nvvm_mul_rn_d", "mul.rn.f" => "__nvvm_mul_rn_f", "mul.rn.ftz.f" => "__nvvm_mul_rn_ftz_f", + "mul.rn.ftz.sat.f16" => "__nvvm_mul_rn_ftz_sat_f16", + "mul.rn.ftz.sat.v2f16" => "__nvvm_mul_rn_ftz_sat_v2f16", + "mul.rn.sat.f16" => "__nvvm_mul_rn_sat_f16", + "mul.rn.sat.v2f16" => "__nvvm_mul_rn_sat_v2f16", "mul.rp.d" => "__nvvm_mul_rp_d", "mul.rp.f" => "__nvvm_mul_rp_f", "mul.rp.ftz.f" => "__nvvm_mul_rp_ftz_f", @@ -5827,8 +5832,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vmuleuh" => "__builtin_altivec_vmuleuh", "altivec.vmuleuw" => "__builtin_altivec_vmuleuw", "altivec.vmulhsd" => "__builtin_altivec_vmulhsd", + "altivec.vmulhsh" => "__builtin_altivec_vmulhsh", "altivec.vmulhsw" => "__builtin_altivec_vmulhsw", "altivec.vmulhud" => "__builtin_altivec_vmulhud", + "altivec.vmulhuh" => "__builtin_altivec_vmulhuh", "altivec.vmulhuw" => "__builtin_altivec_vmulhuw", "altivec.vmulosb" => "__builtin_altivec_vmulosb", "altivec.vmulosd" => "__builtin_altivec_vmulosd", @@ -5912,22 +5919,45 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vsum4shs" => "__builtin_altivec_vsum4shs", "altivec.vsum4ubs" => "__builtin_altivec_vsum4ubs", "altivec.vsumsws" => "__builtin_altivec_vsumsws", + "altivec.vucmprhb" => "__builtin_altivec_vucmprhb", + "altivec.vucmprhh" => "__builtin_altivec_vucmprhh", + "altivec.vucmprhn" => "__builtin_altivec_vucmprhn", + "altivec.vucmprlb" => "__builtin_altivec_vucmprlb", + "altivec.vucmprlh" => "__builtin_altivec_vucmprlh", + "altivec.vucmprln" => "__builtin_altivec_vucmprln", "altivec.vupkhpx" => "__builtin_altivec_vupkhpx", "altivec.vupkhsb" => "__builtin_altivec_vupkhsb", "altivec.vupkhsh" => "__builtin_altivec_vupkhsh", + "altivec.vupkhsntob" => "__builtin_altivec_vupkhsntob", "altivec.vupkhsw" => "__builtin_altivec_vupkhsw", + "altivec.vupkint4tobf16" => "__builtin_altivec_vupkint4tobf16", + "altivec.vupkint4tofp32" => "__builtin_altivec_vupkint4tofp32", + "altivec.vupkint8tobf16" => "__builtin_altivec_vupkint8tobf16", + "altivec.vupkint8tofp32" => "__builtin_altivec_vupkint8tofp32", "altivec.vupklpx" => "__builtin_altivec_vupklpx", "altivec.vupklsb" => "__builtin_altivec_vupklsb", "altivec.vupklsh" => "__builtin_altivec_vupklsh", + "altivec.vupklsntob" => "__builtin_altivec_vupklsntob", "altivec.vupklsw" => "__builtin_altivec_vupklsw", "amo.ldat" => "__builtin_amo_ldat", + "amo.ldat.cond" => "__builtin_amo_ldat_cond", + "amo.ldat.csne" => "__builtin_amo_ldat_csne", "amo.lwat" => "__builtin_amo_lwat", + "amo.lwat.cond" => "__builtin_amo_lwat_cond", + "amo.lwat.csne" => "__builtin_amo_lwat_csne", + "amo.stdat" => "__builtin_amo_stdat", + "amo.stwat" => "__builtin_amo_stwat", "bcdadd" => "__builtin_ppc_bcdadd", "bcdadd.p" => "__builtin_ppc_bcdadd_p", "bcdcopysign" => "__builtin_ppc_bcdcopysign", "bcdsetsign" => "__builtin_ppc_bcdsetsign", + "bcdshift" => "__builtin_ppc_bcdshift", + "bcdshiftround" => "__builtin_ppc_bcdshiftround", "bcdsub" => "__builtin_ppc_bcdsub", "bcdsub.p" => "__builtin_ppc_bcdsub_p", + "bcdtruncate" => "__builtin_ppc_bcdtruncate", + "bcdunsignedshift" => "__builtin_ppc_bcdunsignedshift", + "bcdunsignedtruncate" => "__builtin_ppc_bcdunsignedtruncate", "bpermd" => "__builtin_bpermd", "cbcdtd" => "__builtin_cbcdtd", "cbcdtdd" => "__builtin_ppc_cbcdtd", @@ -6126,6 +6156,27 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "vsx.xxinsertw" => "__builtin_vsx_xxinsertw", "vsx.xxleqv" => "__builtin_vsx_xxleqv", "vsx.xxpermx" => "__builtin_vsx_xxpermx", + "xsaddaddsuqm" => "__builtin_xsaddaddsuqm", + "xsaddadduqm" => "__builtin_xsaddadduqm", + "xsaddsubsuqm" => "__builtin_xsaddsubsuqm", + "xsaddsubuqm" => "__builtin_xsaddsubuqm", + "xsmerge2t1uqm" => "__builtin_xsmerge2t1uqm", + "xsmerge2t2uqm" => "__builtin_xsmerge2t2uqm", + "xsmerge2t3uqm" => "__builtin_xsmerge2t3uqm", + "xsmerge3t1uqm" => "__builtin_xsmerge3t1uqm", + "xsrebase2t1uqm" => "__builtin_xsrebase2t1uqm", + "xsrebase2t2uqm" => "__builtin_xsrebase2t2uqm", + "xsrebase2t3uqm" => "__builtin_xsrebase2t3uqm", + "xsrebase2t4uqm" => "__builtin_xsrebase2t4uqm", + "xsrebase3t1uqm" => "__builtin_xsrebase3t1uqm", + "xsrebase3t2uqm" => "__builtin_xsrebase3t2uqm", + "xsrebase3t3uqm" => "__builtin_xsrebase3t3uqm", + "xxmulmul" => "__builtin_xxmulmul", + "xxmulmulhiadd" => "__builtin_xxmulmulhiadd", + "xxmulmulloadd" => "__builtin_xxmulmulloadd", + "xxssumudm" => "__builtin_xxssumudm", + "xxssumudmc" => "__builtin_xxssumudmc", + "xxssumudmcext" => "__builtin_xxssumudmcext", "zoned2packed" => "__builtin_ppc_zoned2packed", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } @@ -6388,13 +6439,13 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { // spv "group.memory.barrier.with.group.sync" => "__builtin_spirv_group_barrier", "num.subgroups" => "__builtin_spirv_num_subgroups", + "subgroup.ballot" => "__builtin_spirv_subgroup_ballot", "subgroup.id" => "__builtin_spirv_subgroup_id", "subgroup.local.invocation.id" => { "__builtin_spirv_subgroup_local_invocation_id" } "subgroup.max.size" => "__builtin_spirv_subgroup_max_size", "subgroup.size" => "__builtin_spirv_subgroup_size", - "wave.ballot" => "__builtin_spirv_subgroup_ballot", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } From a2d570d57d2bd77fc036992b83cddd1011ff5318 Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Sat, 30 May 2026 15:01:26 -0300 Subject: [PATCH 039/166] Run the mir-preserve-ub switch test in CI The test opts into -Zmir-preserve-ub through CARGO_TEST_FLAGS and is skipped when that variable is unset, so the default cargo-tests run never exercises it. Invoke it explicitly with the flag set. --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa9535a3729c3..764ace9167011 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,6 +98,7 @@ jobs: run: | ./y.sh build --sysroot ./y.sh test --cargo-tests + CARGO_TEST_FLAGS="-Zmir-preserve-ub" ./y.sh test --cargo-tests -- mir_preserve_ub_empty_switch - name: Run y.sh cargo build run: | From d66d11db6fad99d68dfafc06a5fd38e21ba775b3 Mon Sep 17 00:00:00 2001 From: Redddy Date: Sun, 8 Mar 2026 01:10:29 +0000 Subject: [PATCH 040/166] Remove TODO in .cspell.json --- .cspell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cspell.json b/.cspell.json index 556432d69a41b..a2856029c2c1a 100644 --- a/.cspell.json +++ b/.cspell.json @@ -22,7 +22,7 @@ "src/intrinsic/llvm.rs" ], "ignoreRegExpList": [ - "/(FIXME|NOTE|TODO)\\([^)]+\\)/", + "/(FIXME|NOTE)\\([^)]+\\)/", "__builtin_\\w*" ] } From 4f811af49c0ff7bf2ddd09bc0b739af0e34a2d62 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 31 May 2026 12:22:46 -0400 Subject: [PATCH 041/166] Add alloc tests --- .github/workflows/ci.yml | 2 +- build_system/src/test.rs | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 764ace9167011..06b0731ca1ce9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - { gcc: "gcc-15.deb" } - { gcc: "gcc-15-without-int128.deb" } commands: [ - "--std-tests", + "--std-tests --alloc-tests", # FIXME: re-enable asm tests when GCC can emit in the right syntax. # "--asm-tests", "--test-libcore", diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 3f02df8399554..e54705cb34ef0 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -30,6 +30,7 @@ fn get_runners() -> Runners { runners.insert("--test-failing-rustc", ("Run failing rustc tests", test_failing_rustc)); runners.insert("--projects", ("Run the tests of popular crates", test_projects)); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); + runners.insert("--alloc-tests", ("Run alloc tests", test_alloc)); runners.insert("--clean", ("Empty cargo target directory", clean)); runners.insert("--build-sysroot", ("Build sysroot", build_sysroot)); runners.insert("--std-tests", ("Run std tests", std_tests)); @@ -764,6 +765,16 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } +fn test_alloc(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] alloc"); + let path = get_sysroot_dir().join("sysroot_src/library/alloctests"); + let _ = remove_dir_all(path.join("target")); + // FIXME(antoyo): run in release mode when we fix the failures. + run_cargo_command(&[&"test"], Some(&path), env, args)?; + Ok(()) +} + fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { println!("Not using GCC master branch. Skipping `extended_rand_tests`."); From c5097de2b4d1ee699afc19f5f0548abe55c02598 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 31 May 2026 19:32:42 -0400 Subject: [PATCH 042/166] Add support for output operand in asm goto --- libgccjit.version | 2 +- src/asm.rs | 6 ++++++ tests/run/asm.rs | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index 104e5c7e2a0e9..e247ce7d3bb16 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -d98bd412c7fb6bf8f2258e75f2e2b42f56a06bc1 +2f06e64df0dc15f861f77595b77bfc2ba5deb59d diff --git a/src/asm.rs b/src/asm.rs index f4b2934178a2c..a61963f7f7988 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -592,6 +592,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { self.llbb().add_eval(None, self.context.new_call(None, builtin_unreachable, &[])); } + if !options.contains(InlineAsmOptions::NORETURN) + && let Some(dest) = dest + { + self.switch_to_block(dest); + } + // Write results to outputs. // // We need to do this because: diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 2d78f5ad5f99c..adbf8465b171e 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -3,6 +3,8 @@ // Run-time: // status: 0 +#![feature(asm_goto_with_outputs)] + #[cfg(target_arch = "x86_64")] use std::arch::{asm, global_asm}; @@ -32,6 +34,20 @@ pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) { ); } +#[cfg(target_arch = "x86_64")] +#[unsafe(no_mangle)] +pub fn asm_goto_test(mut a: i16) -> i16 { + unsafe { + std::arch::asm!( + "jmp {op}", + inout("eax") a, + op = label { a = 7; }, + options(nostack,nomem) + ); + a + } +} + #[cfg(target_arch = "x86_64")] fn asm() { unsafe { @@ -235,6 +251,8 @@ fn asm() { out("r15b") _, ); } + + asm_goto_test(0); } #[cfg(not(target_arch = "x86_64"))] From c1dd71ec6b18ff0132701acdf4911577a0a49fb6 Mon Sep 17 00:00:00 2001 From: Redddy Date: Sat, 7 Mar 2026 10:47:36 +0000 Subject: [PATCH 043/166] Add TODO checker --- .github/workflows/ci.yml | 3 ++ build_system/src/main.rs | 7 +++- build_system/src/todo.rs | 72 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 build_system/src/todo.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 764ace9167011..66caa181573fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,6 +88,9 @@ jobs: - name: Check formatting run: ./y.sh fmt --check + - name: Check todo + run: ./y.sh check-todo + - name: clippy run: | cargo clippy --all-targets -- -D warnings diff --git a/build_system/src/main.rs b/build_system/src/main.rs index ae975c94fff25..150239cbbb421 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -12,6 +12,7 @@ mod prepare; mod rust_tools; mod rustc_info; mod test; +mod todo; mod utils; const BUILD_DIR: &str = "build"; @@ -45,7 +46,8 @@ Commands: clone-gcc : Clones the GCC compiler from a specified source. fmt : Runs rustfmt fuzz : Fuzzes `cg_gcc` using rustlantis - abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM" + abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM + check-todo : Checks todo in the project" ); } @@ -61,6 +63,7 @@ pub enum Command { Fmt, Fuzz, AbiTest, + CheckTodo, } fn main() { @@ -80,6 +83,7 @@ fn main() { Some("info") => Command::Info, Some("clone-gcc") => Command::CloneGcc, Some("abi-test") => Command::AbiTest, + Some("check-todo") => Command::CheckTodo, Some("fmt") => Command::Fmt, Some("fuzz") => Command::Fuzz, Some("--help") => { @@ -106,6 +110,7 @@ fn main() { Command::Fmt => fmt::run(), Command::Fuzz => fuzz::run(), Command::AbiTest => abi_test::run(), + Command::CheckTodo => todo::run(), } { eprintln!("Command failed to run: {e}"); process::exit(1); diff --git a/build_system/src/todo.rs b/build_system/src/todo.rs new file mode 100644 index 0000000000000..5b89410844788 --- /dev/null +++ b/build_system/src/todo.rs @@ -0,0 +1,72 @@ +use std::ffi::OsStr; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::{Path, PathBuf}; +use std::process::Command; + +const EXTENSIONS: &[&str] = + &["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "toml", "yml", "yaml"]; + +fn has_supported_extension(path: &Path) -> bool { + path.extension().is_some_and(|ext| EXTENSIONS.iter().any(|e| ext == OsStr::new(e))) +} + +fn list_tracked_files() -> Result, String> { + let output = Command::new("git") + .args(["ls-files", "-z"]) + .output() + .map_err(|e| format!("Failed to run `git ls-files`: {e}"))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(format!("`git ls-files` failed: {stderr}")); + } + + let mut files = Vec::new(); + for entry in output.stdout.split(|b| *b == 0) { + if entry.is_empty() { + continue; + } + let path = std::str::from_utf8(entry).unwrap(); + files.push(PathBuf::from(path)); + } + + Ok(files) +} + +pub(crate) fn run() -> Result<(), String> { + let files = list_tracked_files()?; + let mut error_count = 0; + // Avoid embedding the task marker in source so greps only find real occurrences. + let todo_marker = "todo".to_ascii_uppercase(); + + for file in files { + if !has_supported_extension(&file) { + continue; + } + + let file_handle = + File::open(&file).map_err(|e| format!("Failed to open {}: {e}", file.display()))?; + let reader = BufReader::new(file_handle); + + for (i, line) in reader.lines().enumerate() { + let line = line.map_err(|e| format!("Failed to read {}: {e}", file.display()))?; + let trimmed = line.trim(); + if trimmed.contains(&todo_marker) { + eprintln!( + "{}:{}: {} is used for tasks that should be done before merging a PR; if you want to leave a message in the codebase use FIXME", + file.display(), + i + 1, + todo_marker + ); + error_count += 1; + } + } + } + + if error_count == 0 { + return Ok(()); + } + + Err(format!("found {} {}(s)", error_count, todo_marker)) +} From feb1d32c209d4d1a60ed8677f7b99f718f20b6f4 Mon Sep 17 00:00:00 2001 From: Redddy Date: Mon, 1 Jun 2026 12:06:51 +0000 Subject: [PATCH 044/166] Update FIXME link to int_traits in comment --- src/int.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/int.rs b/src/int.rs index dfae4eceebe44..8b84d7176cf62 100644 --- a/src/int.rs +++ b/src/int.rs @@ -862,7 +862,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.bitwise_operation(BinaryOp::BitwiseOr, a, b, loc) } - // FIXME(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/master/src/int/mod.rs#L379 instead? + // FIXME(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/1a99c2aa295bb2d507fa0e67a3b5eef64fba92a0/libm/src/math/support/int_traits.rs#L485 instead? pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { let value_type = value.get_type(); if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type) From c3101c0fd0bcd503cd90c955501bd3f572134faf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 29 May 2026 15:45:10 -0700 Subject: [PATCH 045/166] Use a `ArrayVec` in `CastTarget` This commit switches a fixed-size list of `[Option; 8]` to instead holding `ArrayVec` in the `CastTarget` type used when calculating ABIs. This is inspired by [discussion on Zulip][link] where I'm hoping to in the near future extend the usage of this to possibly beyond 8 elements for a new WebAssembly ABI taking advantage of multi-value. For now though this mostly just switches to array/slice-like idioms of accessors rather than dealing with `Option` as the unit. [link]: https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/Using.20.60ArgAbi.3A.3Amake_direct_deprecated.60/with/598607139 --- src/abi.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 7239a5bcb0413..fb243ff842c83 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -46,7 +46,7 @@ impl GccType for CastTarget { ) }; - if self.prefix.iter().all(|x| x.is_none()) { + if self.prefix.is_empty() { // Simplify to a single unit when there is no prefix and size <= unit size if self.rest.total <= self.rest.unit.size { return rest_gcc_unit; @@ -62,7 +62,7 @@ impl GccType for CastTarget { let mut args: Vec<_> = self .prefix .iter() - .flat_map(|option_reg| option_reg.map(|reg| reg.gcc_type(cx))) + .map(|reg| reg.gcc_type(cx)) .chain((0..rest_count).map(|_| rest_gcc_unit)) .collect(); From b3197a883181636c00f7c38fbf1392ae74551849 Mon Sep 17 00:00:00 2001 From: moses7054 Date: Fri, 5 Jun 2026 13:16:47 +0530 Subject: [PATCH 046/166] add stdarch-tests command --- build_system/src/test.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index e54705cb34ef0..dd04cf1bd3ebf 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -45,6 +45,7 @@ fn get_runners() -> Runners { runners.insert("--mini-tests", ("Run mini tests", mini_tests)); runners.insert("--cargo-tests", ("Run cargo tests", cargo_tests)); runners.insert("--no-builtins-tests", ("Test #![no_builtins] attribute", no_builtins_tests)); + runners.insert("--stdarch-tests", ("Run stdarch tests", test_stdarch as Runner)); runners } @@ -765,6 +766,23 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } +fn test_stdarch(env: &Env, args: &TestArg) -> Result<(), String> { + println!("[TEST] stdarch"); + let manifest_path = get_sysroot_dir().join("sysroot_src/library/stdarch/Cargo.toml"); + let mut env = env.clone(); + + // `config.setup` already baked `CG_RUSTFLAGS` into `RUSTFLAGS`, so append the lint-allow to + // `RUSTFLAGS` directly (which `run_cargo_command` also propagates to `RUSTDOCFLAGS`). + let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); + env.insert( + "RUSTFLAGS".to_string(), + format!("{rustflags} -Ainternal_features").trim().to_owned(), + ); + env.insert("TARGET".to_string(), args.config_info.target_triple.clone()); + run_cargo_command(&[&"test", &"--manifest-path", &manifest_path], None, &env, args)?; + Ok(()) +} + fn test_alloc(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] alloc"); From 2688bb0dbfdf1a677451b94a255753d1a3936d42 Mon Sep 17 00:00:00 2001 From: moses7054 Date: Fri, 5 Jun 2026 13:38:28 +0530 Subject: [PATCH 047/166] Use stdarch-tests command in stdarch CI --- .github/workflows/stdarch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 34438a097c642..1ef1d2be934ae 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -90,7 +90,7 @@ jobs: - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} run: | - CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml + ./y.sh test --release --stdarch-tests - name: Run stdarch tests if: ${{ matrix.cargo_runner }} From 5059de25dcbaada15f337e687251b399945ec6fb Mon Sep 17 00:00:00 2001 From: moses7054 Date: Fri, 5 Jun 2026 20:06:37 +0530 Subject: [PATCH 048/166] Download Intel sde from rust-lang CI mirror --- .github/workflows/stdarch.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 1ef1d2be934ae..a437f06a465d9 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -51,10 +51,9 @@ jobs: mkdir intel-sde cd intel-sde version=10.8.0-2026-03-15 - url_path=915934 dir=sde-external-$version-lin file=$dir.tar.xz - wget https://downloadmirror.intel.com/$url_path/$file + wget http://ci-mirrors.rust-lang.org/$file tar xvf $file sudo mkdir /usr/share/intel-sde sudo cp -r $dir/* /usr/share/intel-sde From d5db9be1cbe86099dd143629bfe2b3b63dccef96 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 27 May 2026 12:22:03 +0200 Subject: [PATCH 049/166] add `extern "tail"` calling convention --- src/abi.rs | 29 ++++++++++++++++++++--------- src/context.rs | 8 ++++---- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index fb243ff842c83..1b7bb8c907735 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -10,7 +10,7 @@ use rustc_middle::bug; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] -use rustc_session::config; +use rustc_session::{Session, config}; use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; #[cfg(feature = "master")] use rustc_target::spec::Arch; @@ -230,32 +230,43 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { #[cfg(feature = "master")] fn gcc_cconv(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Option> { - conv_to_fn_attribute(self.conv, &cx.tcx.sess.target.arch) + conv_to_fn_attribute(cx.sess(), self.conv) } } #[cfg(feature = "master")] -pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &Arch) -> Option> { +pub fn conv_to_fn_attribute<'gcc>(sess: &Session, conv: CanonAbi) -> Option> { let attribute = match conv { CanonAbi::C | CanonAbi::Rust => return None, - // gcc/gccjit does not have anything for this. - CanonAbi::RustPreserveNone => return None, + CanonAbi::RustPreserveNone => { + // This calling convention is LLVM-specific and unspecified. + sess.dcx() + .fatal("gcc/gccjit backend does not support RustPreserveNone calling convention") + } + CanonAbi::RustTail => { + // This calling convention is LLVM-specific and unspecified. + sess.dcx().fatal("gcc/gccjit backend does not support RustTail calling convention") + } CanonAbi::RustCold => FnAttribute::Cold, // Functions with this calling convention can only be called from assembly, but it is // possible to declare an `extern "custom"` block, so the backend still needs a calling // convention for declaring foreign functions. CanonAbi::Custom => return None, - // gcc/gccjit does not have anything for Swift's calling convention. - CanonAbi::Swift => panic!("gcc/gccjit backend does not support Swift calling convention"), + CanonAbi::Swift => { + // gcc/gccjit does not have anything for Swift's calling convention. + sess.dcx().fatal("gcc/gccjit backend does not support Swift calling convention") + } CanonAbi::Arm(arm_call) => match arm_call { ArmCall::CCmseNonSecureCall => FnAttribute::ArmCmseNonsecureCall, ArmCall::CCmseNonSecureEntry => FnAttribute::ArmCmseNonsecureEntry, ArmCall::Aapcs => FnAttribute::ArmPcs("aapcs"), }, - CanonAbi::GpuKernel => match arch { + CanonAbi::GpuKernel => match &sess.target.arch { &Arch::AmdGpu => FnAttribute::GcnAmdGpuHsaKernel, &Arch::Nvptx64 => FnAttribute::NvptxKernel, - arch => panic!("Arch {arch} does not support GpuKernel calling convention"), + arch => sess + .dcx() + .fatal(format!("Arch {arch} does not support GpuKernel calling convention")), }, // FIXME(antoyo): check if those AVR attributes are mapped correctly. CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind { diff --git a/src/context.rs b/src/context.rs index ed313859aeafa..ea71546ea1c0e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -486,10 +486,10 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn declare_c_main(&self, fn_type: Self::Type) -> Option { let entry_name = self.sess().target.entry_name.as_ref(); if !self.functions.borrow().contains_key(entry_name) { - #[cfg(feature = "master")] - let conv = conv_to_fn_attribute(self.sess().target.entry_abi, &self.sess().target.arch); - #[cfg(not(feature = "master"))] - let conv = None; + let conv = cfg_select! { + feature = "master" => conv_to_fn_attribute(self.sess(), self.sess().target.entry_abi), + _ => None, + }; Some(self.declare_entry_fn(entry_name, fn_type, conv)) } else { // If the symbol already exists, it is an error: for example, the user wrote From 774e911f18265d841d82d1445261c801c6671047 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:01:07 +0000 Subject: [PATCH 050/166] Use WorkProductMap instead of FxIndexMap This is an UnordMap internally. Iteration order for the work product map should not matter aside from the place it is serialized where sorting by WorkProductId is sufficient. --- src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9669f40166287..850b67c7b25af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -89,11 +89,10 @@ use rustc_codegen_ssa::base::codegen_crate; use rustc_codegen_ssa::target_features::cfg_target_feature; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods}; use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, TargetConfig}; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; @@ -301,7 +300,7 @@ impl CodegenBackend for GccCodegenBackend { sess: &Session, _outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, FxIndexMap) { + ) -> (CompiledModules, WorkProductMap) { ongoing_codegen .downcast::>() .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") From 5fb3b38f6a8096cd786122078b01866d56928153 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Fri, 3 Oct 2025 16:50:06 +0100 Subject: [PATCH 051/166] asm! support for the Xtensa architecture Co-authored-by: Taiki Endo Co-authored-by: Kerry Jones --- src/asm.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/asm.rs b/src/asm.rs index 5bb65365ad6ad..e4b75dc462ba1 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -751,6 +751,11 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { | X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::tmm_reg, ) => unreachable!("clobber-only"), + InlineAsmRegClass::Xtensa(XtensaInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Xtensa(XtensaInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::Xtensa( + XtensaInlineAsmRegClass::sreg | XtensaInlineAsmRegClass::breg, + ) => unreachable!("clobber-only"), InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("GCC backend does not support SPIR-V") } @@ -872,6 +877,11 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("GCC backend does not support SPIR-V") } + InlineAsmRegClass::Xtensa(XtensaInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Xtensa(XtensaInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::Xtensa( + XtensaInlineAsmRegClass::sreg | XtensaInlineAsmRegClass::breg, + ) => unreachable!("clobber-only"), InlineAsmRegClass::Err => unreachable!(), } } @@ -1070,6 +1080,7 @@ fn modifier_to_gcc( InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } + InlineAsmRegClass::Xtensa(_) => None, InlineAsmRegClass::Err => unreachable!(), } } From 92029523af40d33b933aab1b08fbfbab01400277 Mon Sep 17 00:00:00 2001 From: Flakebi Date: Wed, 3 Jun 2026 09:51:47 +0200 Subject: [PATCH 052/166] Add inline asm support for amdgpu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for inline assembly for the amdgpu backend (the amdgcn-amd-amdhsa target). Add register classes for `vgpr` (vector general purpose register) and `sgpr` (scalar general purpose register). The LLVM backend supports two more classes, `reg`, which is either VGPR or SGPR, up to the compiler to decide. As instructions often rely on a register being either a VGPR or SGPR for the assembly to be valid, reg doesn’t seem that useful (I struggled to write correct tests for it), so I didn’t end up adding it. The fourth register class is AGPRs, which only exist on some hardware versions (not the consumer ones) and they have restricted ways to write and read from them, which makes it hard to write a Rust variable into them. They could be used inside assembly blocks, but I didn’t add them as Rust register class. There are a few change affecting general inline assembly code, that is `InlineAsmReg::name()` now returns a `Cow` instead of a `&'static str`. Because amdgpu has many registers, 256 VGPRs plus combinations of 2 or 4 VGPRs, and I didn’t want to list hundreds of static strings, the amdgpu reg stores the register number(s) and a non-static String is generated at runtime for the register name. Similar for register classes and supported_types. Vectors of 64-bit types are supported by the LLVM backend, but omitted here to make the code simpler. There is currently no systematic support in LLVM of which vectors of 64-bit types are supported. Also, they are likely seldomly unused, vectors of 16- and 32-bit types are important. --- src/asm.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/asm.rs b/src/asm.rs index e4b75dc462ba1..53074e313f9ce 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -677,6 +677,8 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } + InlineAsmRegClass::Amdgpu(AmdgpuInlineAsmRegClass::Sgpr(_)) => "Sg", + InlineAsmRegClass::Amdgpu(AmdgpuInlineAsmRegClass::Vgpr(_)) => "v", InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) @@ -785,6 +787,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } + InlineAsmRegClass::Amdgpu(_) => cx.type_i32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(), @@ -993,6 +996,7 @@ fn modifier_to_gcc( InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } + InlineAsmRegClass::Amdgpu(_) => None, InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => None, InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => None, From ef638de1a5f1c9caf632aa6deffbc22772c2cd42 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Wed, 10 Jun 2026 15:11:57 +0000 Subject: [PATCH 053/166] Move create_scope_map to rustc_codegen_ssa. --- src/debuginfo.rs | 151 ++++------------------------------------------- src/lib.rs | 1 - 2 files changed, 12 insertions(+), 140 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index cf938a3988ce7..8907d8a42b38f 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -3,13 +3,9 @@ use std::sync::Arc; use gccjit::{Function, Location, RValue}; use rustc_abi::Size; -use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; +use rustc_codegen_ssa::mir::debuginfo::VariableKind; use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; -use rustc_index::bit_set::DenseBitSet; -use rustc_index::{Idx, IndexVec}; -use rustc_middle::mir::{self, Body, SourceScope}; use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty}; -use rustc_session::config::DebugInfo; use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol}; use rustc_target::callconv::FnAbi; @@ -65,115 +61,6 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } } -/// Generate the `debug_context` in an MIR Body. -/// # Source of Origin -/// Copied from `create_scope_map.rs` of rustc_codegen_llvm -fn compute_mir_scopes<'gcc, 'tcx>( - cx: &CodegenCx<'gcc, 'tcx>, - instance: Instance<'tcx>, - mir: &Body<'tcx>, - debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>, -) { - // Find all scopes with variables defined in them. - let variables = if cx.sess().opts.debuginfo == DebugInfo::Full { - let mut vars = DenseBitSet::new_empty(mir.source_scopes.len()); - // FIXME(eddyb) take into account that arguments always have debuginfo, - // irrespective of their name (assuming full debuginfo is enabled). - // NOTE(eddyb) actually, on second thought, those are always in the - // function scope, which always exists. - for var_debug_info in &mir.var_debug_info { - vars.insert(var_debug_info.source_info.scope); - } - Some(vars) - } else { - // Nothing to emit, of course. - None - }; - let mut instantiated = DenseBitSet::new_empty(mir.source_scopes.len()); - // Instantiate all scopes. - for idx in 0..mir.source_scopes.len() { - let scope = SourceScope::new(idx); - make_mir_scope(cx, instance, mir, &variables, debug_context, &mut instantiated, scope); - } - assert!(instantiated.count() == mir.source_scopes.len()); -} - -/// Update the `debug_context`, adding new scope to it, -/// if it's not added as is denoted in `instantiated`. -/// -/// # Source of Origin -/// Copied from `create_scope_map.rs` of rustc_codegen_llvm -/// FIXME(tempdragon/?): Add Scope Support Here. -fn make_mir_scope<'gcc, 'tcx>( - cx: &CodegenCx<'gcc, 'tcx>, - _instance: Instance<'tcx>, - mir: &Body<'tcx>, - variables: &Option>, - debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>, - instantiated: &mut DenseBitSet, - scope: SourceScope, -) { - if instantiated.contains(scope) { - return; - } - - let scope_data = &mir.source_scopes[scope]; - let parent_scope = if let Some(parent) = scope_data.parent_scope { - make_mir_scope(cx, _instance, mir, variables, debug_context, instantiated, parent); - debug_context.scopes[parent] - } else { - // The root is the function itself. - let file = cx.sess().source_map().lookup_source_file(mir.span.lo()); - debug_context.scopes[scope] = DebugScope { - file_start_pos: file.start_pos, - file_end_pos: file.end_position(), - ..debug_context.scopes[scope] - }; - instantiated.insert(scope); - return; - }; - - if let Some(ref vars) = *variables - && !vars.contains(scope) - && scope_data.inlined.is_none() - { - // Do not create a DIScope if there are no variables defined in this - // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. - debug_context.scopes[scope] = parent_scope; - instantiated.insert(scope); - return; - } - - let loc = cx.lookup_debug_loc(scope_data.span.lo()); - - // FIXME(tempdragon): Add the scope related code here if the scope is supported. - let dbg_scope = (); - - let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { - // FIXME(eddyb) this doesn't account for the macro-related - // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does. - - // FIXME(tempdragon): Add scope support and then revert to cg_llvm version of this closure - // NOTE: These variables passed () here. - // Changed to comply to clippy. - - /* let callsite_scope = */ - parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); - cx.dbg_loc(/* callsite_scope */ (), parent_scope.inlined_at, callsite_span) - }); - let p_inlined_at = parent_scope.inlined_at; - // FIXME(tempdragon): dbg_scope: Add support for scope extension here. - inlined_at.or(p_inlined_at); - - debug_context.scopes[scope] = DebugScope { - dbg_scope, - inlined_at, - file_start_pos: loc.file.start_pos, - file_end_pos: loc.file.end_position(), - }; - instantiated.insert(scope); -} - /// A source code location used to generate debug information. // FIXME(eddyb) rename this to better indicate it's a duplicate of // `rustc_span::Loc` rather than `DILocation`, perhaps by making @@ -228,33 +115,19 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // FIXME(antoyo) } - fn create_function_debug_context( + fn dbg_create_lexical_block( &self, - instance: Instance<'tcx>, - fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - llfn: Function<'gcc>, - mir: &mir::Body<'tcx>, - ) -> Option> { - if self.sess().opts.debuginfo == DebugInfo::None { - return None; - } - - // Initialize fn debug context (including scopes). - let empty_scope = DebugScope { - dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)), - inlined_at: None, - file_start_pos: BytePos(0), - file_end_pos: BytePos(0), - }; - let mut fn_debug_context = FunctionDebugContext { - scopes: IndexVec::from_elem(empty_scope, mir.source_scopes.as_slice()), - inlined_function_scopes: Default::default(), - }; - - // Fill in all the scopes, with the information from the MIR body. - compute_mir_scopes(self, instance, mir, &mut fn_debug_context); + _pos: BytePos, + _parent_scope: Self::DIScope, + ) -> Self::DIScope { + } - Some(fn_debug_context) + fn dbg_location_clone_with_discriminator( + &self, + loc: Self::DILocation, + _discriminator: u32, + ) -> Option { + Some(loc) } fn extend_scope_to_file( diff --git a/src/lib.rs b/src/lib.rs index 850b67c7b25af..4cc4a2d258d14 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,6 @@ extern crate rustc_data_structures; extern crate rustc_errors; extern crate rustc_fs_util; extern crate rustc_hir; -extern crate rustc_index; #[cfg(feature = "master")] extern crate rustc_interface; extern crate rustc_log; From 9b4d3208277dd5a6514901f4eb315cddcd4496e1 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 8 Jun 2026 21:44:31 +0200 Subject: [PATCH 054/166] remove LLVM `va_end` calls The operation is a no-op, so we skip it. --- src/intrinsic/mod.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 728cd90cf637d..a12116d5b9d39 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -705,10 +705,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc unimplemented!(); } - fn va_end(&mut self, _va_list: RValue<'gcc>) { - // FIXME(antoyo): implement. - } - fn retag_reg(&mut self, _ptr: Self::Value, _info: &RetagInfo) -> Self::Value { unimplemented!() } From 9ff44af040e6605fe1ee20275abe33998dea9d1c Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 22 Jun 2026 14:35:51 +0000 Subject: [PATCH 055/166] codegen_ssa: multiply scalable vec size by `vscale` When emitting a `memcpy` for a scalable vector, the size computed by rustc (`num_vectors * element_count * element_ty`), since rust-lang/rust#157915, needs to be multiplied by `vscale`. --- src/builder.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/builder.rs b/src/builder.rs index 33f0f6fc2f809..8ae4dedff8f28 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1459,6 +1459,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { ); } + fn vscale(&mut self, _: Self::Type) -> Self::Value { + unimplemented!("`rustc_codegen_gcc` doesn't support scalable vectors yet") + } + fn select( &mut self, cond: RValue<'gcc>, From 515a89c86addc7ce2a4291e1910b4a9708ff4bc0 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 23 May 2026 15:27:28 -0700 Subject: [PATCH 056/166] cg_LLVM: Stop needing an alloca for volatile loads And while I'm here, improve the tests to check that the unaligned ones are actually unaligned, since `unaligned_volatile_load::` doesn't actually test anything. --- src/builder.rs | 3 ++- src/intrinsic/mod.rs | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 8ae4dedff8f28..6cbc0054cc015 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -993,7 +993,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { loaded_value.to_rvalue() } - fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> { + fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>, _: Align) -> RValue<'gcc> { + // FIXME(antoyo): set alignment. let ptr = self.context.new_cast(self.location, ptr, ty.make_volatile().make_pointer()); // (FractalFir): We insert a local here, to ensure this volatile load can't move across // blocks. diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index a12116d5b9d39..78a4c7e88c895 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -5,7 +5,7 @@ mod simd; use std::iter; use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; -use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; +use rustc_abi::{Align, BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; use rustc_codegen_ssa::errors::InvalidMonomorphization; @@ -368,8 +368,9 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc sym::volatile_load | sym::unaligned_volatile_load => { let ptr = args[0].immediate(); - let load = self.volatile_load(result.layout.gcc_type(self), ptr); - // FIXME(antoyo): set alignment. + let abi_align = result_layout.align.abi; + let ptr_align = if name == sym::volatile_load { abi_align } else { Align::ONE }; + let load = self.volatile_load(result.layout.gcc_type(self), ptr, ptr_align); if let BackendRepr::Scalar(scalar) = result.layout.backend_repr { self.to_immediate_scalar(load, scalar) } else { From 27da6ce2074fae205d0e46f5dd3c133b632e8fef Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Tue, 23 Jun 2026 21:00:04 +0800 Subject: [PATCH 057/166] rustc_target/asm: add LoongArch LSX/LASX inline asm register support Add support for LoongArch LSX and LASX registers in inline assembly by introducing the `vreg` and `xreg` register classes, along with their associated vector types and operand modifiers. The new register classes are gated behind the `asm_experimental_reg` feature. Also model the overlap between FPU, LSX, and LASX registers so register conflict checking works correctly for aliased registers. --- src/asm.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 53074e313f9ce..6fd7188f656c5 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -706,7 +706,9 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { unreachable!("clobber-only") } InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) + | InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::vreg) + | InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::xreg) => "f", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", @@ -815,6 +817,12 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl } InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::vreg) => { + cx.type_vector(cx.type_i32(), 4) + } + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::xreg) => { + cx.type_vector(cx.type_i32(), 8) + } InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), @@ -1013,7 +1021,22 @@ fn modifier_to_gcc( } } InlineAsmRegClass::Hexagon(_) => None, - InlineAsmRegClass::LoongArch(_) => None, + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => None, + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => modifier, + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::vreg) => { + if modifier.is_none() { + Some('w') + } else { + modifier + } + } + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::xreg) => { + if modifier.is_none() { + Some('u') + } else { + modifier + } + } InlineAsmRegClass::Mips(_) => None, InlineAsmRegClass::Nvptx(_) => None, InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vsreg) => { From 3d3ea2f2131c40f3772eedc0706db5ea8fa14367 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 25 Jun 2026 18:50:36 +0200 Subject: [PATCH 058/166] cg_gcc: Fix Clippy lint fallout --- src/common.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/common.rs b/src/common.rs index dd0064d34bc4a..b9b6e51d3b82c 100644 --- a/src/common.rs +++ b/src/common.rs @@ -58,13 +58,19 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> // or is it using a more efficient representation? match bytes.len() % 8 { 0 => { + debug_assert_eq!( + bytes.len() % 8, + 0, + "bytes length is not a multiple of 8, so bytes.as_chunks will have a remainder" + ); let context = &cx.context; let byte_type = context.new_type::(); let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 8); let elements: Vec<_> = bytes - .chunks_exact(8) - .map(|arr| { - let arr: [u8; 8] = arr.try_into().unwrap(); + .as_chunks::<8>() + .0 + .iter() + .map(|&arr| { context.new_rvalue_from_long( byte_type, // Since we are representing arbitrary byte runs as integers, we need to follow the target @@ -79,13 +85,19 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> context.new_array_constructor(None, typ, &elements) } 4 => { + debug_assert_eq!( + bytes.len() % 4, + 0, + "bytes length is not a multiple of 4, so bytes.as_chunks will have a remainder" + ); let context = &cx.context; let byte_type = context.new_type::(); let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 4); let elements: Vec<_> = bytes - .chunks_exact(4) - .map(|arr| { - let arr: [u8; 4] = arr.try_into().unwrap(); + .as_chunks::<4>() + .0 + .iter() + .map(|&arr| { context.new_rvalue_from_int( byte_type, match cx.sess().target.options.endian { From 59b042d888351807e7c8530d748bec5dc8c06adf Mon Sep 17 00:00:00 2001 From: Jakub Chlanda Date: Fri, 3 Apr 2026 15:05:47 +0000 Subject: [PATCH 059/166] New signature of `get_fn_addr`, teach Rust how to sign fn pointers Allow PAC metadata to be passed to `get_fn_addr` and related API changes. --- src/common.rs | 13 ++++++++++--- src/context.rs | 6 ++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/common.rs b/src/common.rs index dd0064d34bc4a..64f3748e4952e 100644 --- a/src/common.rs +++ b/src/common.rs @@ -2,7 +2,8 @@ use gccjit::{LValue, RValue, ToRValue, Type}; use rustc_abi::Primitive::Pointer; use rustc_abi::{self as abi, HasDataLayout}; use rustc_codegen_ssa::traits::{ - BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods, + BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, PacMetadata, + StaticCodegenMethods, }; use rustc_middle::mir::Mutability; use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar}; @@ -229,7 +230,13 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { None } - fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> { + fn scalar_to_backend_with_pac( + &self, + cv: Scalar, + layout: abi::Scalar, + ty: Type<'gcc>, + _pac: Option, + ) -> RValue<'gcc> { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { Scalar::Int(int) => { @@ -278,7 +285,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { } value } - GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance), + GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance, None), GlobalAlloc::VTable(ty, dyn_ty) => { let alloc = self .tcx diff --git a/src/context.rs b/src/context.rs index ea71546ea1c0e..3a6c415b38963 100644 --- a/src/context.rs +++ b/src/context.rs @@ -5,7 +5,9 @@ use gccjit::{Block, CType, Context, Function, FunctionType, LValue, Location, RV use rustc_abi::{Align, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::errors as ssa_errors; -use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods}; +use rustc_codegen_ssa::traits::{ + BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods, PacMetadata, +}; use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::interpret::Allocation; @@ -398,7 +400,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { get_fn(self, instance) } - fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> { + fn get_fn_addr(&self, instance: Instance<'tcx>, _pac: Option) -> RValue<'gcc> { let func_name = self.tcx.symbol_name(instance).name; let func = if let Some(variable) = self.get_declared_value(func_name) { From cd67c774f0771b8898b04d2ac40d744d4fe47198 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 27 Jun 2026 23:14:21 +0200 Subject: [PATCH 060/166] use `"llvm.prefetch.p0"` instead of `"llvm.prefetch"` LLVM updated the name, the old one still works but stdarch is now using the new one --- src/intrinsic/llvm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index d58697f1bf270..41efe3e8209bf 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1044,7 +1044,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function #[cfg(feature = "master")] pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> { let gcc_name = match name { - "llvm.prefetch" => { + "llvm.prefetch.p0" => { let gcc_name = "__builtin_prefetch"; let func = cx.context.get_builtin_function(gcc_name); cx.functions.borrow_mut().insert(gcc_name.to_string(), func); From cf22ea918d719b235df739e978873c7e6c702715 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 28 Jun 2026 11:11:08 -0400 Subject: [PATCH 061/166] Update to nightly-2026-06-28 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 7860423093bc5..ee95f8e6e1cf9 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-05-28" +channel = "nightly-2026-06-28" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 3120a7a05b23f01937614e486753157d33b18d45 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 28 Jun 2026 11:11:22 -0400 Subject: [PATCH 062/166] Remove useless stdarch patch --- ...1-Add-stdarch-Cargo.toml-for-testing.patch | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 patches/0001-Add-stdarch-Cargo.toml-for-testing.patch diff --git a/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch b/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch deleted file mode 100644 index 3a8c37a8b8d9a..0000000000000 --- a/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 190e26c9274b3c93a9ee3516b395590e6bd9213b Mon Sep 17 00:00:00 2001 -From: None -Date: Sun, 3 Aug 2025 19:54:56 -0400 -Subject: [PATCH] Patch 0001-Add-stdarch-Cargo.toml-for-testing.patch - ---- - library/stdarch/Cargo.toml | 20 ++++++++++++++++++++ - 1 file changed, 20 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..bd6725c ---- /dev/null -+++ b/library/stdarch/Cargo.toml -@@ -0,0 +1,20 @@ -+[workspace] -+resolver = "1" -+members = [ -+ "crates/*", -+ #"examples/" -+] -+exclude = [ -+ "crates/wasm-assert-instr-tests", -+ "rust_programs", -+] -+ -+[profile.release] -+debug = true -+opt-level = 3 -+incremental = true -+ -+[profile.bench] -+debug = 1 -+opt-level = 3 -+incremental = true --- -2.50.1 - From e44da234c71645b9bbecbe724bca473e0d951bb3 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 28 Jun 2026 11:11:45 -0400 Subject: [PATCH 063/166] Fix the debug_assert in bytes_in_context --- src/common.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/common.rs b/src/common.rs index b9b6e51d3b82c..2e6fcf29bbadd 100644 --- a/src/common.rs +++ b/src/common.rs @@ -58,17 +58,12 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> // or is it using a more efficient representation? match bytes.len() % 8 { 0 => { - debug_assert_eq!( - bytes.len() % 8, - 0, - "bytes length is not a multiple of 8, so bytes.as_chunks will have a remainder" - ); let context = &cx.context; let byte_type = context.new_type::(); let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 8); - let elements: Vec<_> = bytes - .as_chunks::<8>() - .0 + let (arrays, remainder) = bytes.as_chunks::<8>(); + debug_assert!(remainder.is_empty()); + let elements: Vec<_> = arrays .iter() .map(|&arr| { context.new_rvalue_from_long( @@ -85,17 +80,12 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> context.new_array_constructor(None, typ, &elements) } 4 => { - debug_assert_eq!( - bytes.len() % 4, - 0, - "bytes length is not a multiple of 4, so bytes.as_chunks will have a remainder" - ); let context = &cx.context; let byte_type = context.new_type::(); let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 4); - let elements: Vec<_> = bytes - .as_chunks::<4>() - .0 + let (arrays, remainder) = bytes.as_chunks::<4>(); + debug_assert!(remainder.is_empty()); + let elements: Vec<_> = arrays .iter() .map(|&arr| { context.new_rvalue_from_int( From 2c9b73d97dbf4a0671b38f0c898de695124f94d1 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 28 Jun 2026 11:36:16 -0400 Subject: [PATCH 064/166] Add failing UI tests --- tests/failing-ui-tests.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index e8a26a90890c1..da6544bb76d44 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -110,4 +110,8 @@ tests/ui/eii/static/cross_crate_decl.rs tests/ui/eii/static/cross_crate_def.rs tests/ui/eii/static/same_address.rs tests/ui/eii/static/simple.rs +tests/ui/eii/static/default.rs +tests/ui/eii/static/default_cross_crate.rs +tests/ui/eii/static/default_explicit.rs +tests/ui/eii/static/default_cross_crate_explicit.rs tests/ui/explicit-tail-calls/default-trait-method.rs From 34418c3d04f13c3753d543a2e4066be8be364d2b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 28 Jun 2026 11:37:24 -0400 Subject: [PATCH 065/166] Add spelling exclusion --- tools/cspell_dicts/rustc_codegen_gcc.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/cspell_dicts/rustc_codegen_gcc.txt b/tools/cspell_dicts/rustc_codegen_gcc.txt index 619221d5260cf..794ebec11c30d 100644 --- a/tools/cspell_dicts/rustc_codegen_gcc.txt +++ b/tools/cspell_dicts/rustc_codegen_gcc.txt @@ -65,6 +65,7 @@ riscv rlib roundevenf rustc +sgpr sitofp sizet spir @@ -75,5 +76,7 @@ uitofp unord uninlined utrunc +vgpr xabort +xtensa zext From 2d86197160b7f6d60a2e05273f36315adc9f50fc Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 28 Jun 2026 13:04:21 -0400 Subject: [PATCH 066/166] Add dummy implementation of more tile intrinsics --- src/intrinsic/llvm.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index b19f63dd077d5..e28b15c708d92 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1662,37 +1662,62 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.ldtilecfg" => "__builtin_trap", "llvm.x86.sttilecfg" => "__builtin_trap", "llvm.x86.tileloadd64" => "__builtin_trap", + "llvm.x86.tileloadd64.internal" => "__builtin_trap", "llvm.x86.tilerelease" => "__builtin_trap", "llvm.x86.tilestored64" => "__builtin_trap", + "llvm.x86.tilestored64.internal" => "__builtin_trap", "llvm.x86.tileloaddrs64" => "__builtin_trap", + "llvm.x86.tileloaddrs64.internal" => "__builtin_trap", "llvm.x86.tileloaddt164" => "__builtin_trap", + "llvm.x86.tileloaddt164.internal" => "__builtin_trap", "llvm.x86.tileloaddrst164" => "__builtin_trap", + "llvm.x86.tileloaddrst164.internal" => "__builtin_trap", "llvm.x86.tilezero" => "__builtin_trap", + "llvm.x86.tilezero.internal" => "__builtin_trap", "llvm.x86.tilemovrow" => "__builtin_trap", + "llvm.x86.tilemovrow.internal" => "__builtin_trap", "llvm.x86.tilemovrowi" => "__builtin_trap", "llvm.x86.tdpbhf8ps" => "__builtin_trap", + "llvm.x86.tdpbhf8ps.internal" => "__builtin_trap", "llvm.x86.tdphbf8ps" => "__builtin_trap", + "llvm.x86.tdphbf8ps.internal" => "__builtin_trap", "llvm.x86.tdpbf8ps" => "__builtin_trap", + "llvm.x86.tdpbf8ps.internal" => "__builtin_trap", "llvm.x86.tdphf8ps" => "__builtin_trap", + "llvm.x86.tdphf8ps.internal" => "__builtin_trap", "llvm.x86.tdpbf16ps" => "__builtin_trap", + "llvm.x86.tdpbf16ps.internal" => "__builtin_trap", "llvm.x86.tdpbssd" => "__builtin_trap", + "llvm.x86.tdpbssd.internal" => "__builtin_trap", "llvm.x86.tdpbsud" => "__builtin_trap", + "llvm.x86.tdpbsud.internal" => "__builtin_trap", "llvm.x86.tdpbusd" => "__builtin_trap", + "llvm.x86.tdpbusd.internal" => "__builtin_trap", "llvm.x86.tdpbuud" => "__builtin_trap", + "llvm.x86.tdpbuud.internal" => "__builtin_trap", "llvm.x86.tdpfp16ps" => "__builtin_trap", + "llvm.x86.tdpfp16ps.internal" => "__builtin_trap", "llvm.x86.tmmultf32ps" => "__builtin_trap", + "llvm.x86.tmmultf32ps.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2phh" => "__builtin_trap", + "llvm.x86.tcvtrowps2phh.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2phl" => "__builtin_trap", + "llvm.x86.tcvtrowps2phl.internal" => "__builtin_trap", "llvm.x86.tcvtrowd2ps" => "__builtin_trap", + "llvm.x86.tcvtrowd2ps.internal" => "__builtin_trap", "llvm.x86.tcvtrowd2psi" => "__builtin_trap", "llvm.x86.tcvtrowps2phhi" => "__builtin_trap", "llvm.x86.tcvtrowps2phli" => "__builtin_trap", "llvm.x86.tcvtrowps2bf16h" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16h.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2bf16hi" => "__builtin_trap", "llvm.x86.tcvtrowps2bf16l" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16l.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2bf16li" => "__builtin_trap", "llvm.x86.tcmmimfp16ps" => "__builtin_trap", + "llvm.x86.tcmmimfp16ps.internal" => "__builtin_trap", "llvm.x86.tcmmrlfp16ps" => "__builtin_trap", + "llvm.x86.tcmmrlfp16ps.internal" => "__builtin_trap", // NOTE: this file is generated by https://github.com/GuillaumeGomez/llvmint/blob/master/generate_list.py _ => map_arch_intrinsic(name), From cf908180f397288070c022adac6ad953fbe0bcc4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 28 Jun 2026 14:37:37 -0400 Subject: [PATCH 067/166] Ignore more tile intrinsic tests --- .github/workflows/stdarch.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index a437f06a465d9..3d2ffa57dff75 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -95,8 +95,8 @@ jobs: if: ${{ matrix.cargo_runner }} run: | # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. - # FIXME: remove --skip test_tile_ when it's implemented. - STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" 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" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ + # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. + STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" 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" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile # Summary job for the merge queue. # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! From adc448406245d5cd18efe73c5905de17f0902f23 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 28 Jun 2026 14:42:06 -0400 Subject: [PATCH 068/166] Add dummy implementation of f16 for m68k CI --- src/type_.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/type_.rs b/src/type_.rs index 5252f93a92ebe..514bcbe3bffd6 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -153,7 +153,7 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { if self.supports_f16_type { return self.context.new_c_type(CType::Float16); } - bug!("unsupported float width 16") + self.u16_type } fn type_f32(&self) -> Type<'gcc> { From 212751edea65b9b0abbd21399b3cbe3594810196 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:27:00 +0200 Subject: [PATCH 069/166] Remove debuginfo_finalize from DebugInfoCodegenMethods It isn't called from cg_ssa. --- src/base.rs | 1 - src/debuginfo.rs | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/base.rs b/src/base.rs index 7658b86a3a200..7a25fc46fd3fc 100644 --- a/src/base.rs +++ b/src/base.rs @@ -7,7 +7,6 @@ use gccjit::{CType, Context, FunctionType, GlobalKind}; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; -use rustc_codegen_ssa::traits::DebugInfoCodegenMethods; use rustc_hir::attrs::{AttributeKind, Linkage}; use rustc_hir::find_attr; use rustc_middle::dep_graph; diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 8907d8a42b38f..7993ababfac95 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -103,6 +103,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { DebugLoc { file, line, col } } } + + pub(crate) fn debuginfo_finalize(&self) { + self.context.set_debug_info(true) + } } impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { @@ -138,10 +142,6 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // FIXME(antoyo): implement. } - fn debuginfo_finalize(&self) { - self.context.set_debug_info(true) - } - fn create_dbg_var( &self, _variable_name: Symbol, From fca34618d1ebb8c7f7b83b6af498e979faabdd0f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:39:43 +0200 Subject: [PATCH 070/166] Move a bunch of debuginfo functions from codegen to builder methods These functions are scoped to a single codegened function --- src/debuginfo.rs | 52 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 7993ababfac95..25ae0f8ffc202 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -16,6 +16,32 @@ pub(super) const UNKNOWN_LINE_NUMBER: u32 = 0; pub(super) const UNKNOWN_COLUMN_NUMBER: u32 = 0; impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { + fn dbg_scope_fn( + &self, + _instance: Instance<'tcx>, + _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + _maybe_definition_llfn: Option>, + ) -> Self::DIScope { + // FIXME(antoyo): implement. + } + + fn dbg_create_lexical_block( + &self, + _pos: BytePos, + _parent_scope: Self::DIScope, + ) -> Self::DIScope { + } + + fn create_dbg_var( + &self, + _variable_name: Symbol, + _variable_type: Ty<'tcx>, + _scope_metadata: Self::DIScope, + _variable_kind: VariableKind, + _span: Span, + ) -> Self::DIVariable { + } + // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). fn dbg_var_addr( @@ -119,13 +145,6 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // FIXME(antoyo) } - fn dbg_create_lexical_block( - &self, - _pos: BytePos, - _parent_scope: Self::DIScope, - ) -> Self::DIScope { - } - fn dbg_location_clone_with_discriminator( &self, loc: Self::DILocation, @@ -142,25 +161,6 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // FIXME(antoyo): implement. } - fn create_dbg_var( - &self, - _variable_name: Symbol, - _variable_type: Ty<'tcx>, - _scope_metadata: Self::DIScope, - _variable_kind: VariableKind, - _span: Span, - ) -> Self::DIVariable { - } - - fn dbg_scope_fn( - &self, - _instance: Instance<'tcx>, - _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - _maybe_definition_llfn: Option>, - ) -> Self::DIScope { - // FIXME(antoyo): implement. - } - fn dbg_loc( &self, _scope: Self::DIScope, From 3ec1773e387937da1e3412df78f4b2f1b3eb354b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:50:50 +0200 Subject: [PATCH 071/166] Move a couple more debuginfo functions from codegen to builder methods These functions are scoped to a single codegened function --- src/debuginfo.rs | 68 ++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 25ae0f8ffc202..efdbc00f95aaf 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -32,6 +32,40 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { ) -> Self::DIScope { } + fn dbg_location_clone_with_discriminator( + &self, + loc: Self::DILocation, + _discriminator: u32, + ) -> Option { + Some(loc) + } + + fn extend_scope_to_file( + &self, + _scope_metadata: Self::DIScope, + _file: &SourceFile, + ) -> Self::DIScope { + // FIXME(antoyo): implement. + } + + fn dbg_loc( + &self, + _scope: Self::DIScope, + _inlined_at: Option, + span: Span, + ) -> Self::DILocation { + let pos = span.lo(); + let DebugLoc { file, line, col } = self.lookup_debug_loc(pos); + match file.name { + rustc_span::FileName::Real(ref name) => self.context.new_location( + name.path(rustc_span::RemapPathScopeComponents::DEBUGINFO).to_string_lossy(), + line as i32, + col as i32, + ), + _ => Location::null(), + } + } + fn create_dbg_var( &self, _variable_name: Symbol, @@ -144,38 +178,4 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { ) { // FIXME(antoyo) } - - fn dbg_location_clone_with_discriminator( - &self, - loc: Self::DILocation, - _discriminator: u32, - ) -> Option { - Some(loc) - } - - fn extend_scope_to_file( - &self, - _scope_metadata: Self::DIScope, - _file: &SourceFile, - ) -> Self::DIScope { - // FIXME(antoyo): implement. - } - - fn dbg_loc( - &self, - _scope: Self::DIScope, - _inlined_at: Option, - span: Span, - ) -> Self::DILocation { - let pos = span.lo(); - let DebugLoc { file, line, col } = self.lookup_debug_loc(pos); - match file.name { - rustc_span::FileName::Real(ref name) => self.context.new_location( - name.path(rustc_span::RemapPathScopeComponents::DEBUGINFO).to_string_lossy(), - line as i32, - col as i32, - ), - _ => Location::null(), - } - } } From 78410baca36f51e6e05ae90d6fce90c8aeed3b88 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 29 Jun 2026 14:10:59 +0200 Subject: [PATCH 072/166] Pass &mut self to all debuginfo builder methods --- src/debuginfo.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index efdbc00f95aaf..5e598e5825d1b 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -17,7 +17,7 @@ pub(super) const UNKNOWN_COLUMN_NUMBER: u32 = 0; impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { fn dbg_scope_fn( - &self, + &mut self, _instance: Instance<'tcx>, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _maybe_definition_llfn: Option>, @@ -26,14 +26,14 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } fn dbg_create_lexical_block( - &self, + &mut self, _pos: BytePos, _parent_scope: Self::DIScope, ) -> Self::DIScope { } fn dbg_location_clone_with_discriminator( - &self, + &mut self, loc: Self::DILocation, _discriminator: u32, ) -> Option { @@ -41,7 +41,7 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } fn extend_scope_to_file( - &self, + &mut self, _scope_metadata: Self::DIScope, _file: &SourceFile, ) -> Self::DIScope { @@ -49,7 +49,7 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } fn dbg_loc( - &self, + &mut self, _scope: Self::DIScope, _inlined_at: Option, span: Span, @@ -67,7 +67,7 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } fn create_dbg_var( - &self, + &mut self, _variable_name: Symbol, _variable_type: Ty<'tcx>, _scope_metadata: Self::DIScope, From 0df4855b840395bc0a8e00dcdca96a382937025d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 28 Jun 2026 22:01:18 -0700 Subject: [PATCH 073/166] Rename `align` to `platform_align` on `Scalar` and `Primitive` To emphasize that just because you see a `Scalar(I32)` that doesn't really tell you anything about the alignment it has -- one should be looking at the type (well, the place) for that. No actual layout or behaviour changes in *this* PR. --- src/builder.rs | 2 +- src/type_of.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 8ae4dedff8f28..bea2b3d483b73 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1064,7 +1064,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { }, ) } else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr { - let b_offset = a.size(self).align_to(b.align(self).abi); + let b_offset = a.size(self).align_to(b.default_align(self).abi); let mut load = |i, scalar: &abi::Scalar, align| { let ptr = if i == 0 { diff --git a/src/type_of.rs b/src/type_of.rs index 5b198eeaf0182..9807a84c0788d 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -325,7 +325,8 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { return cx.type_i1(); } - let offset = if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.align(cx).abi) }; + let offset = + if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.default_align(cx).abi) }; self.scalar_gcc_type_at(cx, scalar, offset) } From 08f0607f602427006c98d7718dd7f4c2a7fb7d79 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 29 Jun 2026 23:23:33 +0200 Subject: [PATCH 074/166] Regenerate intrinsics --- src/intrinsic/archs.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 1f0c1c25ff758..1856c2468616d 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -388,6 +388,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.barrier.signal.isfirst" => "__builtin_amdgcn_s_barrier_signal_isfirst", "s.barrier.signal.var" => "__builtin_amdgcn_s_barrier_signal_var", "s.barrier.wait" => "__builtin_amdgcn_s_barrier_wait", + "s.bitreplicate" => "__builtin_amdgcn_s_bitreplicate", "s.buffer.prefetch.data" => "__builtin_amdgcn_s_buffer_prefetch_data", "s.cluster.barrier" => "__builtin_amdgcn_s_cluster_barrier", "s.dcache.inv" => "__builtin_amdgcn_s_dcache_inv", @@ -8712,10 +8713,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "bmi.bextr.64" => "__builtin_ia32_bextr_u64", "bmi.bzhi.32" => "__builtin_ia32_bzhi_si", "bmi.bzhi.64" => "__builtin_ia32_bzhi_di", - "bmi.pdep.32" => "__builtin_ia32_pdep_si", - "bmi.pdep.64" => "__builtin_ia32_pdep_di", - "bmi.pext.32" => "__builtin_ia32_pext_si", - "bmi.pext.64" => "__builtin_ia32_pext_di", "cldemote" => "__builtin_ia32_cldemote", "clflushopt" => "__builtin_ia32_clflushopt", "clrssbsy" => "__builtin_ia32_clrssbsy", From 59efe30999a2451bf68b54c6bd40eb0caecb9b98 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 29 Jun 2026 23:43:29 +0200 Subject: [PATCH 075/166] Directly generate correctly formatted intrinsics file --- tools/generate_intrinsics.py | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 5390323407779..06425f682a88b 100644 --- a/tools/generate_intrinsics.py +++ b/tools/generate_intrinsics.py @@ -84,6 +84,10 @@ def update_intrinsics(llvm_path): # This speeds up the comparison, and makes our code considerably smaller. # Since all intrinsic names start with "llvm.", we skip that prefix. print("Updating content of `{}`...".format(output_file)) + indent4 = " " + indent8 = indent4 + indent4 + indent12 = indent8 + indent4 + indent16 = indent12 + indent4 with open(output_file, "w", encoding="utf8") as out: out.write("""// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py` // DO NOT EDIT IT! @@ -95,33 +99,35 @@ def update_intrinsics(llvm_path): if let ArchCheckResult::Ok(res) = old_arch_res { return res; } -match arch {""") + match arch { +""") for arch in archs: if len(intrinsics[arch]) == 0: continue attribute = "#[expect(non_snake_case)]" if arch[0].isupper() else "" - out.write("\"{}\" => {{ {} fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch, attribute, arch)) + out.write(f"""{indent4}"{arch}" => {{ +{indent8}{attribute} fn {arch}(name: &str,full_name:&str) -> &'static str {{ +{indent12}match name {{""") intrinsics[arch].sort(key=lambda x: (x[0], x[1])) - out.write(' // {}\n'.format(arch)) + out.write(f'{indent16}// {arch}\n') for entry in intrinsics[arch]: llvm_name = entry[0].removeprefix("llvm."); llvm_name = llvm_name.removeprefix(arch); llvm_name = llvm_name.removeprefix("."); if "_round_mask" in entry[1]: - out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1])) + out.write(f'{indent16}// [INVALID CONVERSION]: "{llvm_name}" => "{entry[1]}",\n') else: - out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1])) - out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n') - out.write("}} }} {}(name,full_name) }}\n,".format(arch)) - out.write(""" _ => { - match old_arch_res { - ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), - ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}"), - ArchCheckResult::Ok(_) => unreachable!(), - } - }""") + out.write(f'{indent16}"{llvm_name}" => "{entry[1]}",\n') + out.write(f'{indent16}_ => unimplemented!("***** unsupported LLVM intrinsic {{full_name}}"),\n') + out.write(f"{indent16}}}\n{indent12}}}\n{indent8}{arch}(name,full_name)\n{indent8}}}\n,") + out.write(f"""{indent4}_ => {{ +{indent8}match old_arch_res {{ +{indent8}ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {{full_name}}"), +{indent8}ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {{arch}}, intrinsic: {{full_name}}"), +{indent8}ArchCheckResult::Ok(_) => unreachable!(), +{indent4}}} +}}""") out.write("}\n}") - subprocess.call(["rustfmt", output_file]) print("Done!") From e278aec33e1d7d4c688e9aa98d9bc9d9c7db3a2d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 30 Jun 2026 00:00:34 +0200 Subject: [PATCH 076/166] Put back removed intrinsics as they are still used --- src/intrinsic/old_archs.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/intrinsic/old_archs.rs b/src/intrinsic/old_archs.rs index 8d3e3487b5cb4..1aac52c28d220 100644 --- a/src/intrinsic/old_archs.rs +++ b/src/intrinsic/old_archs.rs @@ -1240,6 +1240,10 @@ pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { "avx512.vbroadcast.sd.pd.512" => "__builtin_ia32_vbroadcastsd_pd512", "avx512.vbroadcast.ss.512" => "__builtin_ia32_vbroadcastss512", "avx512.vbroadcast.ss.ps.512" => "__builtin_ia32_vbroadcastss_ps512", + "bmi.pdep.32" => "__builtin_ia32_pdep_si", + "bmi.pdep.64" => "__builtin_ia32_pdep_di", + "bmi.pext.32" => "__builtin_ia32_pext_si", + "bmi.pext.64" => "__builtin_ia32_pext_di", "fma.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", "fma.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", "fma.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", From ccaf7197e1ce606927d7f129606c8b8848d4475b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 30 Jun 2026 18:48:36 +0200 Subject: [PATCH 077/166] Add comment explaining why we don't handle all function parameter attributes in GCC --- src/abi.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/abi.rs b/src/abi.rs index 1b7bb8c907735..00e43dab0f83f 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -146,6 +146,14 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { non_null_args.push(arg_index as i32 + 1); } + // There are a few others `ArgAttribute` variants" + // + // * ArgAttribute::ReadOnly: `access(read_only())`, but it's only used for emitting + // warning, not for optimization. + // * ArgAttribute::NoUndef: No equivalent in GCC + // * ArgAttribute::Writable: `access(read_write())` or `access(write_only())`, but it's + // only used for emitting warning, not for optimization. + // * ArgAttribute::NoFree: No equivalent in GCC ty }; #[cfg(not(feature = "master"))] From b08124aac217421f377f5f7965b7f444b47d5ede Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Jul 2026 01:50:54 +0200 Subject: [PATCH 078/166] Add asm tests --- .gitignore | 2 +- build_system/Cargo.lock | 500 +++++++++++++++++++++++- build_system/Cargo.toml | 1 + build_system/src/test.rs | 82 +++- tests/asm/panic-no-unwind-no-uwtable.rs | 8 + 5 files changed, 573 insertions(+), 20 deletions(-) create mode 100644 tests/asm/panic-no-unwind-no-uwtable.rs diff --git a/.gitignore b/.gitignore index 8f73d3eb972a0..1bbd3a9958073 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ perf.data.old *.events *.string* gimple* -*asm +*_asm res test-backend projects diff --git a/build_system/Cargo.lock b/build_system/Cargo.lock index e727561a2bfba..dd34bfd8aa734 100644 --- a/build_system/Cargo.lock +++ b/build_system/Cargo.lock @@ -1,6 +1,15 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] [[package]] name = "boml" @@ -8,9 +17,498 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5" +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "compiletest_rs" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f150fe9105fcd2a57cad53f0c079a24de65195903ef670990f5909f695eac04c" +dependencies = [ + "diff", + "filetime", + "getopts", + "lazy_static", + "libc", + "log", + "miow", + "regex", + "rustfix", + "serde", + "serde_derive", + "serde_json", + "tester", + "windows-sys 0.59.0", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "filetime" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +dependencies = [ + "cfg-if", + "libc", +] + +[[package]] +name = "getopts" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libredox" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +dependencies = [ + "libc", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "miow" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rustfix" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" +dependencies = [ + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "tester" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e8bf7e0eb2dd7b4228cc1b6821fc5114cd6841ae59f652a85488c016091e5f" +dependencies = [ + "cfg-if", + "getopts", + "libc", + "num_cpus", + "term", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +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-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "y" version = "0.1.0" dependencies = [ "boml", + "compiletest_rs", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/build_system/Cargo.toml b/build_system/Cargo.toml index 540d82369fdf7..9087697826fa6 100644 --- a/build_system/Cargo.toml +++ b/build_system/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" [dependencies] boml = "0.3.1" +compiletest_rs = "0.11.2" [[bin]] name = "y" diff --git a/build_system/src/test.rs b/build_system/src/test.rs index eda31418842fa..91b9be7660cf0 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -43,6 +43,7 @@ fn get_runners() -> Runners { ); runners.insert("--extended-regex-tests", ("Run extended regex tests", extended_regex_tests)); runners.insert("--mini-tests", ("Run mini tests", mini_tests)); + runners.insert("--gcc-asm-tests", ("Run cg_gcc asm tests", test_asm)); runners.insert("--cargo-tests", ("Run cargo tests", cargo_tests)); runners.insert("--no-builtins-tests", ("Test #![no_builtins] attribute", no_builtins_tests)); runners.insert("--stdarch-tests", ("Run stdarch tests", test_stdarch as Runner)); @@ -507,6 +508,26 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } +fn get_llvm_filecheck(env: &Env) -> Result { + match run_command_with_env( + &[ + &"bash", + &"-c", + &"which FileCheck-10 || \ + which FileCheck-11 || \ + which FileCheck-12 || \ + which FileCheck-13 || \ + which FileCheck-14 || \ + which FileCheck", + ], + None, + Some(env), + ) { + Ok(cmd) => Ok(String::from_utf8_lossy(&cmd.stdout).trim().to_string()), + Err(_) => Err("Failed to retrieve LLVM FileCheck, ignoring...".to_owned()), + } +} + fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let toolchain = format!( "+{channel}-{host}", @@ -550,23 +571,10 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let rustc = rustc.trim().to_owned(); if rustc.is_empty() { Err("`rustc` path is empty".to_string()) } else { Ok(rustc) } })?; - let llvm_filecheck = match run_command_with_env( - &[ - &"bash", - &"-c", - &"which FileCheck-10 || \ - which FileCheck-11 || \ - which FileCheck-12 || \ - which FileCheck-13 || \ - which FileCheck-14 || \ - which FileCheck", - ], - rust_dir, - Some(env), - ) { - Ok(cmd) => String::from_utf8_lossy(&cmd.stdout).to_string(), - Err(_) => { - eprintln!("Failed to retrieve LLVM FileCheck, ignoring..."); + let llvm_filecheck = match get_llvm_filecheck(env) { + Ok(l) => l, + Err(error) => { + eprintln!("{error}"); // FIXME: the test tests/run-make/no-builtins-attribute will fail if we cannot find // FileCheck. String::new() @@ -636,7 +644,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"0", &"--set", &"build.compiletest-allow-stage0=true", - &"tests/assembly-llvm/asm", + &"tests/assembly-gcc/asm", &"--compiletest-rustc-args", &rustc_args, ], @@ -1326,6 +1334,44 @@ fn remove_files_callback<'a>( } } +fn test_asm(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] cg_gcc assembly"); + let llvm_filecheck = get_llvm_filecheck(env)?; + + let mut env: HashMap = std::env::vars().collect(); + let mut config = ConfigInfo::default(); + config.setup(&mut env, false)?; + + let mut test_config = compiletest_rs::Config::default(); + + test_config.mode = compiletest_rs::common::Mode::Assembly; + test_config.src_base = PathBuf::from("tests/asm"); + test_config.llvm_filecheck = Some(PathBuf::from(llvm_filecheck)); + test_config.filters = args.test_args.clone(); + test_config.strict_headers = true; + test_config.build_base = PathBuf::from("build/tests/asm"); + let rustc_flags = config + .rustc_command_vec() + .iter() + .skip(1) + .map(|arg| arg.as_ref().to_string_lossy()) + .collect::>() + .join(" "); + test_config.target_rustcflags = Some(rustc_flags); + test_config.link_deps(); + test_config.clean_rmeta(); + + match std::thread::spawn(move || { + compiletest_rs::run_tests(&test_config); + }) + .join() + { + Ok(_) => Ok(()), + Err(_) => Err("Assembly tests failed".to_owned()), + } +} + fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { clean(env, args)?; mini_tests(env, args)?; diff --git a/tests/asm/panic-no-unwind-no-uwtable.rs b/tests/asm/panic-no-unwind-no-uwtable.rs new file mode 100644 index 0000000000000..b51b173e9616e --- /dev/null +++ b/tests/asm/panic-no-unwind-no-uwtable.rs @@ -0,0 +1,8 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu +//@ compile-flags: -C panic=unwind -C force-unwind-tables=n -Copt-level=3 + +#![crate_type = "lib"] + +// CHECK-NOT: .cfi_startproc +pub fn foo() {} From 31181d1e027a66ceb38818e86f4c3b6dd3554a1f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Jul 2026 17:37:25 +0200 Subject: [PATCH 079/166] Move `asm-tester` into its own binary so the `compiletest_rs` dependency is only built when actually needed --- build_system/Cargo.lock | 498 --------------------------- build_system/Cargo.toml | 1 - build_system/asm-tester/Cargo.lock | 507 ++++++++++++++++++++++++++++ build_system/asm-tester/Cargo.toml | 13 + build_system/asm-tester/src/main.rs | 66 ++++ build_system/src/fmt.rs | 1 + build_system/src/test.rs | 47 ++- build_system/src/utils.rs | 1 - 8 files changed, 606 insertions(+), 528 deletions(-) create mode 100644 build_system/asm-tester/Cargo.lock create mode 100644 build_system/asm-tester/Cargo.toml create mode 100644 build_system/asm-tester/src/main.rs diff --git a/build_system/Cargo.lock b/build_system/Cargo.lock index dd34bfd8aa734..5e761149eb3bc 100644 --- a/build_system/Cargo.lock +++ b/build_system/Cargo.lock @@ -2,513 +2,15 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - [[package]] name = "boml" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5" -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "compiletest_rs" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f150fe9105fcd2a57cad53f0c079a24de65195903ef670990f5909f695eac04c" -dependencies = [ - "diff", - "filetime", - "getopts", - "lazy_static", - "libc", - "log", - "miow", - "regex", - "rustfix", - "serde", - "serde_derive", - "serde_json", - "tester", - "windows-sys 0.59.0", -] - -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "filetime" -version = "0.2.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" -dependencies = [ - "cfg-if", - "libc", -] - -[[package]] -name = "getopts" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.186" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" - -[[package]] -name = "libredox" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" -dependencies = [ - "libc", -] - -[[package]] -name = "log" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" - -[[package]] -name = "memchr" -version = "2.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" - -[[package]] -name = "miow" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" - -[[package]] -name = "rustfix" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" -dependencies = [ - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "syn" -version = "2.0.118" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - -[[package]] -name = "tester" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e8bf7e0eb2dd7b4228cc1b6821fc5114cd6841ae59f652a85488c016091e5f" -dependencies = [ - "cfg-if", - "getopts", - "libc", - "num_cpus", - "term", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -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-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "y" version = "0.1.0" dependencies = [ "boml", - "compiletest_rs", ] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/build_system/Cargo.toml b/build_system/Cargo.toml index 9087697826fa6..540d82369fdf7 100644 --- a/build_system/Cargo.toml +++ b/build_system/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] boml = "0.3.1" -compiletest_rs = "0.11.2" [[bin]] name = "y" diff --git a/build_system/asm-tester/Cargo.lock b/build_system/asm-tester/Cargo.lock new file mode 100644 index 0000000000000..9ad96acfda407 --- /dev/null +++ b/build_system/asm-tester/Cargo.lock @@ -0,0 +1,507 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "asm-tester" +version = "0.1.0" +dependencies = [ + "compiletest_rs", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "compiletest_rs" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f150fe9105fcd2a57cad53f0c079a24de65195903ef670990f5909f695eac04c" +dependencies = [ + "diff", + "filetime", + "getopts", + "lazy_static", + "libc", + "log", + "miow", + "regex", + "rustfix", + "serde", + "serde_derive", + "serde_json", + "tester", + "windows-sys 0.59.0", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "filetime" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +dependencies = [ + "cfg-if", + "libc", +] + +[[package]] +name = "getopts" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "libc", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "miow" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rustfix" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" +dependencies = [ + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "tester" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e8bf7e0eb2dd7b4228cc1b6821fc5114cd6841ae59f652a85488c016091e5f" +dependencies = [ + "cfg-if", + "getopts", + "libc", + "num_cpus", + "term", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +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-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/build_system/asm-tester/Cargo.toml b/build_system/asm-tester/Cargo.toml new file mode 100644 index 0000000000000..eeefe61bdc75b --- /dev/null +++ b/build_system/asm-tester/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "asm-tester" +version = "0.1.0" +edition = "2024" + +[dependencies] +compiletest_rs = "0.11.2" + +[[bin]] +name = "asm-tester" +path = "src/main.rs" + +[workspace] diff --git a/build_system/asm-tester/src/main.rs b/build_system/asm-tester/src/main.rs new file mode 100644 index 0000000000000..00ee4ac936520 --- /dev/null +++ b/build_system/asm-tester/src/main.rs @@ -0,0 +1,66 @@ +use std::path::PathBuf; + +#[derive(Default)] +struct Config { + llvm_filecheck: Option, + filters: Vec, + rustc_flags: Vec, +} + +impl Config { + fn new() -> Result { + // We skip the program's name. + let mut args = std::env::args().skip(1); + let mut config = Self::default(); + + while let Some(arg) = args.next() { + match arg.as_str() { + "--llvm-filecheck" => { + config.llvm_filecheck = args.next().map(PathBuf::from); + } + "--filter" => { + if let Some(arg) = args.next() { + config.filters.push(arg); + } + } + "--" => { + config.rustc_flags.extend(&mut args); + // Nothing else to be read but the `break` makes it more clear. + break; + } + arg => return Err(format!("Unknown argument {arg:?}")), + } + } + if config.llvm_filecheck.is_none() { + Err("Missing `--llvm-filecheck` option".to_owned()) + } else if config.rustc_flags.is_empty() { + Err("Missing rustc flags (passed after `--`)".to_owned()) + } else { + Ok(config) + } + } +} + +fn main() { + let Config { llvm_filecheck, filters, rustc_flags } = match Config::new() { + Ok(c) => c, + Err(error) => { + eprintln!("{error}"); + std::process::exit(1); + } + }; + + let mut test_config = compiletest_rs::Config::default(); + + test_config.mode = compiletest_rs::common::Mode::Assembly; + test_config.src_base = PathBuf::from("tests/asm"); + test_config.llvm_filecheck = llvm_filecheck; + test_config.filters = filters; + test_config.strict_headers = true; + test_config.build_base = PathBuf::from("build/tests/asm"); + test_config.target_rustcflags = Some(rustc_flags.join(" ")); + test_config.link_deps(); + test_config.clean_rmeta(); + + compiletest_rs::run_tests(&test_config) +} diff --git a/build_system/src/fmt.rs b/build_system/src/fmt.rs index 91535f217e351..bf1c4676d0bc3 100644 --- a/build_system/src/fmt.rs +++ b/build_system/src/fmt.rs @@ -33,6 +33,7 @@ pub fn run() -> Result<(), String> { run_command_with_output(cmd, Some(Path::new(".")))?; run_command_with_output(cmd, Some(Path::new("build_system")))?; + run_command_with_output(cmd, Some(Path::new("build_system/asm-tester")))?; run_rustfmt_recursively("tests/run", check) } diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 91b9be7660cf0..65b5d4ef83617 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -9,8 +9,8 @@ use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ create_dir, get_sysroot_dir, get_toolchain, git_clone, git_clone_root_dir, remove_file, - run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, - split_args, walk_dir, + run_command, run_command_with_env, run_command_with_output_and_env, + run_command_with_output_and_env_no_err, rustc_version_info, split_args, walk_dir, }; type Env = HashMap; @@ -1343,33 +1343,24 @@ fn test_asm(env: &Env, args: &TestArg) -> Result<(), String> { let mut config = ConfigInfo::default(); config.setup(&mut env, false)?; - let mut test_config = compiletest_rs::Config::default(); - - test_config.mode = compiletest_rs::common::Mode::Assembly; - test_config.src_base = PathBuf::from("tests/asm"); - test_config.llvm_filecheck = Some(PathBuf::from(llvm_filecheck)); - test_config.filters = args.test_args.clone(); - test_config.strict_headers = true; - test_config.build_base = PathBuf::from("build/tests/asm"); - let rustc_flags = config - .rustc_command_vec() - .iter() - .skip(1) - .map(|arg| arg.as_ref().to_string_lossy()) - .collect::>() - .join(" "); - test_config.target_rustcflags = Some(rustc_flags); - test_config.link_deps(); - test_config.clean_rmeta(); - - match std::thread::spawn(move || { - compiletest_rs::run_tests(&test_config); - }) - .join() - { - Ok(_) => Ok(()), - Err(_) => Err("Assembly tests failed".to_owned()), + let mut test_asm_args: Vec<&dyn AsRef> = vec![ + &"cargo", + &"run", + &"--manifest-path", + &"build_system/asm-tester/Cargo.toml", + &"--", + &"--llvm-filecheck", + &llvm_filecheck, + ]; + for test_arg in &args.test_args { + test_asm_args.push(&"--filter"); + test_asm_args.push(test_arg); + } + test_asm_args.push(&"--"); + for arg in config.rustc_command_vec().into_iter().skip(1) { + test_asm_args.push(arg); } + run_command_with_output_and_env_no_err(&test_asm_args, Some(Path::new(".")), Some(&env)) } fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 112322f8688c1..6939d93099634 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -124,7 +124,6 @@ pub fn run_command_with_output_and_env( check_exit_status(input, cwd, exit_status, None, true) } -#[cfg(not(unix))] pub fn run_command_with_output_and_env_no_err( input: &[&dyn AsRef], cwd: Option<&Path>, From d9b9ce7c820219b081a87306d8e9f4769607c63f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Jul 2026 17:38:26 +0200 Subject: [PATCH 080/166] Add `test_asm` to the `run_all` call and run `--gcc-asm-tests` in the CI --- .github/workflows/ci.yml | 1 + build_system/src/test.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a965397b8ba49..4463a6bd53c38 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,7 @@ jobs: "--test-successful-rustc --nb-parts 2 --current-part 0", "--test-successful-rustc --nb-parts 2 --current-part 1", "--projects", + "--gcc-asm-tests", ] steps: diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 65b5d4ef83617..530029c91df99 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1374,6 +1374,7 @@ fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { cargo_tests(env, args)?; no_builtins_tests(env, args)?; test_rustc(env, args)?; + test_asm(env, args)?; Ok(()) } From 1b0167d9a7928bc94817bb9529b4a256db751601 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 2 Jul 2026 00:20:07 +0200 Subject: [PATCH 081/166] Prevent unwanted recompilations --- build_system/src/test.rs | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 530029c91df99..b945d91a81c49 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1335,6 +1335,12 @@ fn remove_files_callback<'a>( } fn test_asm(env: &Env, args: &TestArg) -> Result<(), String> { + fn is_path_time_more_recent(ref_time: std::time::SystemTime, path: &str) -> bool { + std::fs::metadata(path) + .and_then(|metadata| metadata.modified()) + .is_ok_and(|time| ref_time < time) + } + // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] cg_gcc assembly"); let llvm_filecheck = get_llvm_filecheck(env)?; @@ -1343,12 +1349,35 @@ fn test_asm(env: &Env, args: &TestArg) -> Result<(), String> { let mut config = ConfigInfo::default(); config.setup(&mut env, false)?; + let target_dir = std::env::current_dir().unwrap().join("build_system/asm-tester/target"); + + // All this code is because `cargo` keeps recompiling this file, and we can't figure out why. + let binary_file_path = "build_system/asm-tester/target/debug/asm-tester"; + let mut need_recompilation = true; + if let Ok(metadata) = std::fs::metadata(binary_file_path) + && let Ok(ref_time) = metadata.modified() + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/Cargo.toml") + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/Cargo.lock") + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/src/main.rs") + { + need_recompilation = false; + } + + if need_recompilation { + let build_asm_args: Vec<&dyn AsRef> = vec![ + &"cargo", + &"build", + &"--manifest-path", + &"build_system/asm-tester/Cargo.toml", + &"--target-dir", + &target_dir, + &"--", + ]; + run_command_with_output_and_env_no_err(&build_asm_args, Some(Path::new(".")), Some(&env))?; + } + let mut test_asm_args: Vec<&dyn AsRef> = vec![ - &"cargo", - &"run", - &"--manifest-path", - &"build_system/asm-tester/Cargo.toml", - &"--", + &"build_system/asm-tester/target/debug/asm-tester", &"--llvm-filecheck", &llvm_filecheck, ]; From c050550d12d186907ddd52cd64eece0112ecf9fe Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 2 Jul 2026 00:24:24 +0200 Subject: [PATCH 082/166] Fix documentation for `y.sh rustc` to use the release channel --- Readme.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index ce5ee1e4adee6..26783aa39cea8 100644 --- a/Readme.md +++ b/Readme.md @@ -136,19 +136,21 @@ $ ./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml ### Cargo ```bash -$ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run +$ CHANNEL=release $CG_GCCJIT_DIR/y.sh cargo run ``` -If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. +If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y.sh build`) you should use `CHANNEL=debug` instead or omit `CHANNEL=release` completely. ### Rustc If you want to run `rustc` directly, you can do so with: ```bash -$ ./y.sh rustc my_crate.rs +$ CHANNEL=release ./y.sh rustc my_crate.rs ``` +If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y.sh build`) you should use `CHANNEL=debug` instead or omit `CHANNEL=release` completely. + You can do the same manually (although we don't recommend it): ```bash From edafd1f0a98b004e733411ba53018b200dea06ee Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 2 Jul 2026 00:26:57 +0200 Subject: [PATCH 083/166] Remove `--out-dir` option when using `y.sh rustc` or `y.sh cargo` to stick closer to the expected behaviour --- build_system/src/build.rs | 2 +- build_system/src/config.rs | 13 +++++++------ build_system/src/rust_tools.rs | 2 +- build_system/src/test.rs | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 839c762fed742..e570a3f16c39e 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -227,7 +227,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { } run_command_with_output_and_env(&command, None, Some(&env))?; - args.config_info.setup(&mut env, false)?; + args.config_info.setup(&mut env, false, true)?; // We voluntarily ignore the error. let _ = fs::remove_dir_all("target/out"); diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 8eb6d8f019e1c..fd78f691d1657 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -314,6 +314,7 @@ impl ConfigInfo { &mut self, env: &mut HashMap, use_system_gcc: bool, + generate_out_dir: bool, ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); @@ -444,12 +445,12 @@ impl ConfigInfo { self.rustc_command = vec![rustc]; self.rustc_command.extend_from_slice(&rustflags); - self.rustc_command.extend_from_slice(&[ - "-L".to_string(), - format!("crate={}", self.cargo_target_dir), - "--out-dir".to_string(), - self.cargo_target_dir.clone(), - ]); + self.rustc_command + .extend_from_slice(&["-L".to_string(), format!("crate={}", self.cargo_target_dir)]); + if generate_out_dir { + self.rustc_command + .extend_from_slice(&["--out-dir".to_string(), self.cargo_target_dir.clone()]); + } if !env.contains_key("RUSTC_LOG") { env.insert("RUSTC_LOG".to_string(), "warn".to_string()); diff --git a/build_system/src/rust_tools.rs b/build_system/src/rust_tools.rs index b1faa27acc4a2..1b50f11c3d324 100644 --- a/build_system/src/rust_tools.rs +++ b/build_system/src/rust_tools.rs @@ -72,7 +72,7 @@ impl RustcTools { let mut env: HashMap = std::env::vars().collect(); let mut config = ConfigInfo::default(); - config.setup(&mut env, false)?; + config.setup(&mut env, false, false)?; let toolchain = get_toolchain()?; let toolchain_version = rustc_toolchain_version_info(&toolchain)?; diff --git a/build_system/src/test.rs b/build_system/src/test.rs index eda31418842fa..f7cbf0d679c4c 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1358,7 +1358,7 @@ pub fn run() -> Result<(), String> { return Ok(()); } - args.config_info.setup(&mut env, args.use_system_gcc)?; + args.config_info.setup(&mut env, args.use_system_gcc, true)?; if args.runners.is_empty() { run_all(&env, &args)?; From b9ea2a585a13232615118ebfa5e488c4b37c409c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 2 Jul 2026 00:47:12 +0200 Subject: [PATCH 084/166] No need to re-create `Config`, use the one provided in `TestArgs` --- build_system/src/test.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index b945d91a81c49..e4da9b3aa2b86 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1345,10 +1345,6 @@ fn test_asm(env: &Env, args: &TestArg) -> Result<(), String> { println!("[TEST] cg_gcc assembly"); let llvm_filecheck = get_llvm_filecheck(env)?; - let mut env: HashMap = std::env::vars().collect(); - let mut config = ConfigInfo::default(); - config.setup(&mut env, false)?; - let target_dir = std::env::current_dir().unwrap().join("build_system/asm-tester/target"); // All this code is because `cargo` keeps recompiling this file, and we can't figure out why. @@ -1373,7 +1369,7 @@ fn test_asm(env: &Env, args: &TestArg) -> Result<(), String> { &target_dir, &"--", ]; - run_command_with_output_and_env_no_err(&build_asm_args, Some(Path::new(".")), Some(&env))?; + run_command_with_output_and_env_no_err(&build_asm_args, Some(Path::new(".")), Some(env))?; } let mut test_asm_args: Vec<&dyn AsRef> = vec![ @@ -1386,10 +1382,10 @@ fn test_asm(env: &Env, args: &TestArg) -> Result<(), String> { test_asm_args.push(test_arg); } test_asm_args.push(&"--"); - for arg in config.rustc_command_vec().into_iter().skip(1) { + for arg in args.config_info.rustc_command_vec().into_iter().skip(1) { test_asm_args.push(arg); } - run_command_with_output_and_env_no_err(&test_asm_args, Some(Path::new(".")), Some(&env)) + run_command_with_output_and_env_no_err(&test_asm_args, Some(Path::new(".")), Some(env)) } fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { From 704a9f7384c7536aa167cc8d4ed1cc25a7a932bc Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 1 Jul 2026 21:18:20 -0400 Subject: [PATCH 085/166] Add passing asm tests --- .../x86_64-naked-fn-no-cet-prolog.rs | 24 +++++++++++++++++++ tests/asm/x86_64-sse_crc.rs | 12 ++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs create mode 100644 tests/asm/x86_64-sse_crc.rs diff --git a/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs b/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs new file mode 100644 index 0000000000000..81ee9b13b4eca --- /dev/null +++ b/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -C no-prepopulate-passes -Zcf-protection=full +//@ assembly-output: emit-asm +//@ needs-asm-support +//@ only-x86_64 + +#![crate_type = "lib"] + +use std::arch::naked_asm; + +// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions", +// meaning "no prologue whatsoever, no, really, not one instruction." +// Unfortunately, x86's control-flow enforcement, specifically indirect branch protection, +// works by using an instruction for each possible landing site, +// and LLVM implements this via making sure of that. +#[no_mangle] +#[unsafe(naked)] +pub extern "sysv64" fn will_halt() -> ! { + // CHECK-NOT: endbr{{32|64}} + // CHECK: hlt + naked_asm!("hlt") +} + +// what about aarch64? +// "branch-protection"=false diff --git a/tests/asm/x86_64-sse_crc.rs b/tests/asm/x86_64-sse_crc.rs new file mode 100644 index 0000000000000..bde58955a2146 --- /dev/null +++ b/tests/asm/x86_64-sse_crc.rs @@ -0,0 +1,12 @@ +//@ only-x86_64 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2 + +// CHECK-LABEL: banana +// CHECK: crc32 +#[no_mangle] +pub unsafe fn banana(v: u8) -> u32 { + use std::arch::x86_64::*; + let out = !0u32; + _mm_crc32_u8(out, v) +} From 45eb8a3d74a89853b0aeb02dd97602030c0ec99f Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 1 Jul 2026 22:03:27 -0400 Subject: [PATCH 086/166] Add another passing asm test that needed an adjustment to the checked label --- tests/asm/asm/comments.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/asm/asm/comments.rs diff --git a/tests/asm/asm/comments.rs b/tests/asm/asm/comments.rs new file mode 100644 index 0000000000000..603bb014930c4 --- /dev/null +++ b/tests/asm/asm/comments.rs @@ -0,0 +1,12 @@ +//@ assembly-output: emit-asm +//@ only-x86_64 +// Check that comments in assembly get passed + +#![crate_type = "lib"] + +// CHECK-LABEL: "test_comments": +#[no_mangle] +pub fn test_comments() { + // CHECK: example comment + unsafe { core::arch::asm!("nop // example comment") }; +} From 684aebb7eb89ba481addfe9cbf8d76c888d6c9e2 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 7 Jul 2026 00:41:13 -0700 Subject: [PATCH 087/166] Fix `unaligned_volatile_store` by removing `MemFlags::UNALIGNED` --- src/builder.rs | 2 +- src/intrinsic/mod.rs | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index f9358872299b7..425d9d6226f83 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1155,7 +1155,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // NOTE: libgccjit does not support specifying the alignment on the assignment, so we cast // to type so it gets the proper alignment. let destination_type = destination.to_rvalue().get_type().unqualified(); - let align = if flags.contains(MemFlags::UNALIGNED) { 1 } else { align.bytes() }; + let align = align.bytes(); let mut modified_destination_type = destination_type.get_aligned(align); if flags.contains(MemFlags::VOLATILE) { modified_destination_type = modified_destination_type.make_volatile(); diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 78a4c7e88c895..80d4a5cf11ad8 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -377,16 +377,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc load } } - sym::volatile_store => { - let dst = args[0].deref(self.cx()); - args[1].val.volatile_store(self, dst); - return IntrinsicResult::WroteIntoPlace; - } - sym::unaligned_volatile_store => { - let dst = args[0].deref(self.cx()); - args[1].val.unaligned_volatile_store(self, dst); - return IntrinsicResult::WroteIntoPlace; - } sym::prefetch_read_data | sym::prefetch_write_data | sym::prefetch_read_instruction From a4cb6e715e0d925746bbfe047b85954f93037770 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 1 Jul 2026 08:33:26 -0700 Subject: [PATCH 088/166] Carry the `b_offset` inside `BackendRepr::ScalarPair` --- src/builder.rs | 6 +++--- src/intrinsic/mod.rs | 2 +- src/type_of.rs | 13 ++++++------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index f9358872299b7..0bef86b1ae8c1 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1064,9 +1064,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { load }, ) - } else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr { - let b_offset = a.size(self).align_to(b.default_align(self).abi); - + } else if let abi::BackendRepr::ScalarPair { ref a, ref b, b_offset } = + place.layout.backend_repr + { let mut load = |i, scalar: &abi::Scalar, align| { let ptr = if i == 0 { place.val.llval diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 78a4c7e88c895..a5b8068e0f018 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -485,7 +485,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let tp_ty = fn_args.type_at(0); let layout = self.layout_of(tp_ty).layout; let _use_integer_compare = match layout.backend_repr() { - Scalar(_) | ScalarPair(_, _) => true, + Scalar(_) | ScalarPair { a: _, b: _, b_offset: _ } => true, SimdVector { .. } | SimdScalableVector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed diff --git a/src/type_of.rs b/src/type_of.rs index 9807a84c0788d..227b513c0ff30 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -75,7 +75,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( }; return cx.context.new_vector_type(element, count); } - BackendRepr::ScalarPair(..) => { + BackendRepr::ScalarPair { .. } => { return cx.type_struct( &[ layout.scalar_pair_element_gcc_type(cx, 0), @@ -182,13 +182,13 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true, // FIXME(rustc_scalable_vector): Not yet implemented in rustc_codegen_gcc. BackendRepr::SimdScalableVector { .. } => todo!(), - BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, + BackendRepr::ScalarPair { .. } | BackendRepr::Memory { .. } => false, } } fn is_gcc_scalar_pair(&self) -> bool { match self.backend_repr { - BackendRepr::ScalarPair(..) => true, + BackendRepr::ScalarPair { .. } => true, BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. } @@ -308,8 +308,8 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // 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.backend_repr { - BackendRepr::ScalarPair(ref a, ref b) => (a, b), + let (a, b, b_offset) = match self.backend_repr { + BackendRepr::ScalarPair { ref a, ref b, b_offset } => (a, b, b_offset), _ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self), }; let scalar = [a, b][index]; @@ -325,8 +325,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { return cx.type_i1(); } - let offset = - if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.default_align(cx).abi) }; + let offset = if index == 0 { Size::ZERO } else { b_offset }; self.scalar_gcc_type_at(cx, scalar, offset) } From 2c0ffd26dec3bdade0304c5f3776349a860b5dc2 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 11 Jul 2026 20:15:49 -0700 Subject: [PATCH 089/166] [cg_ssa] Eliminate the `is_backend_{immediate,scalar_pair,ref}` methods --- src/builder.rs | 2 +- src/type_of.rs | 29 ----------------------------- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index da17f05bb8a32..7671d2e026b03 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1054,7 +1054,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let val = if place.val.llextra.is_some() { // FIXME: Merge with the `else` below? OperandValue::Ref(place.val) - } else if place.layout.is_gcc_immediate() { + } else if place.layout.backend_repr.is_scalar_or_simd() { let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align); OperandValue::Immediate( if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr { diff --git a/src/type_of.rs b/src/type_of.rs index 227b513c0ff30..f2ce7bca1e338 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -154,8 +154,6 @@ fn uncached_gcc_type<'gcc, 'tcx>( } pub trait LayoutGccExt<'tcx> { - fn is_gcc_immediate(&self) -> bool; - fn is_gcc_scalar_pair(&self) -> bool; 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>( @@ -177,25 +175,6 @@ pub trait LayoutGccExt<'tcx> { } impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { - fn is_gcc_immediate(&self) -> bool { - match self.backend_repr { - BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true, - // FIXME(rustc_scalable_vector): Not yet implemented in rustc_codegen_gcc. - BackendRepr::SimdScalableVector { .. } => todo!(), - BackendRepr::ScalarPair { .. } | BackendRepr::Memory { .. } => false, - } - } - - fn is_gcc_scalar_pair(&self) -> bool { - match self.backend_repr { - BackendRepr::ScalarPair { .. } => true, - BackendRepr::Scalar(_) - | BackendRepr::SimdVector { .. } - | BackendRepr::SimdScalableVector { .. } - | BackendRepr::Memory { .. } => false, - } - } - /// Gets the GCC type corresponding to a Rust type, i.e., `rustc_middle::ty::Ty`. /// The pointee type of the pointer in `PlaceRef` is always this type. /// For sized types, it is also the right LLVM type for an `alloca` @@ -350,14 +329,6 @@ impl<'gcc, 'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { layout.immediate_gcc_type(self) } - fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool { - layout.is_gcc_immediate() - } - - fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool { - layout.is_gcc_scalar_pair() - } - fn scalar_pair_element_backend_type( &self, layout: TyAndLayout<'tcx>, From 162a3a55c2aba4dcdfb854e7d74af4e1a50f95bb Mon Sep 17 00:00:00 2001 From: Jakub Chlanda Date: Thu, 7 May 2026 12:42:56 +0000 Subject: [PATCH 090/166] Pointer authentication config and user facing options This patch brings: * unified handling of pointer authentication options through: `-Zpointer-authentication`, with possible values: `aarch64-jump-table-hardening`, `auth-traps`, `calls`, `elf-got`, `function-pointer-type-discrimination`, `indirect-gotos`, `init-fini`, `init-fini-address-discrimination`, `return-addresses`. Toggled with `+`/`-`. * centralized handling of pointer authentication features. Session holds `pointer_auth_config: Option` * encapsulation of schema for function pointers and init/fini through `PointerAuthSchema`. This allowed for retiring of `PacMetadata`. * refactor enabling of pointer authentication in code, instead of relying on the target (`pauthtest`) use the session --- src/common.rs | 6 +++--- src/context.rs | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/common.rs b/src/common.rs index 7450f11f3ce80..e73b8aab54d73 100644 --- a/src/common.rs +++ b/src/common.rs @@ -2,12 +2,12 @@ use gccjit::{LValue, RValue, ToRValue, Type}; use rustc_abi::Primitive::Pointer; use rustc_abi::{self as abi, HasDataLayout}; use rustc_codegen_ssa::traits::{ - BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, PacMetadata, - StaticCodegenMethods, + BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods, }; use rustc_middle::mir::Mutability; use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar}; use rustc_middle::ty::layout::LayoutOf; +use rustc_session::PointerAuthSchema; use crate::consts::const_alloc_to_gcc; use crate::context::{CodegenCx, new_array_type}; @@ -247,7 +247,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>, - _pac: Option, + _schema: Option<&PointerAuthSchema>, ) -> RValue<'gcc> { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { diff --git a/src/context.rs b/src/context.rs index 3a6c415b38963..e20a1502a275d 100644 --- a/src/context.rs +++ b/src/context.rs @@ -5,9 +5,7 @@ use gccjit::{Block, CType, Context, Function, FunctionType, LValue, Location, RV use rustc_abi::{Align, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::errors as ssa_errors; -use rustc_codegen_ssa::traits::{ - BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods, PacMetadata, -}; +use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods}; use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::interpret::Allocation; @@ -18,9 +16,9 @@ use rustc_middle::ty::layout::{ LayoutOfHelpers, }; use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; -use rustc_session::Session; #[cfg(feature = "master")] use rustc_session::config::DebugInfo; +use rustc_session::{PointerAuthSchema, Session}; use rustc_span::{DUMMY_SP, Span, Symbol, respan}; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; @@ -400,7 +398,11 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { get_fn(self, instance) } - fn get_fn_addr(&self, instance: Instance<'tcx>, _pac: Option) -> RValue<'gcc> { + fn get_fn_addr( + &self, + instance: Instance<'tcx>, + _schema: Option<&PointerAuthSchema>, + ) -> RValue<'gcc> { let func_name = self.tcx.symbol_name(instance).name; let func = if let Some(variable) = self.get_declared_value(func_name) { From 0203f8edba4090779c914c25c528b087fdd70abb Mon Sep 17 00:00:00 2001 From: Jakub Chlanda Date: Thu, 21 May 2026 13:11:35 +0000 Subject: [PATCH 091/166] Document -Zpointer-authentication option --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index e20a1502a275d..0e3fa72fbcfb3 100644 --- a/src/context.rs +++ b/src/context.rs @@ -401,7 +401,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn get_fn_addr( &self, instance: Instance<'tcx>, - _schema: Option<&PointerAuthSchema>, + _pointer_auth_schema: Option<&PointerAuthSchema>, ) -> RValue<'gcc> { let func_name = self.tcx.symbol_name(instance).name; From 254808db0ec11adc6dcb2e2511d32134cd11f225 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 14 Jul 2026 13:01:56 -0400 Subject: [PATCH 092/166] Update to nightly-2026-07-14 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index ee95f8e6e1cf9..fdd85175e0340 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-06-28" +channel = "nightly-2026-07-14" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 2bee6342735ee7b5734e180a8350e296b653f820 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 14 Jul 2026 13:04:40 -0400 Subject: [PATCH 093/166] Fix spelling --- tools/cspell_dicts/rustc_codegen_gcc.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/cspell_dicts/rustc_codegen_gcc.txt b/tools/cspell_dicts/rustc_codegen_gcc.txt index 794ebec11c30d..bae8edc9ffdf9 100644 --- a/tools/cspell_dicts/rustc_codegen_gcc.txt +++ b/tools/cspell_dicts/rustc_codegen_gcc.txt @@ -78,5 +78,6 @@ uninlined utrunc vgpr xabort +xreg xtensa zext From 68e317cbd3f924137ab4b6f52d2dc8cb5909e8b7 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 14 Jul 2026 13:05:03 -0400 Subject: [PATCH 094/166] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index e247ce7d3bb16..01a3f83465838 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -2f06e64df0dc15f861f77595b77bfc2ba5deb59d +6249f1b21d0c17856c6fa87def9edd0eaa968caf From 83a96cd47330bc776aff7a7b62dd49a73e2ffe4d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 14 Jul 2026 13:23:33 -0400 Subject: [PATCH 095/166] Update failing UI tests --- tests/failing-ui-tests.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index da6544bb76d44..a1397746b735d 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -17,7 +17,7 @@ tests/ui/drop/dynamic-drop.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs tests/ui/drop/panic-during-drop-14875.rs -tests/ui/issues/issue-29948.rs +tests/ui/drop/move-closure-drop-on-unwind.rs tests/ui/process/println-with-broken-pipe.rs tests/ui/lto/thin-lto-inlines2.rs tests/ui/panic-runtime/lto-abort.rs @@ -96,6 +96,7 @@ tests/ui/eii/default/call_default.rs tests/ui/eii/linking/same-symbol.rs tests/ui/eii/privacy1.rs tests/ui/eii/default/call_impl.rs +tests/ui/eii/linking/track_caller_cross_crate.rs tests/ui/c-variadic/copy.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs @@ -115,3 +116,4 @@ tests/ui/eii/static/default_cross_crate.rs tests/ui/eii/static/default_explicit.rs tests/ui/eii/static/default_cross_crate_explicit.rs tests/ui/explicit-tail-calls/default-trait-method.rs +tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs From 22789e6b3eace84e8e92917ac5544375b1a9238a Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 12 Jul 2026 17:17:29 +0200 Subject: [PATCH 096/166] implement `va_start` and `va_arg` --- src/builder.rs | 10 ++++++---- src/intrinsic/mod.rs | 20 ++++++++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index a9287d3247a00..9eca9eeb620a6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -4,8 +4,8 @@ use std::convert::TryFrom; use std::ops::Deref; use gccjit::{ - BinaryOp, Block, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, Type, - UnaryOp, + BinaryOp, Block, CType, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, + Type, UnaryOp, }; use rustc_abi as abi; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout, WrappingRange}; @@ -1513,8 +1513,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { variable.to_rvalue() } - fn va_arg(&mut self, _list: RValue<'gcc>, _ty: Type<'gcc>) -> RValue<'gcc> { - unimplemented!(); + fn va_arg(&mut self, list: RValue<'gcc>, ty: Type<'gcc>) -> RValue<'gcc> { + let va_list_type = self.context.new_c_type(CType::VaList); + let list = self.context.new_cast(self.location, list, va_list_type.make_pointer()); + self.context.new_va_arg(self.location, list, ty) } #[cfg(feature = "master")] diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index ff8312beb368f..76a868e0fad4f 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,7 +4,7 @@ mod simd; #[cfg(feature = "master")] use std::iter; -use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; +use gccjit::{CType, ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; use rustc_abi::{Align, BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -362,7 +362,9 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc unimplemented!(); } sym::va_arg => { - unimplemented!(); + let va_list = args[0].immediate(); + let gcc_type = self.immediate_backend_type(result.layout); + self.va_arg(va_list, gcc_type) } sym::volatile_load | sym::unaligned_volatile_load => { @@ -691,8 +693,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.context.new_rvalue_from_int(self.int_type, 0) } - fn va_start(&mut self, _va_list: RValue<'gcc>) { - unimplemented!(); + fn va_start(&mut self, va_list: RValue<'gcc>) { + let func = self.context.get_builtin_function("__builtin_va_start"); + + let va_list_type = self.context.new_c_type(CType::VaList); + let va_list = self.context.new_cast(self.location, va_list, va_list_type.make_pointer()); + + // Pre-C23 requires that the last "normal" argument was passed to va_start. + // Just pass 0, this appears to be handled correctly. + let last_normal_arg = self.context.new_rvalue_from_int(self.int_type, 0); + + let call = self.context.new_call(self.location, func, &[va_list, last_normal_arg]); + self.block.add_eval(self.location, call); } fn retag_reg(&mut self, _ptr: Self::Value, _info: &RetagInfo) -> Self::Value { From ff01db22276313c3c82da7804c4f97447d13080a Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 14 Jul 2026 16:07:21 +0200 Subject: [PATCH 097/166] enable c-variadic ui tests --- tests/failing-ui-tests.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index a1397746b735d..b9de22cecd51c 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -74,9 +74,6 @@ tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs tests/ui/explicit-tail-calls/recursion-etc.rs tests/ui/explicit-tail-calls/indexer.rs tests/ui/explicit-tail-calls/drop-order.rs -tests/ui/c-variadic/valid.rs -tests/ui/c-variadic/inherent-method.rs -tests/ui/c-variadic/trait-method.rs tests/ui/explicit-tail-calls/become-cast-return.rs tests/ui/explicit-tail-calls/become-indirect-return.rs tests/ui/panics/panic-abort-backtrace-without-debuginfo.rs @@ -97,7 +94,6 @@ tests/ui/eii/linking/same-symbol.rs tests/ui/eii/privacy1.rs tests/ui/eii/default/call_impl.rs tests/ui/eii/linking/track_caller_cross_crate.rs -tests/ui/c-variadic/copy.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs tests/ui/consts/const-eval/c-variadic.rs @@ -105,7 +101,6 @@ tests/ui/eii/default/call_default_panics.rs tests/ui/explicit-tail-calls/indirect.rs tests/ui/traits/inheritance/self-in-supertype.rs tests/ui/fmt/fmt_debug/shallow.rs -tests/ui/c-variadic/roundtrip.rs tests/ui/eii/eii_impl_with_contract.rs tests/ui/eii/static/cross_crate_decl.rs tests/ui/eii/static/cross_crate_def.rs From f9c093a8814a12fe02abcc3792006861755f5d9f Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 14 Jul 2026 16:09:32 +0200 Subject: [PATCH 098/166] use latest version of gccjit --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- tests/failing-ui-tests.txt | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b984e66531e60..3786a94b2418d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b73d18b642ce16378af78f89664841d7eeafa113682ff5d14573424eb0232a" +checksum = "8b2c6ee720b5459292678267e9ffed8229b11e0e27fc5ecf7618634dc6272fa4" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee689456c013616942d5aef9a84d613cefcc3b335340d036f3650fc1a7459e15" +checksum = "0cea2ed05e093fd90bd21fa03a7d09e07f62103ce94de21859f048c9a6c18e42" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 8956bd6948979..aba88456801f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "3.3.0", features = ["dlopen"] } +gccjit = { version = "3.4.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index b9de22cecd51c..bf274f2c78133 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -96,7 +96,6 @@ tests/ui/eii/default/call_impl.rs tests/ui/eii/linking/track_caller_cross_crate.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs -tests/ui/consts/const-eval/c-variadic.rs tests/ui/eii/default/call_default_panics.rs tests/ui/explicit-tail-calls/indirect.rs tests/ui/traits/inheritance/self-in-supertype.rs From bd30184c9a7a4ccea68d26829257655d96f9699c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Jul 2026 17:23:13 +0200 Subject: [PATCH 099/166] Update uses of `rustc_codegen_ssa::errors` --- src/context.rs | 2 +- src/intrinsic/mod.rs | 2 +- src/intrinsic/simd.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/context.rs b/src/context.rs index 0e3fa72fbcfb3..184db4cb25778 100644 --- a/src/context.rs +++ b/src/context.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use gccjit::{Block, CType, Context, Function, FunctionType, LValue, Location, RValue, Type}; use rustc_abi::{Align, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; -use rustc_codegen_ssa::errors as ssa_errors; +use rustc_codegen_ssa::diagnostics as ssa_errors; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods}; use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 06fbd287435d6..09ad3254e5714 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -8,7 +8,7 @@ use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, Unary use rustc_abi::{Align, BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; -use rustc_codegen_ssa::errors::InvalidMonomorphization; +use rustc_codegen_ssa::diagnostics::InvalidMonomorphization; use rustc_codegen_ssa::mir::IntrinsicResult; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 82ef99703b253..1416f4eec9c4a 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -7,8 +7,8 @@ use rustc_abi::{Align, Size}; use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; #[cfg(feature = "master")] -use rustc_codegen_ssa::errors::ExpectedPointerMutability; -use rustc_codegen_ssa::errors::InvalidMonomorphization; +use rustc_codegen_ssa::diagnostics::ExpectedPointerMutability; +use rustc_codegen_ssa::diagnostics::InvalidMonomorphization; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; From 75f5d185c178f87bfef5705866324ec9f1561422 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 16 Jul 2026 18:47:45 +0200 Subject: [PATCH 100/166] use core fallbacks for more `f16`/`f128` operations --- src/intrinsic/mod.rs | 36 +++++------------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index ff8312beb368f..98b67b1946d77 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -95,7 +95,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::floorf64 => "floor", sym::ceilf32 => "ceilf", sym::ceilf64 => "ceil", - sym::powf128 => return float_intrinsic(cx, cx.type_f128(), "powf128"), sym::truncf32 => "truncf", sym::truncf64 => "trunc", // We match the LLVM backend and lower this to `rint`. @@ -118,12 +117,7 @@ fn get_simple_function_f128<'gcc, 'tcx>( let func_name = match name { sym::ceilf128 => "ceilf128", sym::fabs => "fabsf128", - sym::expf128 => "expf128", - sym::exp2f128 => "exp2f128", sym::floorf128 => "floorf128", - sym::logf128 => "logf128", - sym::log2f128 => "log2f128", - sym::log10f128 => "log10f128", sym::truncf128 => "truncf128", sym::roundf128 => "roundf128", sym::round_ties_even_f128 => "roundevenf128", @@ -167,14 +161,8 @@ fn f16_builtin<'gcc, 'tcx>( let builtin_name = match name { sym::ceilf16 => "__builtin_ceilf", sym::copysignf16 => "__builtin_copysignf", - sym::expf16 => "expf", - sym::exp2f16 => "exp2f", sym::floorf16 => "__builtin_floorf", sym::fmaf16 => "fmaf", - sym::logf16 => "logf", - sym::log2f16 => "log2f", - sym::log10f16 => "log10f", - sym::powf16 => "__builtin_powf", sym::roundf16 => "__builtin_roundf", sym::round_ties_even_f16 => "__builtin_rintf", sym::sqrtf16 => "__builtin_sqrtf", @@ -209,14 +197,11 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let simple = get_simple_intrinsic(self, name); let value = match name { - _ if simple.is_some() => { - let func = simple.expect("simple intrinsic function"); - self.cx.context.new_call( - self.location, - func, - &args.iter().map(|arg| arg.immediate()).collect::>(), - ) - } + _ if let Some(func) = simple => self.cx.context.new_call( + self.location, + func, + &args.iter().map(|arg| arg.immediate()).collect::>(), + ), // FIXME(antoyo): We can probably remove these and use the fallback intrinsic implementation. sym::minimumf32 | sym::minimumf64 | sym::maximumf32 | sym::maximumf64 => { let (ty, func_name) = match name { @@ -245,14 +230,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::ceilf16 | sym::copysignf16 - | sym::expf16 - | sym::exp2f16 | sym::floorf16 | sym::fmaf16 - | sym::logf16 - | sym::log2f16 - | sym::log10f16 - | sym::powf16 | sym::roundf16 | sym::round_ties_even_f16 | sym::sqrtf16 @@ -263,11 +242,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc | sym::roundf128 | sym::round_ties_even_f128 | sym::sqrtf128 - | sym::expf128 - | sym::exp2f128 - | sym::logf128 - | sym::log2f128 - | sym::log10f128 if self.cx.supports_f128_type => { let func = get_simple_function_f128(span, self, name); From 61a02cd8e08d30a49de652b138f5f2effb80aad2 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 16 Jul 2026 21:48:09 +0200 Subject: [PATCH 101/166] add support for explicit tail calls (`musttail`) --- Cargo.lock | 8 ++-- Cargo.toml | 2 +- src/builder.rs | 93 ++++++++++++++++++++++++++------------ src/errors.rs | 4 -- tests/failing-ui-tests.txt | 7 --- 5 files changed, 69 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3786a94b2418d..87f95e11ec698 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2c6ee720b5459292678267e9ffed8229b11e0e27fc5ecf7618634dc6272fa4" +checksum = "796be22e4854830de9e785ddbd814b275a80fe6a975598be355c239e5b4eabe1" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cea2ed05e093fd90bd21fa03a7d09e07f62103ce94de21859f048c9a6c18e42" +checksum = "3db558fc13a541c478ef791d2a88cdb276a9373f46fb2e8aa30734d19037ffa6" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index aba88456801f3..86b7b56acdcfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "3.4.0", features = ["dlopen"] } +gccjit = { version = "3.5.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/src/builder.rs b/src/builder.rs index 9eca9eeb620a6..67c6616b5195b 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -36,7 +36,6 @@ use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; use crate::abi::FnAbiGccExt; use crate::common::{SignType, TypeReflection, type_is_pointer}; use crate::context::CodegenCx; -use crate::errors; use crate::intrinsic::llvm; use crate::type_of::LayoutGccExt; @@ -312,14 +311,48 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.block.get_function() } + /// Shared implementation of `call` and `tail_call`. For tail call it is important that this + /// returns a bare call, and not the result assigned to a local, or the result of `add_eval`. + fn build_call( + &mut self, + typ: Type<'gcc>, + fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, + func: RValue<'gcc>, + args: &[RValue<'gcc>], + funclet: Option<&Funclet>, + must_tail: bool, + ) -> RValue<'gcc> { + // FIXME(antoyo): remove when having a proper API. + let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; + let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { + // FIXME(antoyo): remove when the API supports a different type for functions. + let func: Function<'gcc> = self.cx.rvalue_as_function(func); + self.function_call(func, args, funclet, must_tail) + } else { + // If it's a not function that was defined, it's a function pointer. + self.function_ptr_call(typ, fn_abi, func, args, funclet, must_tail) + }; + if let Some(_fn_abi) = fn_abi { + // FIXME(bjorn3): Apply function attributes + } + call + } + pub fn function_call( &mut self, func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, + must_tail: bool, ) -> RValue<'gcc> { let args = self.check_call("call", func, args); + let call = self.cx.context.new_call(self.location, func, &args); + if must_tail { + // Return the bare tail call, don't assign or `add_eval` it yet. + return call; + } + // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = func.get_return_type(); @@ -331,15 +364,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { return_type, format!("returnValue{}", self.next_value_counter()), ); - self.block.add_assignment( - self.location, - result, - self.cx.context.new_call(self.location, func, &args), - ); + self.block.add_assignment(self.location, result, call); result.to_rvalue() } else { - self.block - .add_eval(self.location, self.cx.context.new_call(self.location, func, &args)); + self.block.add_eval(self.location, call); // Return dummy value when not having return value. self.context.new_rvalue_zero(self.isize_type) } @@ -352,6 +380,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, + must_tail: bool, ) -> RValue<'gcc> { let func_ptr_type = { let func_ptr_type = func_ptr.get_type(); @@ -376,6 +405,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let args_adjusted = args.len() != previous_arg_count; let args = self.check_ptr_call("call", func_ptr, &args, &on_stack_param_indices); + if must_tail { + // Return the bare tail call, don't assign or `add_eval` it yet. + let call = self.cx.context.new_call_through_ptr(self.location, func_ptr, &args); + return call; + } + // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = gcc_func.get_return_type(); @@ -1798,34 +1833,34 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { funclet: Option<&Funclet>, _instance: Option>, ) -> RValue<'gcc> { - // FIXME(antoyo): remove when having a proper API. - let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; - let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { - // FIXME(antoyo): remove when the API supports a different type for functions. - let func: Function<'gcc> = self.cx.rvalue_as_function(func); - self.function_call(func, args, funclet) - } else { - // If it's a not function that was defined, it's a function pointer. - self.function_ptr_call(typ, fn_abi, func, args, funclet) - }; - if let Some(_fn_abi) = fn_abi { - // FIXME(bjorn3): Apply function attributes - } - call + self.build_call(typ, fn_abi, func, args, funclet, false) } fn tail_call( &mut self, - _llty: Self::Type, + llty: Self::Type, _fn_attrs: Option<&CodegenFnAttrs>, - _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - _llfn: Self::Value, - _args: &[Self::Value], - _funclet: Option<&Self::Funclet>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + llfn: Self::Value, + args: &[Self::Value], + funclet: Option<&Self::Funclet>, _instance: Option>, ) { - // FIXME: implement support for explicit tail calls like rustc_codegen_llvm. - self.tcx.dcx().emit_fatal(errors::ExplicitTailCallsUnsupported); + // `emit_call` returns a bare call for here, it has not been assigned or passed to add_eval. + let call = self.build_call(llty, Some(fn_abi), llfn, args, funclet, true); + call.set_require_tail_call(true); + + let return_type = self.current_func().get_return_type(); + let void_type = self.context.new_type::<()>(); + + if return_type == void_type { + // For a void return the call is emitted as its own statement, immediately + // followed by a void return, so the tail call sits in tail position. + self.llbb().add_eval(self.location, call); + self.ret_void(); + } else { + self.ret(call) + } } fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { diff --git a/src/errors.rs b/src/errors.rs index de633d3bdde79..67723ebd2f30b 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -20,10 +20,6 @@ pub(crate) struct LtoBitcodeFromRlib { pub gcc_err: String, } -#[derive(Diagnostic)] -#[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")] -pub(crate) struct ExplicitTailCallsUnsupported; - #[derive(Diagnostic)] #[diag("asm contains a NUL byte")] pub(crate) struct NulBytesInAsm { diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index bf274f2c78133..84bfbc19c0a8d 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -71,11 +71,6 @@ tests/ui/linking/no-gc-encapsulation-symbols.rs tests/ui/panics/unwind-force-no-unwind-tables.rs tests/ui/attributes/fn-align-dyn.rs tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs -tests/ui/explicit-tail-calls/recursion-etc.rs -tests/ui/explicit-tail-calls/indexer.rs -tests/ui/explicit-tail-calls/drop-order.rs -tests/ui/explicit-tail-calls/become-cast-return.rs -tests/ui/explicit-tail-calls/become-indirect-return.rs tests/ui/panics/panic-abort-backtrace-without-debuginfo.rs tests/ui/sanitizer/kcfi-c-variadic.rs tests/ui/sanitizer/kcfi/fn-trait-objects.rs @@ -97,7 +92,6 @@ tests/ui/eii/linking/track_caller_cross_crate.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs tests/ui/eii/default/call_default_panics.rs -tests/ui/explicit-tail-calls/indirect.rs tests/ui/traits/inheritance/self-in-supertype.rs tests/ui/fmt/fmt_debug/shallow.rs tests/ui/eii/eii_impl_with_contract.rs @@ -109,5 +103,4 @@ tests/ui/eii/static/default.rs tests/ui/eii/static/default_cross_crate.rs tests/ui/eii/static/default_explicit.rs tests/ui/eii/static/default_cross_crate_explicit.rs -tests/ui/explicit-tail-calls/default-trait-method.rs tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs From 5e2d1e296aae0221ac2a0d4a6967779005ff48f8 Mon Sep 17 00:00:00 2001 From: kulst Date: Tue, 6 Jan 2026 21:42:06 +0100 Subject: [PATCH 102/166] Treat `-Ctarget-cpu` as a target-modifier when targeting AVR, AMDGCN and NVPTX For AVR, AMDGCN, and NVPTX, crates built with different target CPU values are not generally link-compatible. Add a `requires_consistent_cpu` flag to the target spec and enable it for these targets. When the flag is set, treat `-Ctarget-cpu` as a target modifier and require all linked crates to agree on its value. Reject `-Ctarget-cpu=native` before codegen for targets that set `requires_consistent_cpu` to true. Also do not include `native` in the printed `target-cpus` list for such targets. Add tests covering: - which built-in targets set `requires-consistent-cpu` - cross-crate behavior with and without `requires-consistent-cpu` - that an omitted `-Ctarget-cpu` compares equal to an explicitly specified default CPU - rejection and printing behavior for `native` - precedence of repeated `-Ctarget-cpu` flags in metadata comparison and LLVM IR --- src/gcc_util.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 330b5ff6828d5..a95b4da28eb63 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -3,6 +3,7 @@ use gccjit::Context; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; use rustc_session::Session; +use rustc_session::config::NATIVE_CPU; use rustc_target::spec::Arch; fn gcc_features_by_flags(sess: &Session, features: &mut Vec) { @@ -115,7 +116,7 @@ fn arch_to_gcc(name: &str) -> &str { } fn handle_native(name: &str) -> &str { - if name != "native" { + if name != NATIVE_CPU { return arch_to_gcc(name); } From 95311e7977ca6fa91b90bfc0b1bb203e0adbc8db Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 17 Jul 2026 09:21:45 -0400 Subject: [PATCH 103/166] Stop unconditionnaly remove some UI tests directories --- build_system/src/test.rs | 15 --------------- tests/failing-ui-tests.txt | 5 +++++ 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index f0c6960b68a7f..c7f104ca4ca63 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1022,21 +1022,6 @@ where true, )?; } else { - walk_dir( - rust_path.join("tests/ui"), - &mut |dir| { - let dir_name = dir.file_name().and_then(|name| name.to_str()).unwrap_or(""); - if ["abi", "extern", "proc-macro", "threads-sendsync"].contains(&dir_name) { - remove_dir_all(dir).map_err(|error| { - format!("Failed to remove folder `{}`: {:?}", dir.display(), error) - })?; - } - Ok(()) - }, - &mut |_| Ok(()), - false, - )?; - // These two functions are used to remove files that are known to not be working currently // with the GCC backend to reduce noise. fn dir_handling(keep_lto_tests: bool) -> impl Fn(&Path) -> Result<(), String> { diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 84bfbc19c0a8d..5d55ad31d1e1d 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -104,3 +104,8 @@ tests/ui/eii/static/default_cross_crate.rs tests/ui/eii/static/default_explicit.rs tests/ui/eii/static/default_cross_crate_explicit.rs tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs +tests/ui/abi/rust-tail-cc.rs +tests/ui/abi/rust-preserve-none-cc.rs +tests/ui/abi/stack-protector.rs +tests/ui/extern/extern-types-field-offset.rs +tests/ui/abi/stack-probes-lto.rs From 2453a68ad4d679788ad87f96f8219d4980e8d4e7 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 17 Jul 2026 17:49:21 -0400 Subject: [PATCH 104/166] Add command to run specified UI tests --- build_system/src/test.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index c7f104ca4ca63..fcbc09b27082c 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -28,6 +28,7 @@ fn get_runners() -> Runners { ("Run failing ui pattern tests", test_failing_ui_pattern_tests), ); runners.insert("--test-failing-rustc", ("Run failing rustc tests", test_failing_rustc)); + runners.insert("--run-ui-tests", ("Run specified rustc UI tests", run_ui_tests)); runners.insert("--projects", ("Run the tests of popular crates", test_projects)); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); runners.insert("--alloc-tests", ("Run alloc tests", test_alloc)); @@ -1218,6 +1219,45 @@ fn test_failing_ui_pattern_tests(env: &Env, args: &TestArg) -> Result<(), String ) } +fn run_ui_tests(env: &Env, args: &TestArg) -> Result<(), String> { + let mut env = env.clone(); + let rust_path = setup_rustc(&mut env, args)?; + + let extra = + if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" }; + + let rustc_args = format!( + "{test_flags} -Zcodegen-backend={backend} --sysroot {sysroot}{extra}", + test_flags = env.get("TEST_FLAGS").unwrap_or(&String::new()), + backend = args.config_info.cg_backend_path, + sysroot = args.config_info.sysroot_path, + extra = extra, + ); + + env.get_mut("RUSTFLAGS").unwrap().clear(); + + let mut command: Vec<&dyn AsRef> = vec![ + &"./x.py", + &"test", + &"--run", + &"always", + &"--stage", + &"0", + &"--set", + &"build.compiletest-allow-stage0=true", + &"--compiletest-rustc-args", + &rustc_args, + &"--bypass-ignore-backends", + ]; + + for test_name in &args.test_args { + command.push(test_name); + } + + run_command_with_output_and_env(&command, Some(&rust_path), Some(&env))?; + Ok(()) +} + fn retain_files_callback<'a>( file_path: &'a str, test_type: &'a str, From d5ed2d4b20de839b4fe7bf9924151629be36826d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 17 Jul 2026 17:49:54 -0400 Subject: [PATCH 105/166] Implement stack protector --- src/gcc_util.rs | 9 ++++++++- tests/failing-ui-tests.txt | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 2615d93e427d4..79bbb8a72dfae 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -7,7 +7,7 @@ use gccjit::Version; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; use rustc_session::Session; -use rustc_target::spec::{Arch, RelocModel}; +use rustc_target::spec::{Arch, RelocModel, StackProtector}; fn gcc_features_by_flags(sess: &Session, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); @@ -204,6 +204,13 @@ pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { }); } + match sess.stack_protector() { + StackProtector::All => context.add_command_line_option("-fstack-protector-all"), + StackProtector::Strong => context.add_command_line_option("-fstack-protector-strong"), + StackProtector::Basic => context.add_command_line_option("-fstack-protector"), + StackProtector::None => (), + } + add_pic_option(&context, sess.relocation_model()); let target_cpu = target_cpu(sess); diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 5d55ad31d1e1d..97a58cc89affd 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -106,6 +106,5 @@ tests/ui/eii/static/default_cross_crate_explicit.rs tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs tests/ui/abi/rust-tail-cc.rs tests/ui/abi/rust-preserve-none-cc.rs -tests/ui/abi/stack-protector.rs tests/ui/extern/extern-types-field-offset.rs tests/ui/abi/stack-probes-lto.rs From 6a44cfa01c023597cc4d4707759d926bd649839e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 17 Jul 2026 18:30:11 -0400 Subject: [PATCH 106/166] Do not stop on error in clean ui-tests --- build_system/src/clean.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_system/src/clean.rs b/build_system/src/clean.rs index 43f01fdf35ecb..ec2092ee92ef5 100644 --- a/build_system/src/clean.rs +++ b/build_system/src/clean.rs @@ -74,7 +74,8 @@ fn clean_ui_tests() -> Result<(), String> { let path = Path::new(crate::BUILD_DIR) .join("rust/build/x86_64-unknown-linux-gnu/test/") .join(directory); - run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None)?; + // The directory might not exist, so ignore the error. + let _ = run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None); } Ok(()) } From 10ceee0c23faa7017c7c3c798f40ff0a1fe3f2fa Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 17 Jul 2026 18:30:49 -0400 Subject: [PATCH 107/166] Stop removing tests containing 'thread' --- build_system/src/test.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index fcbc09b27082c..7e46389e46fbb 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -946,7 +946,6 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< "//@ known-bug", "-Cllvm-args", "//~", - "thread", ] .iter() .any(|check| line.contains(check)) From ebe0b3953c8e2e7347ede63beee05fdc5121e010 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 17 Jul 2026 18:33:54 -0400 Subject: [PATCH 108/166] Implement stack probes --- src/gcc_util.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 79bbb8a72dfae..0e5992c7a439c 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -7,7 +7,7 @@ use gccjit::Version; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; use rustc_session::Session; -use rustc_target::spec::{Arch, RelocModel, StackProtector}; +use rustc_target::spec::{Arch, RelocModel, StackProbeType, StackProtector}; fn gcc_features_by_flags(sess: &Session, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); @@ -211,6 +211,15 @@ pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { StackProtector::None => (), } + match sess.target.stack_probes { + StackProbeType::None => (), + StackProbeType::Inline | StackProbeType::InlineOrCall { .. } => { + context.add_command_line_option("-fstack-clash-protection") + } + // FIXME(antoyo): We should define the stack probe symbol to be __rust_probestack, but it seems GCC cannot do that. + StackProbeType::Call => (), + }; + add_pic_option(&context, sess.relocation_model()); let target_cpu = target_cpu(sess); From e5e3a494a29bce1f1caddb291203c388104ec943 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 17 Jul 2026 20:18:50 -0400 Subject: [PATCH 109/166] Add new failing UI tests --- tests/failing-ui-tests.txt | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 97a58cc89affd..997255a957187 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -107,4 +107,29 @@ tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs tests/ui/abi/rust-tail-cc.rs tests/ui/abi/rust-preserve-none-cc.rs tests/ui/extern/extern-types-field-offset.rs -tests/ui/abi/stack-probes-lto.rs +tests/ui/numbers-arithmetic/int-abs-overflow.rs +tests/ui/numbers-arithmetic/issue-8460.rs +tests/ui/panics/panic-handler-chain-update-hook.rs +tests/ui/panics/panic-handler-chain.rs +tests/ui/panics/panic-handler-set-twice.rs +tests/ui/panics/panic-recover-propagate.rs +tests/ui/panics/panic-in-dtor-drops-fields.rs +tests/ui/panics/panic-handler-flail-wildly.rs +tests/ui/panics/rvalue-cleanup-during-box-panic.rs +tests/ui/process/multi-panic.rs +tests/ui/sepcomp/sepcomp-unwind.rs +tests/ui/structs/unit-like-struct-drop-run.rs +tests/ui/threads-sendsync/unwind-resource.rs +tests/ui/array-slice-vec/box-of-array-of-drop-2.rs +tests/ui/array-slice-vec/box-of-array-of-drop-1.rs +tests/ui/array-slice-vec/nested-vec-3.rs +tests/ui/array-slice-vec/slice-panic-1.rs +tests/ui/array-slice-vec/slice-panic-2.rs +tests/ui/backtrace/synchronized-panic-handler.rs +tests/ui/cross-crate/mut-ref-write-visible-after-unwind.rs +tests/ui/drop/drop-once-on-panic.rs +tests/ui/drop/enum-destructor-on-unwind.rs +tests/ui/drop/drop-trait-enum.rs +tests/ui/drop/panic-during-slice-init.rs +tests/ui/drop/terminate-in-initializer.rs +tests/ui/eii/track_caller.rs From e6a5f92abae996c415df34e30725812e1adeb6b2 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 17 Jul 2026 20:50:58 -0400 Subject: [PATCH 110/166] Add new failing LTO tests --- tests/failing-lto-tests.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/failing-lto-tests.txt b/tests/failing-lto-tests.txt index 4c62c35a512c1..e98d2aab9361b 100644 --- a/tests/failing-lto-tests.txt +++ b/tests/failing-lto-tests.txt @@ -4,3 +4,7 @@ tests/ui/uninhabited/uninhabited-transparent-return-abi.rs tests/ui/coroutine/panic-drops-resume.rs tests/ui/coroutine/panic-drops.rs tests/ui/coroutine/panic-safe.rs +tests/ui/panic-handler/catch-unwind-during-unwind-68696.rs +tests/ui/threads-sendsync/task-stderr.rs +tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs From 721e0a8be922844dbd9a0aa035fc76a6f3298cc2 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 18 Jul 2026 16:50:31 +0200 Subject: [PATCH 111/166] modify `asm_experimental_reg` example to not need x86_64 --- .../feature-gate-asm_experimental_reg.rs | 23 ++++++++--- .../feature-gate-asm_experimental_reg.stderr | 40 ++++++++++++++++--- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs index bfc79ae8db663..0d2c4fe2b67c3 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs @@ -1,16 +1,27 @@ //@ add-minicore -//@ compile-flags: --target x86_64-unknown-linux-gnu -//@ needs-llvm-components: x86 +//@ compile-flags: --target loongarch64-unknown-none +//@ needs-llvm-components: loongarch //@ ignore-backends: gcc -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd)] #![crate_type = "rlib"] #![no_core] +#![allow(non_camel_case_types)] extern crate minicore; use minicore::*; -unsafe fn main() { - asm!("{:x}", in(xmm_reg) 0u128); - //~^ ERROR type `u128` cannot be used with this register class in stable +#[repr(simd)] +pub struct i8x16([i8; 16]); + +impl Copy for i8x16 {} + +unsafe fn main(x: i8x16) -> i8x16 { + let y; + asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); + //~^ ERROR register class `vreg` can only be used as a clobber in stable + //~| ERROR register class `vreg` can only be used as a clobber in stable + //~| ERROR type `i8x16` cannot be used with this register class in stable + //~| ERROR type `i8x16` cannot be used with this register class in stable + y } diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr index 4042ee7029b53..fb54438ef589e 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr @@ -1,13 +1,43 @@ -error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:14:30 +error[E0658]: register class `vreg` can only be used as a clobber in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:21:41 | -LL | asm!("{:x}", in(xmm_reg) 0u128); - | ^^^^^ +LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); + | ^^^^^^^^^^^ | = note: see issue #133416 for more information = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0658]: register class `vreg` can only be used as a clobber in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:21:54 + | +LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); + | ^^^^^^^^^^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: type `i8x16` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:21:51 + | +LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); + | ^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: type `i8x16` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:21:63 + | +LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); + | ^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. From b68b9bc201d6b9284c596657855ee8797316b227 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 18 Jul 2026 16:59:52 +0200 Subject: [PATCH 112/166] stabilize passing 128-bit integers via vector registers with `asm!` on x86 --- compiler/rustc_target/src/asm/x86.rs | 44 ++---- .../language-features/asm-experimental-reg.md | 3 - .../x86_64/bad-reg.experimental_reg.stderr | 64 ++++----- tests/ui/asm/x86_64/bad-reg.rs | 21 +-- tests/ui/asm/x86_64/bad-reg.stable.stderr | 127 +++++------------- tests/ui/asm/x86_64/type-check-3.stderr | 2 +- 6 files changed, 83 insertions(+), 178 deletions(-) diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs index 6f0faffa32984..c582c06d8f4bb 100644 --- a/compiler/rustc_target/src/asm/x86.rs +++ b/compiler/rustc_target/src/asm/x86.rs @@ -105,7 +105,7 @@ impl X86InlineAsmRegClass { pub fn supported_types( self, arch: InlineAsmArch, - allow_experimental_reg: bool, + _allow_experimental_reg: bool, ) -> &'static [(InlineAsmType, Option)] { match self { Self::reg | Self::reg_abcd => { @@ -117,48 +117,24 @@ impl X86InlineAsmRegClass { } Self::reg_byte => types! { _: I8; }, Self::xmm_reg => { - if allow_experimental_reg { - types! { - sse: I32, I64, I128, F16, F32, F64, F128, - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); - } - } else { - types! { - sse: I32, I64, F16, F32, F64, F128, - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); - } + types! { + sse: I32, I64, I128, F16, F32, F64, F128, + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); } } Self::ymm_reg => { - if allow_experimental_reg { - types! { - avx: I32, I64, I128, F16, F32, F64, F128, - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2), - VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4); - } - } else { - types! { - avx: I32, I64, F16, F32, F64, F128, - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2), - VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4); - } + types! { + avx: I32, I64, I128, F16, F32, F64, F128, + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2), + VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4); } } Self::zmm_reg => { - if allow_experimental_reg { - types! { - avx512f: I32, I64, I128, F16, F32, F64, F128, - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2), - VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4), - VecI8(64), VecI16(32), VecI32(16), VecI64(8), VecF16(32), VecF32(16), VecF64(8); - } - } else { - types! { - avx512f: I32, I64, F16, F32, F64, F128, + types! { + avx512f: I32, I64, I128, F16, F32, F64, F128, VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2), VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4), VecI8(64), VecI16(32), VecI32(16), VecI64(8), VecF16(32), VecF32(16), VecF64(8); - } } } diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-reg.md b/src/doc/unstable-book/src/language-features/asm-experimental-reg.md index 095b541da6e46..db72c44a2dc92 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-reg.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-reg.md @@ -19,9 +19,6 @@ This tracks support for additional registers in architectures where inline assem | Architecture | Register class | Target feature | Allowed types | | ------------ | -------------- | -------------- | ------------- | -| x86 | `xmm_reg` | `sse` | `i128` | -| x86 | `ymm_reg` | `avx` | `i128` | -| x86 | `zmm_reg` | `avx512f` | `i128` | | LoongArch | `vreg` | `lsx` | `f32`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | | LoongArch | `xreg` | `lasx` | `f32`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`,
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` | diff --git a/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr b/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr index fe2a53aec5d48..a03791b9222cc 100644 --- a/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr +++ b/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr @@ -1,5 +1,5 @@ error: invalid register class `foo`: unknown register class - --> $DIR/bad-reg.rs:20:20 + --> $DIR/bad-reg.rs:19:20 | LL | asm!("{}", in(foo) foo); | ^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | asm!("{}", in(foo) foo); = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, and `tmm_reg` error: invalid register `foo`: unknown register - --> $DIR/bad-reg.rs:22:18 + --> $DIR/bad-reg.rs:21:18 | LL | asm!("", in("foo") foo); | ^^^^^^^^^^^^^ error: invalid asm template modifier `z` for this register class - --> $DIR/bad-reg.rs:24:15 + --> $DIR/bad-reg.rs:23:15 | LL | asm!("{:z}", in(reg) foo); | ^^^^ ----------- argument @@ -23,7 +23,7 @@ LL | asm!("{:z}", in(reg) foo); = note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, and `r` error: invalid asm template modifier `r` for this register class - --> $DIR/bad-reg.rs:26:15 + --> $DIR/bad-reg.rs:25:15 | LL | asm!("{:r}", in(xmm_reg) foo); | ^^^^ --------------- argument @@ -33,7 +33,7 @@ LL | asm!("{:r}", in(xmm_reg) foo); = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, and `z` error: asm template modifiers are not allowed for `const` arguments - --> $DIR/bad-reg.rs:28:15 + --> $DIR/bad-reg.rs:27:15 | LL | asm!("{:a}", const 0); | ^^^^ ------- argument @@ -41,7 +41,7 @@ LL | asm!("{:a}", const 0); | template modifier error: asm template modifiers are not allowed for `sym` arguments - --> $DIR/bad-reg.rs:30:15 + --> $DIR/bad-reg.rs:29:15 | LL | asm!("{:a}", sym main); | ^^^^ -------- argument @@ -49,67 +49,67 @@ LL | asm!("{:a}", sym main); | template modifier error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", in("ebp") foo); | ^^^^^^^^^^^^^ error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", in("rsp") foo); | ^^^^^^^^^^^^^ error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", in("ip") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:43:18 + --> $DIR/bad-reg.rs:42:18 | LL | asm!("", in("st(2)") foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", in("mm0") foo); | ^^^^^^^^^^^^^ error: register class `kreg0` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:49:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", in("k0") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:54:20 + --> $DIR/bad-reg.rs:53:20 | LL | asm!("{}", in(x87_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:57:20 + --> $DIR/bad-reg.rs:56:20 | LL | asm!("{}", in(mmx_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:60:20 + --> $DIR/bad-reg.rs:59:20 | LL | asm!("{}", out(x87_reg) _); | ^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:62:20 + --> $DIR/bad-reg.rs:61:20 | LL | asm!("{}", out(mmx_reg) _); | ^^^^^^^^^^^^^^ error: register `al` conflicts with register `eax` - --> $DIR/bad-reg.rs:68:33 + --> $DIR/bad-reg.rs:67:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` @@ -117,7 +117,7 @@ LL | asm!("", in("eax") foo, in("al") bar); | register `eax` error: register `rax` conflicts with register `rax` - --> $DIR/bad-reg.rs:71:33 + --> $DIR/bad-reg.rs:70:33 | LL | asm!("", in("rax") foo, out("rax") bar); | ------------- ^^^^^^^^^^^^^^ register `rax` @@ -125,13 +125,13 @@ LL | asm!("", in("rax") foo, out("rax") bar); | register `rax` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:71:18 + --> $DIR/bad-reg.rs:70:18 | LL | asm!("", in("rax") foo, out("rax") bar); | ^^^^^^^^^^^^^ error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:76:34 + --> $DIR/bad-reg.rs:75:34 | LL | asm!("", in("xmm0") foo, in("ymm0") bar); | -------------- ^^^^^^^^^^^^^^ register `ymm0` @@ -139,7 +139,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar); | register `xmm0` error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:78:34 + --> $DIR/bad-reg.rs:77:34 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | -------------- ^^^^^^^^^^^^^^^ register `ymm0` @@ -147,25 +147,25 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar); | register `xmm0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:78:18 + --> $DIR/bad-reg.rs:77:18 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | ^^^^^^^^^^^^^^ error: cannot use register `bl`: rbx is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:37:18 | LL | asm!("", in("bl") foo); | ^^^^^^^^^^^^ error: cannot use register `bh`: rbx is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:39:18 | LL | asm!("", in("bh") foo); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:43:30 + --> $DIR/bad-reg.rs:42:30 | LL | asm!("", in("st(2)") foo); | ^^^ @@ -173,7 +173,7 @@ LL | asm!("", in("st(2)") foo); = note: register class `x87_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:46:28 + --> $DIR/bad-reg.rs:45:28 | LL | asm!("", in("mm0") foo); | ^^^ @@ -181,7 +181,7 @@ LL | asm!("", in("mm0") foo); = note: register class `mmx_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:49:27 + --> $DIR/bad-reg.rs:48:27 | LL | asm!("", in("k0") foo); | ^^^ @@ -189,7 +189,7 @@ LL | asm!("", in("k0") foo); = note: register class `kreg0` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:54:32 + --> $DIR/bad-reg.rs:53:32 | LL | asm!("{}", in(x87_reg) foo); | ^^^ @@ -197,7 +197,7 @@ LL | asm!("{}", in(x87_reg) foo); = note: register class `x87_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:57:32 + --> $DIR/bad-reg.rs:56:32 | LL | asm!("{}", in(mmx_reg) foo); | ^^^ @@ -205,7 +205,7 @@ LL | asm!("{}", in(mmx_reg) foo); = note: register class `mmx_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:68:42 + --> $DIR/bad-reg.rs:67:42 | LL | asm!("", in("eax") foo, in("al") bar); | ^^^ @@ -213,7 +213,7 @@ LL | asm!("", in("eax") foo, in("al") bar); = note: register class `reg_byte` supports these types: i8 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:73:27 + --> $DIR/bad-reg.rs:72:27 | LL | asm!("", in("al") foo, lateout("al") bar); | ^^^ @@ -221,7 +221,7 @@ LL | asm!("", in("al") foo, lateout("al") bar); = note: register class `reg_byte` supports these types: i8 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:73:46 + --> $DIR/bad-reg.rs:72:46 | LL | asm!("", in("al") foo, lateout("al") bar); | ^^^ diff --git a/tests/ui/asm/x86_64/bad-reg.rs b/tests/ui/asm/x86_64/bad-reg.rs index cc3def95508ff..3e9858f4d9664 100644 --- a/tests/ui/asm/x86_64/bad-reg.rs +++ b/tests/ui/asm/x86_64/bad-reg.rs @@ -3,7 +3,6 @@ //@ compile-flags: --target x86_64-unknown-linux-gnu -C target-feature=+avx2,+avx512f //@ needs-llvm-components: x86 #![cfg_attr(experimental_reg, feature(asm_experimental_reg))] - #![crate_type = "lib"] #![feature(no_core)] #![no_core] @@ -79,22 +78,16 @@ fn main() { //~^ ERROR register `ymm0` conflicts with register `xmm0` asm!("", in("xmm0") foo, lateout("ymm0") bar); - // Passing u128/i128 is currently experimental. + // Use 128-bit integers with vector registers. let mut xmmword = 0u128; - asm!("/* {:x} */", in(xmm_reg) xmmword); // requires asm_experimental_reg - //[stable]~^ ERROR type `u128` cannot be used with this register class in stable - asm!("/* {:x} */", out(xmm_reg) xmmword); // requires asm_experimental_reg - //[stable]~^ ERROR type `u128` cannot be used with this register class in stable + asm!("/* {:x} */", in(xmm_reg) xmmword); + asm!("/* {:x} */", out(xmm_reg) xmmword); - asm!("/* {:y} */", in(ymm_reg) xmmword); // requires asm_experimental_reg - //[stable]~^ ERROR type `u128` cannot be used with this register class in stable - asm!("/* {:y} */", out(ymm_reg) xmmword); // requires asm_experimental_reg - //[stable]~^ ERROR type `u128` cannot be used with this register class in stable + asm!("/* {:y} */", in(ymm_reg) xmmword); + asm!("/* {:y} */", out(ymm_reg) xmmword); - asm!("/* {:z} */", in(zmm_reg) xmmword); // requires asm_experimental_reg - //[stable]~^ ERROR type `u128` cannot be used with this register class in stable - asm!("/* {:z} */", out(zmm_reg) xmmword); // requires asm_experimental_reg - //[stable]~^ ERROR type `u128` cannot be used with this register class in stable + asm!("/* {:z} */", in(zmm_reg) xmmword); + asm!("/* {:z} */", out(zmm_reg) xmmword); } } diff --git a/tests/ui/asm/x86_64/bad-reg.stable.stderr b/tests/ui/asm/x86_64/bad-reg.stable.stderr index d8a37933065e1..a03791b9222cc 100644 --- a/tests/ui/asm/x86_64/bad-reg.stable.stderr +++ b/tests/ui/asm/x86_64/bad-reg.stable.stderr @@ -1,5 +1,5 @@ error: invalid register class `foo`: unknown register class - --> $DIR/bad-reg.rs:20:20 + --> $DIR/bad-reg.rs:19:20 | LL | asm!("{}", in(foo) foo); | ^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | asm!("{}", in(foo) foo); = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, and `tmm_reg` error: invalid register `foo`: unknown register - --> $DIR/bad-reg.rs:22:18 + --> $DIR/bad-reg.rs:21:18 | LL | asm!("", in("foo") foo); | ^^^^^^^^^^^^^ error: invalid asm template modifier `z` for this register class - --> $DIR/bad-reg.rs:24:15 + --> $DIR/bad-reg.rs:23:15 | LL | asm!("{:z}", in(reg) foo); | ^^^^ ----------- argument @@ -23,7 +23,7 @@ LL | asm!("{:z}", in(reg) foo); = note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, and `r` error: invalid asm template modifier `r` for this register class - --> $DIR/bad-reg.rs:26:15 + --> $DIR/bad-reg.rs:25:15 | LL | asm!("{:r}", in(xmm_reg) foo); | ^^^^ --------------- argument @@ -33,7 +33,7 @@ LL | asm!("{:r}", in(xmm_reg) foo); = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, and `z` error: asm template modifiers are not allowed for `const` arguments - --> $DIR/bad-reg.rs:28:15 + --> $DIR/bad-reg.rs:27:15 | LL | asm!("{:a}", const 0); | ^^^^ ------- argument @@ -41,7 +41,7 @@ LL | asm!("{:a}", const 0); | template modifier error: asm template modifiers are not allowed for `sym` arguments - --> $DIR/bad-reg.rs:30:15 + --> $DIR/bad-reg.rs:29:15 | LL | asm!("{:a}", sym main); | ^^^^ -------- argument @@ -49,67 +49,67 @@ LL | asm!("{:a}", sym main); | template modifier error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", in("ebp") foo); | ^^^^^^^^^^^^^ error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", in("rsp") foo); | ^^^^^^^^^^^^^ error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", in("ip") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:43:18 + --> $DIR/bad-reg.rs:42:18 | LL | asm!("", in("st(2)") foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", in("mm0") foo); | ^^^^^^^^^^^^^ error: register class `kreg0` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:49:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", in("k0") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:54:20 + --> $DIR/bad-reg.rs:53:20 | LL | asm!("{}", in(x87_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:57:20 + --> $DIR/bad-reg.rs:56:20 | LL | asm!("{}", in(mmx_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:60:20 + --> $DIR/bad-reg.rs:59:20 | LL | asm!("{}", out(x87_reg) _); | ^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:62:20 + --> $DIR/bad-reg.rs:61:20 | LL | asm!("{}", out(mmx_reg) _); | ^^^^^^^^^^^^^^ error: register `al` conflicts with register `eax` - --> $DIR/bad-reg.rs:68:33 + --> $DIR/bad-reg.rs:67:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` @@ -117,7 +117,7 @@ LL | asm!("", in("eax") foo, in("al") bar); | register `eax` error: register `rax` conflicts with register `rax` - --> $DIR/bad-reg.rs:71:33 + --> $DIR/bad-reg.rs:70:33 | LL | asm!("", in("rax") foo, out("rax") bar); | ------------- ^^^^^^^^^^^^^^ register `rax` @@ -125,13 +125,13 @@ LL | asm!("", in("rax") foo, out("rax") bar); | register `rax` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:71:18 + --> $DIR/bad-reg.rs:70:18 | LL | asm!("", in("rax") foo, out("rax") bar); | ^^^^^^^^^^^^^ error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:76:34 + --> $DIR/bad-reg.rs:75:34 | LL | asm!("", in("xmm0") foo, in("ymm0") bar); | -------------- ^^^^^^^^^^^^^^ register `ymm0` @@ -139,7 +139,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar); | register `xmm0` error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:78:34 + --> $DIR/bad-reg.rs:77:34 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | -------------- ^^^^^^^^^^^^^^^ register `ymm0` @@ -147,25 +147,25 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar); | register `xmm0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:78:18 + --> $DIR/bad-reg.rs:77:18 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | ^^^^^^^^^^^^^^ error: cannot use register `bl`: rbx is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:37:18 | LL | asm!("", in("bl") foo); | ^^^^^^^^^^^^ error: cannot use register `bh`: rbx is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:39:18 | LL | asm!("", in("bh") foo); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:43:30 + --> $DIR/bad-reg.rs:42:30 | LL | asm!("", in("st(2)") foo); | ^^^ @@ -173,7 +173,7 @@ LL | asm!("", in("st(2)") foo); = note: register class `x87_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:46:28 + --> $DIR/bad-reg.rs:45:28 | LL | asm!("", in("mm0") foo); | ^^^ @@ -181,7 +181,7 @@ LL | asm!("", in("mm0") foo); = note: register class `mmx_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:49:27 + --> $DIR/bad-reg.rs:48:27 | LL | asm!("", in("k0") foo); | ^^^ @@ -189,7 +189,7 @@ LL | asm!("", in("k0") foo); = note: register class `kreg0` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:54:32 + --> $DIR/bad-reg.rs:53:32 | LL | asm!("{}", in(x87_reg) foo); | ^^^ @@ -197,7 +197,7 @@ LL | asm!("{}", in(x87_reg) foo); = note: register class `x87_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:57:32 + --> $DIR/bad-reg.rs:56:32 | LL | asm!("{}", in(mmx_reg) foo); | ^^^ @@ -205,7 +205,7 @@ LL | asm!("{}", in(mmx_reg) foo); = note: register class `mmx_reg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:68:42 + --> $DIR/bad-reg.rs:67:42 | LL | asm!("", in("eax") foo, in("al") bar); | ^^^ @@ -213,7 +213,7 @@ LL | asm!("", in("eax") foo, in("al") bar); = note: register class `reg_byte` supports these types: i8 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:73:27 + --> $DIR/bad-reg.rs:72:27 | LL | asm!("", in("al") foo, lateout("al") bar); | ^^^ @@ -221,73 +221,12 @@ LL | asm!("", in("al") foo, lateout("al") bar); = note: register class `reg_byte` supports these types: i8 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:73:46 + --> $DIR/bad-reg.rs:72:46 | LL | asm!("", in("al") foo, lateout("al") bar); | ^^^ | = note: register class `reg_byte` supports these types: i8 -error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:85:40 - | -LL | asm!("/* {:x} */", in(xmm_reg) xmmword); // requires asm_experimental_reg - | ^^^^^^^ - | - = note: see issue #133416 for more information - = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:87:41 - | -LL | asm!("/* {:x} */", out(xmm_reg) xmmword); // requires asm_experimental_reg - | ^^^^^^^ - | - = note: see issue #133416 for more information - = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:90:40 - | -LL | asm!("/* {:y} */", in(ymm_reg) xmmword); // requires asm_experimental_reg - | ^^^^^^^ - | - = note: see issue #133416 for more information - = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:92:41 - | -LL | asm!("/* {:y} */", out(ymm_reg) xmmword); // requires asm_experimental_reg - | ^^^^^^^ - | - = note: see issue #133416 for more information - = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:95:40 - | -LL | asm!("/* {:z} */", in(zmm_reg) xmmword); // requires asm_experimental_reg - | ^^^^^^^ - | - = note: see issue #133416 for more information - = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: type `u128` cannot be used with this register class in stable - --> $DIR/bad-reg.rs:97:41 - | -LL | asm!("/* {:z} */", out(zmm_reg) xmmword); // requires asm_experimental_reg - | ^^^^^^^ - | - = note: see issue #133416 for more information - = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 36 previous errors +error: aborting due to 30 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/asm/x86_64/type-check-3.stderr b/tests/ui/asm/x86_64/type-check-3.stderr index 5a7b349413e45..ea9a3955e7078 100644 --- a/tests/ui/asm/x86_64/type-check-3.stderr +++ b/tests/ui/asm/x86_64/type-check-3.stderr @@ -28,7 +28,7 @@ error: type `u8` cannot be used with this register class LL | asm!("{}", in(xmm_reg) 0u8); | ^^^ | - = note: register class `xmm_reg` supports these types: i32, i64, f16, f32, f64, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 + = note: register class `xmm_reg` supports these types: i32, i64, i128, f16, f32, f64, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: `avx512bw` target feature is not enabled --> $DIR/type-check-3.rs:27:29 From d017855c7de000fe0e355de9178b7c57badb448b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 18 Jul 2026 19:19:11 -0400 Subject: [PATCH 113/166] Fix --run-ui-tests command to always run the tests --- build_system/src/test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 7e46389e46fbb..cbaf58796983c 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1247,6 +1247,7 @@ fn run_ui_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"--compiletest-rustc-args", &rustc_args, &"--bypass-ignore-backends", + &"--force-rerun", ]; for test_name in &args.test_args { From c3cb935c2a0b0316647ca08e48c6ab415da50e45 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 20 Jul 2026 11:46:03 -0400 Subject: [PATCH 114/166] Switch to new_temp to avoid having big stack in debug mode --- src/builder.rs | 66 +++++++++++++++++++++---------------------- src/int.rs | 2 +- src/intrinsic/llvm.rs | 2 +- src/intrinsic/mod.rs | 8 +++--- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 67c6616b5195b..064527787c729 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -84,7 +84,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.atomic_load(dst.get_type(), dst, load_ordering, Size::from_bytes(size)); let previous_var = func.new_local(self.location, previous_value.get_type(), "previous_value"); - let return_value = func.new_local(self.location, previous_value.get_type(), "return_value"); + let return_value = self.new_temp(func, self.location, previous_value.get_type()); self.llbb().add_assignment(self.location, previous_var, previous_value); self.llbb().add_assignment(self.location, return_value, previous_var.to_rvalue()); @@ -359,11 +359,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let void_type = self.context.new_type::<()>(); let current_func = self.block.get_function(); if return_type != void_type { - let result = current_func.new_local( - self.location, - return_type, - format!("returnValue{}", self.next_value_counter()), - ); + let result = self.new_temp(current_func, self.location, return_type); self.block.add_assignment(self.location, result, call); result.to_rvalue() } else { @@ -427,11 +423,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { args_adjusted, orig_args, ); - let result = current_func.new_local( - self.location, - return_value.get_type(), - format!("ptrReturnValue{}", self.next_value_counter()), - ); + let result = self.new_temp(current_func, self.location, return_value.get_type()); self.block.add_assignment(self.location, result, return_value); result.to_rvalue() } else { @@ -477,11 +469,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let return_type = self.context.new_type::(); let current_func = self.block.get_function(); // FIXME(antoyo): return the new_call() directly? Since the overflow function has no side-effects. - let result = current_func.new_local( - self.location, - return_type, - format!("overflowReturnValue{}", self.next_value_counter()), - ); + let result = self.new_temp(current_func, self.location, return_type); self.block.add_assignment( self.location, result, @@ -671,8 +659,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let call = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); // FIXME(antoyo): use funclet here? self.block = current_block; - let return_value = - self.current_func().new_local(self.location, call.get_type(), "invokeResult"); + let return_value = self.new_temp(self.current_func(), self.location, call.get_type()); try_block.add_assignment(self.location, return_value, call); @@ -719,8 +706,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { if return_type == void_type { self.block.end_with_void_return(self.location) } else { - let return_value = - self.current_func().new_local(self.location, return_type, "unreachableReturn"); + let return_value = self.new_temp(self.current_func(), self.location, return_type); self.block.end_with_return(self.location, return_value) } } @@ -1039,11 +1025,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // the current basic block. Otherwise, it could be used in another basic block, causing a // dereference after a drop, for instance. let deref = ptr.dereference(self.location).to_rvalue(); - let loaded_value = function.new_local( - self.location, - aligned_type, - format!("loadedValue{}", self.next_value_counter()), - ); + let loaded_value = self.new_temp(function, self.location, aligned_type); block.add_assignment(self.location, loaded_value, deref); loaded_value.to_rvalue() } @@ -1161,7 +1143,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let next_bb = self.append_sibling_block("repeat_loop_next"); let ptr_type = start.get_type(); - let current = self.llbb().get_function().new_local(self.location, ptr_type, "loop_var"); + let current = self.new_temp(self.llbb().get_function(), self.location, ptr_type); let current_val = current.to_rvalue(); self.assign(current, start); @@ -1526,7 +1508,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { mut else_val: RValue<'gcc>, ) -> RValue<'gcc> { let func = self.current_func(); - let variable = func.new_local(self.location, then_val.get_type(), "selectVar"); + let variable = self.new_temp(func, self.location, then_val.get_type()); let then_block = func.new_block("then"); let else_block = func.new_block("else"); let after_block = func.new_block("after"); @@ -1672,11 +1654,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(not(feature = "master"))] fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { let value1 = self - .current_func() - .new_local(self.location, self.u8_type.make_pointer(), "landing_pad0") + .new_temp(self.current_func(), self.location, self.u8_type.make_pointer()) .to_rvalue(); - let value2 = - self.current_func().new_local(self.location, self.i32_type, "landing_pad1").to_rvalue(); + let value2 = self.new_temp(self.current_func(), self.location, self.i32_type).to_rvalue(); (value1, value2) } @@ -1744,7 +1724,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // NOTE: since success contains the call to the intrinsic, it must be added to the basic block before // expected so that we store expected after the call. - let success_var = self.current_func().new_local(self.location, self.bool_type, "success"); + let success_var = self.new_temp(self.current_func(), self.location, self.bool_type); self.llbb().add_assignment(self.location, success_var, success); (expected.to_rvalue(), success_var.to_rvalue()) @@ -2445,11 +2425,31 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.bitcast_if_needed(res, result_type) } + /// Create a temporary variable. + /// + /// GCC will use more stack space with a local variable than with a temporary variable in debug mode, + /// so in order to avoid having the stack probe test fail in CI, we avoid creating local variables for temporaries. + pub fn new_temp( + &self, + function: Function<'gcc>, + location: Option>, + typ: Type<'gcc>, + ) -> LValue<'gcc> { + #[cfg(feature = "master")] + { + function.new_temp(location, typ) + } + #[cfg(not(feature = "master"))] + { + function.new_local(location, typ, format!("temp{}", self.next_value_counter())) + } + } + // GCC doesn't like deeply nested expressions. // By assigning intermediate expressions to a variable, this allow us to avoid deeply nested // expressions and GCC will use much less RAM. fn assign_to_var(&self, value: RValue<'gcc>) -> RValue<'gcc> { - let var = self.current_func().new_local(self.location, value.get_type(), "opResult"); + let var = self.new_temp(self.current_func(), self.location, value.get_type()); self.llbb().add_assignment(self.location, var, value); var.to_rvalue() } diff --git a/src/int.rs b/src/int.rs index 8b84d7176cf62..13a867ab32366 100644 --- a/src/int.rs +++ b/src/int.rs @@ -432,7 +432,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) { // 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(self.location, self.int_type, "icmp_result"); + let result = self.new_temp(self.current_func(), self.location, self.int_type); let block1 = self.current_func().new_block("block1"); let block2 = self.current_func().new_block("block2"); let block3 = self.current_func().new_block("block3"); diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index c922d5cc41653..bdd5a71533ae9 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -877,7 +877,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( "__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.new_temp(builder.current_func(), None, return_value.get_type()); builder.llbb().add_assignment(None, success_variable, return_value); let field1 = builder.context.new_field(None, random_number.get_type(), "random_number"); diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 56f07661a2836..c9f3b57ec5ff1 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -936,7 +936,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let else_block = func.new_block("else"); let after_block = func.new_block("after"); - let result = func.new_local(None, self.u32_type, "zeros"); + let result = self.new_temp(func, None, self.u32_type); let zero = self.cx.gcc_zero(arg.get_type()); let cond = self.gcc_icmp(IntPredicate::IntEQ, arg, zero); self.llbb().end_with_conditional(None, cond, then_block, else_block); @@ -1017,7 +1017,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // else call it on the 64 high bits and add 64. In the else case, 64 high bits can't be 0 // because arg is not 0. - let result = self.current_func().new_local(None, result_type, "count_zeroes_results"); + let result = self.new_temp(self.current_func(), None, result_type); let cz_then_block = self.current_func().new_block("cz_then"); let cz_else_block = self.current_func().new_block("cz_else"); @@ -1132,8 +1132,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let loop_tail = func.new_block("tail"); let counter_type = self.int_type; - let counter = self.current_func().new_local(None, counter_type, "popcount_counter"); - let val = self.current_func().new_local(None, value_type, "popcount_value"); + let counter = self.new_temp(self.current_func(), None, counter_type); + let val = self.new_temp(self.current_func(), None, value_type); let zero = self.gcc_zero(counter_type); self.llbb().add_assignment(self.location, counter, zero); self.llbb().add_assignment(self.location, val, value); From 946b0fa4239e06736884a26d7133b3aab6f3c0e8 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 20 Jul 2026 18:00:39 -0400 Subject: [PATCH 115/166] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index 01a3f83465838..f1882be2c1007 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -6249f1b21d0c17856c6fa87def9edd0eaa968caf +31396c2f72909f5973b6acab17242f4e4fece99a From fa4cae59713d6fc11eadb788ddf576b03680190e Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Tue, 21 Jul 2026 11:46:36 +0900 Subject: [PATCH 116/166] codegen: add OperandValue::Uninit to skip stores for entirely-uninit constants MIR GVN propagates MaybeUninit::uninit() as `const ` in aggregate constructions and codegen emits a memcpy from an `[N x i8] undef` global for each such field, which LLVM materializes as zero-initialization. Instead of special-casing `all_bytes_uninit` at each call site, add a new `OperandValue::Uninit` variant that `eval_mir_constant_to_operand` returns for any all-bytes-uninit constant. `store_with_flags` is a no-op for this variant, so the fix applies uniformly across `Rvalue::Use`, `Rvalue::Repeat`, and `Rvalue::Aggregate` without per-site checks. The variant propagates through field extraction and transmutes, and is handled appropriately at the remaining call sites (function arguments, discriminant reads, debug info, etc.). --- src/intrinsic/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 09ad3254e5714..986c04e6b4813 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -629,7 +629,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc for arg in args { match arg.val { - OperandValue::ZeroSized => {} + OperandValue::ZeroSized | OperandValue::Uninit => {} OperandValue::Immediate(_) => call_args.push(arg.immediate()), OperandValue::Pair(a, b) => { call_args.push(a); From d76c33bf3bf7d86d5385ac5adfa47aa0d3254b16 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 21 Jul 2026 22:52:01 +0200 Subject: [PATCH 117/166] Update `gccjit` dependency version to `3.6.0` --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87f95e11ec698..edbaacf6ecca0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.5.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "796be22e4854830de9e785ddbd814b275a80fe6a975598be355c239e5b4eabe1" +checksum = "5bd96d5f5f1752c2f6ff639d19d51f2b64c6169981606f5066808685f75f58b4" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db558fc13a541c478ef791d2a88cdb276a9373f46fb2e8aa30734d19037ffa6" +checksum = "7a34e8df2602945338835eade9ef69a057203197ad32ec512a9c763b96dafab5" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 86b7b56acdcfa..02cce3c14a26d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "3.5.0", features = ["dlopen"] } +gccjit = { version = "3.6.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. From caa7473d8def2e36c16f6719cf43d5e9b85eaa17 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 21 Jul 2026 23:09:11 +0200 Subject: [PATCH 118/166] Add support for global variable aliases --- src/mono_item.rs | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/mono_item.rs b/src/mono_item.rs index d5874779021d2..5a782bc301a25 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -1,5 +1,5 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, VarAttribute}; +use gccjit::{FnAttribute, VarAttribute, LValue}; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; @@ -21,7 +21,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { def_id: DefId, _linkage: Linkage, visibility: Visibility, - symbol_name: &str, + global_name: &str, ) { let attrs = self.tcx.codegen_fn_attrs(def_id); let instance = Instance::mono(self.tcx, def_id); @@ -33,11 +33,19 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let gcc_type = self.layout_of(ty).gcc_type(self); let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); - let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section); - #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); - // FIXME(antoyo): set linkage. + let create_global = |this: &CodegenCx<'gcc, 'tcx>, name: &str, visibility: Visibility| { + let global = this.define_global(name, gcc_type, is_tls, attrs.link_section); + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + // FIXME(antoyo): set linkage. + global + }; + let global = create_global(self, global_name, visibility); + + let attrs = self.tcx.codegen_instance_attrs(instance.def); + self.add_static_aliases(&attrs.foreign_item_symbol_aliases, global_name, &create_global); + self.instances.borrow_mut().insert(instance, global); } @@ -77,3 +85,26 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { self.function_instances.borrow_mut().insert(instance, decl); } } + +#[cfg(feature = "master")] +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + fn add_static_aliases(&self, aliases: &[(DefId, Linkage, Visibility)], aliasee: &str, create_global: &F) + where F: Fn(&CodegenCx<'gcc, 'tcx>, &str, Visibility) -> LValue<'gcc> + { + for (alias, _linkage, visibility) in aliases { + let instance = Instance::mono(self.tcx, *alias); + let symbol_name = self.tcx.symbol_name(instance); + + let alias = create_global(self, symbol_name.name, *visibility); + alias.add_attribute(VarAttribute::Alias(aliasee)); + + // Add the alias name to the set of cached items, so there is no duplicate + // instance added to it during the normal `external static` codegen + let prev_entry = self.instances.borrow_mut().insert(instance, alias); + + // If there already was a previous entry, then `add_static_aliases` was called multiple times for the same `alias` + // which would result in incorrect codegen + assert!(prev_entry.is_none(), "An instance was already present for {instance:?}"); + } + } +} From 7f4f4e908d5a78ef3701d7372a1311482196fc6d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Jul 2026 00:45:12 +0200 Subject: [PATCH 119/166] Add support for function aliases --- src/mono_item.rs | 119 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 24 deletions(-) diff --git a/src/mono_item.rs b/src/mono_item.rs index 5a782bc301a25..85e59831a5b39 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -1,11 +1,16 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, VarAttribute, LValue}; +use std::borrow::Cow; + +#[cfg(feature = "master")] +use gccjit::{FnAttribute, Function, LValue, ToRValue, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; +#[cfg(feature = "master")] +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::mono::Visibility; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; @@ -44,6 +49,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let global = create_global(self, global_name, visibility); let attrs = self.tcx.codegen_instance_attrs(instance.def); + #[cfg(feature = "master")] self.add_static_aliases(&attrs.foreign_item_symbol_aliases, global_name, &create_global); self.instances.borrow_mut().insert(instance, global); @@ -58,38 +64,28 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { ) { 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)); - let decl = self.declare_fn(symbol_name, fn_abi); - //let attrs = self.tcx.codegen_instance_attrs(instance.def); - - attributes::from_fn_attrs(self, decl, instance); + let attrs = self.tcx.codegen_instance_attrs(instance.def); - // If we're compiling the compiler-builtins crate, e.g., the equivalent of - // compiler-rt, then we want to implicitly compile everything with hidden - // visibility as we're going to link this object all over the place but - // don't want the symbols to get exported. - if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { - #[cfg(feature = "master")] - decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); - } else if visibility != Visibility::Default { - #[cfg(feature = "master")] - decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); - } + let decl = + self.predefine_without_aliases(instance, &attrs, linkage, visibility, symbol_name); - // FIXME(antoyo): call set_link_section() to allow initializing argc/argv. - // FIXME(antoyo): set unique comdat. - // FIXME(antoyo): use inline attribute from there in linkage.set() above. + #[cfg(feature = "master")] + self.add_function_aliases(instance, decl, &attrs, &attrs.foreign_item_symbol_aliases); self.functions.borrow_mut().insert(symbol_name.to_string(), decl); self.function_instances.borrow_mut().insert(instance, decl); } } -#[cfg(feature = "master")] impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { - fn add_static_aliases(&self, aliases: &[(DefId, Linkage, Visibility)], aliasee: &str, create_global: &F) - where F: Fn(&CodegenCx<'gcc, 'tcx>, &str, Visibility) -> LValue<'gcc> + #[cfg(feature = "master")] + fn add_static_aliases( + &self, + aliases: &[(DefId, Linkage, Visibility)], + aliasee: &str, + create_global: &F, + ) where + F: Fn(&CodegenCx<'gcc, 'tcx>, &str, Visibility) -> LValue<'gcc>, { for (alias, _linkage, visibility) in aliases { let instance = Instance::mono(self.tcx, *alias); @@ -107,4 +103,79 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { assert!(prev_entry.is_none(), "An instance was already present for {instance:?}"); } } + + #[cfg(feature = "master")] + fn add_function_aliases( + &self, + aliasee_instance: Instance<'tcx>, + aliasee: Function<'gcc>, + attrs: &Cow<'_, CodegenFnAttrs>, + aliases: &[(DefId, Linkage, Visibility)], + ) { + for (alias, linkage, visibility) in aliases { + let symbol_name = self.tcx.symbol_name(Instance::mono(self.tcx, *alias)); + + // predefine another copy of the original instance + // with a new symbol name + let alias_fn_decl = self.predefine_without_aliases( + aliasee_instance, + attrs, + *linkage, + *visibility, + symbol_name.name, + ); + + let block = alias_fn_decl.new_block("start"); + let nb_params = alias_fn_decl.get_param_count(); + let mut args = Vec::with_capacity(nb_params); + for idx in 0..nb_params { + args.push(alias_fn_decl.get_param(idx as _).to_rvalue()); + } + + let void_type = self.context.new_type::<()>(); + let call = self.context.new_call(None, aliasee, &args); + if alias_fn_decl.get_return_type() == void_type { + block.add_eval(None, call); + block.end_with_void_return(None); + } else { + block.end_with_return(None, call); + } + } + } + + fn predefine_without_aliases( + &self, + instance: Instance<'tcx>, + _attrs: &Cow<'_, CodegenFnAttrs>, + linkage: Linkage, + visibility: Visibility, + symbol_name: &str, + ) -> Function<'gcc> { + let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); + self.linkage.set(base::linkage_to_gcc(linkage)); + let fn_decl = self.declare_fn(symbol_name, fn_abi); + + attributes::from_fn_attrs(self, fn_decl, instance); + + // If we're compiling the compiler-builtins crate, e.g., the equivalent of + // compiler-rt, then we want to implicitly compile everything with hidden + // visibility as we're going to link this object all over the place but + // don't want the symbols to get exported. + if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { + #[cfg(feature = "master")] + fn_decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); + } else if visibility != Visibility::Default { + #[cfg(feature = "master")] + fn_decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); + } + + // FIXME(GuillaumeGomez): Add support for link section for `Function`. + // fn_decl.set_link_section(&attrs.link_section); + + // FIXME(antoyo): set unique comdat. + // FIXME(antoyo): use inline attribute from there in linkage.set() above. + // FIXME: Should we handle dso? + + fn_decl + } } From 920bd4031e91b655c54899cb09d82e0176a84807 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Jul 2026 00:45:27 +0200 Subject: [PATCH 120/166] Remove newly passing eii ui tests --- tests/failing-ui-tests.txt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 997255a957187..512fb2b600ed3 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -80,21 +80,11 @@ tests/ui/thir-print/offset_of.rs tests/ui/iterators/rangefrom-overflow-debug.rs tests/ui/iterators/rangefrom-overflow-overflow-checks.rs tests/ui/iterators/iter-filter-count-debug-check.rs -tests/ui/eii/linking/codegen_single_crate.rs -tests/ui/eii/linking/codegen_cross_crate.rs -tests/ui/eii/default/local_crate.rs -tests/ui/eii/duplicate/multiple_impls.rs -tests/ui/eii/default/call_default.rs -tests/ui/eii/linking/same-symbol.rs -tests/ui/eii/privacy1.rs tests/ui/eii/default/call_impl.rs -tests/ui/eii/linking/track_caller_cross_crate.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs -tests/ui/eii/default/call_default_panics.rs tests/ui/traits/inheritance/self-in-supertype.rs tests/ui/fmt/fmt_debug/shallow.rs -tests/ui/eii/eii_impl_with_contract.rs tests/ui/eii/static/cross_crate_decl.rs tests/ui/eii/static/cross_crate_def.rs tests/ui/eii/static/same_address.rs @@ -132,4 +122,3 @@ tests/ui/drop/enum-destructor-on-unwind.rs tests/ui/drop/drop-trait-enum.rs tests/ui/drop/panic-during-slice-init.rs tests/ui/drop/terminate-in-initializer.rs -tests/ui/eii/track_caller.rs From d21eee5c2c81b85fe42f4aa7fc1ad0bab84a395f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Jul 2026 00:51:35 +0200 Subject: [PATCH 121/166] Fix clippy lints --- src/mono_item.rs | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/mono_item.rs b/src/mono_item.rs index 85e59831a5b39..7267580a97f4b 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -1,16 +1,12 @@ +use gccjit::Function; #[cfg(feature = "master")] -use std::borrow::Cow; - -#[cfg(feature = "master")] -use gccjit::{FnAttribute, Function, LValue, ToRValue, VarAttribute}; +use gccjit::{FnAttribute, LValue, ToRValue, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -#[cfg(feature = "master")] -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mono::Visibility; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; @@ -87,11 +83,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { ) where F: Fn(&CodegenCx<'gcc, 'tcx>, &str, Visibility) -> LValue<'gcc>, { - for (alias, _linkage, visibility) in aliases { - let instance = Instance::mono(self.tcx, *alias); + for &(alias, _linkage, visibility) in aliases { + let instance = Instance::mono(self.tcx, alias); let symbol_name = self.tcx.symbol_name(instance); - let alias = create_global(self, symbol_name.name, *visibility); + let alias = create_global(self, symbol_name.name, visibility); alias.add_attribute(VarAttribute::Alias(aliasee)); // Add the alias name to the set of cached items, so there is no duplicate @@ -109,19 +105,19 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { &self, aliasee_instance: Instance<'tcx>, aliasee: Function<'gcc>, - attrs: &Cow<'_, CodegenFnAttrs>, + attrs: &CodegenFnAttrs, aliases: &[(DefId, Linkage, Visibility)], ) { - for (alias, linkage, visibility) in aliases { - let symbol_name = self.tcx.symbol_name(Instance::mono(self.tcx, *alias)); + for &(alias, linkage, visibility) in aliases { + let symbol_name = self.tcx.symbol_name(Instance::mono(self.tcx, alias)); // predefine another copy of the original instance // with a new symbol name let alias_fn_decl = self.predefine_without_aliases( aliasee_instance, attrs, - *linkage, - *visibility, + linkage, + visibility, symbol_name.name, ); @@ -146,7 +142,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { fn predefine_without_aliases( &self, instance: Instance<'tcx>, - _attrs: &Cow<'_, CodegenFnAttrs>, + _attrs: &CodegenFnAttrs, linkage: Linkage, visibility: Visibility, symbol_name: &str, From 97ad6fc7ab276b59a8aa1c3d170a0f2b3bc99604 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Jul 2026 00:53:11 +0200 Subject: [PATCH 122/166] Fix typo "aliasee" --- src/mono_item.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mono_item.rs b/src/mono_item.rs index 7267580a97f4b..f7626dc90bed4 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -78,7 +78,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { fn add_static_aliases( &self, aliases: &[(DefId, Linkage, Visibility)], - aliasee: &str, + aliased: &str, create_global: &F, ) where F: Fn(&CodegenCx<'gcc, 'tcx>, &str, Visibility) -> LValue<'gcc>, @@ -88,7 +88,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let symbol_name = self.tcx.symbol_name(instance); let alias = create_global(self, symbol_name.name, visibility); - alias.add_attribute(VarAttribute::Alias(aliasee)); + alias.add_attribute(VarAttribute::Alias(aliased)); // Add the alias name to the set of cached items, so there is no duplicate // instance added to it during the normal `external static` codegen @@ -103,8 +103,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { #[cfg(feature = "master")] fn add_function_aliases( &self, - aliasee_instance: Instance<'tcx>, - aliasee: Function<'gcc>, + aliased_instance: Instance<'tcx>, + aliased: Function<'gcc>, attrs: &CodegenFnAttrs, aliases: &[(DefId, Linkage, Visibility)], ) { @@ -114,7 +114,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { // predefine another copy of the original instance // with a new symbol name let alias_fn_decl = self.predefine_without_aliases( - aliasee_instance, + aliased_instance, attrs, linkage, visibility, @@ -129,7 +129,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } let void_type = self.context.new_type::<()>(); - let call = self.context.new_call(None, aliasee, &args); + let call = self.context.new_call(None, aliased, &args); if alias_fn_decl.get_return_type() == void_type { block.add_eval(None, call); block.end_with_void_return(None); From 622323a1dd242dd2affb007d23606fcfc1ed20bb Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Wed, 22 Jul 2026 13:38:39 -0300 Subject: [PATCH 123/166] Lower x86-interrupt byval first argument as pointer --- src/abi.rs | 33 ++++++++++++++++--- src/attributes.rs | 26 +++++++++++++++ src/callee.rs | 2 +- src/declare.rs | 24 +++++++------- src/intrinsic/mod.rs | 2 +- src/mono_item.rs | 2 +- .../compile/x86_interrupt_first_arg_byval.rs | 16 +++++++++ tests/lang_tests.rs | 8 ++++- 8 files changed, 93 insertions(+), 20 deletions(-) create mode 100644 tests/compile/x86_interrupt_first_arg_byval.rs diff --git a/src/abi.rs b/src/abi.rs index 00e43dab0f83f..45fc5e3c4f619 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -159,7 +159,10 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { #[cfg(not(feature = "master"))] let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; - for arg in self.args.iter() { + for (source_arg_index, arg) in self.args.iter().enumerate() { + #[cfg(not(feature = "master"))] + let _ = source_arg_index; + let arg_ty = match arg.mode { PassMode::Ignore => continue, PassMode::Pair(a, b) => { @@ -185,9 +188,31 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply_attrs(ty, &cast.attrs, argument_tys.len()) } PassMode::Indirect { attrs: _, meta_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()); - arg.layout.gcc_type(cx) + let x86_interrupt_first_arg = { + #[cfg(feature = "master")] + { + source_arg_index == 0 + && matches!(self.conv, CanonAbi::Interrupt(InterruptKind::X86)) + } + #[cfg(not(feature = "master"))] + { + false + } + }; + + if x86_interrupt_first_arg { + // Rust lowers the first `x86-interrupt` argument as a byval stack slot. + // LLVM represents that as a pointer parameter with `byval`; GCC's + // interrupt attribute likewise requires a pointer-shaped first parameter. + // Do not add this parameter to `on_stack_param_indices`: that set is only + // needed when GCC represents a byval argument as a value parameter, while + // this parameter is already pointer-shaped. + cx.type_ptr_to(arg.layout.gcc_type(cx)) + } else { + // This is a "byval" argument, so we don't apply the `restrict` attribute on it. + on_stack_param_indices.insert(argument_tys.len()); + arg.layout.gcc_type(cx) + } } PassMode::Direct(attrs) => { apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()) diff --git a/src/attributes.rs b/src/attributes.rs index ce1877b308e94..95d12480efa69 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -2,6 +2,8 @@ use gccjit::FnAttribute; use gccjit::Function; #[cfg(feature = "master")] +use rustc_abi::{CanonAbi, InterruptKind}; +#[cfg(feature = "master")] use rustc_hir::attrs::InlineAttr; use rustc_hir::attrs::InstructionSetAttr; #[cfg(feature = "master")] @@ -9,6 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; #[cfg(feature = "master")] use rustc_middle::mir::TerminatorKind; use rustc_middle::ty; +use rustc_target::callconv::FnAbi; #[cfg(feature = "master")] use rustc_target::spec::Arch; @@ -82,12 +85,23 @@ fn inline_attr<'gcc, 'tcx>( } } +#[cfg(feature = "master")] +fn is_x86_interrupt<'tcx>(fn_abi: Option<&FnAbi<'tcx, ty::Ty<'tcx>>>) -> bool { + matches!( + fn_abi, + Some(fn_abi) if matches!(fn_abi.conv, CanonAbi::Interrupt(InterruptKind::X86)) + ) +} + /// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`) /// attributes. pub fn from_fn_attrs<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, #[cfg_attr(not(feature = "master"), expect(unused_variables))] func: Function<'gcc>, instance: ty::Instance<'tcx>, + #[cfg_attr(not(feature = "master"), expect(unused_variables))] fn_abi: Option< + &FnAbi<'tcx, ty::Ty<'tcx>>, + >, ) { let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def); @@ -120,6 +134,11 @@ pub fn from_fn_attrs<'gcc, 'tcx>( } } + #[cfg(feature = "master")] + let x86_interrupt = is_x86_interrupt(fn_abi); + #[cfg(not(feature = "master"))] + let x86_interrupt = false; + let mut function_features = codegen_fn_attrs .target_features .iter() @@ -135,6 +154,13 @@ pub fn from_fn_attrs<'gcc, 'tcx>( // 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); + if x86_interrupt { + // GCC does not preserve SSE, MMX, or x87 state in interrupt handlers and rejects + // them whenever those instruction sets are enabled, even if the handler does not + // emit such instructions. Restrict the function to general registers so the + // interrupt attribute works with the default x86_64 target features. + function_features.push("general-regs-only"); + } let target_features = function_features .iter() .filter_map(|feature| { diff --git a/src/callee.rs b/src/callee.rs index 00f095ed54371..d3f412180da55 100644 --- a/src/callee.rs +++ b/src/callee.rs @@ -70,7 +70,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) cx.linkage.set(FunctionType::Extern); let func = cx.declare_fn(sym, fn_abi); - attributes::from_fn_attrs(cx, func, instance); + attributes::from_fn_attrs(cx, func, instance, Some(fn_abi)); #[cfg(feature = "master")] { diff --git a/src/declare.rs b/src/declare.rs index 4174eebcf7b02..2d97c10c5f935 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; -use crate::abi::{FnAbiGcc, FnAbiGccExt}; +use crate::abi::FnAbiGccExt; use crate::context::CodegenCx; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -110,22 +110,22 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> { - let FnAbiGcc { - return_type, - arguments_type, - is_c_variadic, - on_stack_param_indices, - #[cfg(feature = "master")] - fn_attributes, - } = fn_abi.gcc_type(self); + let fn_abi_gcc = fn_abi.gcc_type(self); #[cfg(feature = "master")] let conv = fn_abi.gcc_cconv(self); #[cfg(not(feature = "master"))] let conv = None; - let func = declare_raw_fn(self, name, conv, return_type, &arguments_type, is_c_variadic); - self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices); + let func = declare_raw_fn( + self, + name, + conv, + fn_abi_gcc.return_type, + &fn_abi_gcc.arguments_type, + fn_abi_gcc.is_c_variadic, + ); + self.on_stack_function_params.borrow_mut().insert(func, fn_abi_gcc.on_stack_param_indices); #[cfg(feature = "master")] - for fn_attr in fn_attributes { + for fn_attr in fn_abi_gcc.fn_attributes { func.add_attribute(fn_attr); } func diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index c9f3b57ec5ff1..eeeda3466c674 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -588,7 +588,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.on_stack_function_params.borrow_mut().insert(func, FxHashSet::default()); - crate::attributes::from_fn_attrs(self, func, instance); + crate::attributes::from_fn_attrs(self, func, instance, None); func }; diff --git a/src/mono_item.rs b/src/mono_item.rs index f7626dc90bed4..d8b6cae7ee00e 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -151,7 +151,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.linkage.set(base::linkage_to_gcc(linkage)); let fn_decl = self.declare_fn(symbol_name, fn_abi); - attributes::from_fn_attrs(self, fn_decl, instance); + attributes::from_fn_attrs(self, fn_decl, instance, Some(fn_abi)); // If we're compiling the compiler-builtins crate, e.g., the equivalent of // compiler-rt, then we want to implicitly compile everything with hidden diff --git a/tests/compile/x86_interrupt_first_arg_byval.rs b/tests/compile/x86_interrupt_first_arg_byval.rs new file mode 100644 index 0000000000000..4b6bbd48f7ad5 --- /dev/null +++ b/tests/compile/x86_interrupt_first_arg_byval.rs @@ -0,0 +1,16 @@ +// Compiler: + +// Test that `x86-interrupt` functions whose first argument is passed by value +// emit pointer-shaped GCC parameters and compile with interrupt-safe target features. + +#![feature(abi_x86_interrupt)] +#![crate_type = "lib"] + +#[repr(C)] +pub struct Frame { + ip: u64, +} + +pub extern "x86-interrupt" fn scalar(_a: i64) {} + +pub extern "x86-interrupt" fn aggregate(_frame: Frame) {} diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index e3baf1e038ffc..f3b4ad34bc9c4 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -211,7 +211,13 @@ fn compile_tests(tempdir: PathBuf, current_dir: String) { "lang compile", "tests/compile", TestMode::Compile, - &["simd-ffi.rs", "asm_nul_byte.rs", "global_asm_nul_byte.rs", "naked_asm_nul_byte.rs"], + &[ + "simd-ffi.rs", + "asm_nul_byte.rs", + "global_asm_nul_byte.rs", + "naked_asm_nul_byte.rs", + "x86_interrupt_first_arg_byval.rs", + ], ); } From 6bc1235d4c66cc9ff2955151ad721017cb1cd474 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 22 Jul 2026 17:20:50 -0400 Subject: [PATCH 124/166] Fix flakyness of the stdarch tests in the CI --- .github/workflows/stdarch.yml | 11 +++++++++-- build_system/src/test.rs | 8 +++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 3d2ffa57dff75..17d6449c85e08 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -42,8 +42,14 @@ jobs: - name: Install more recent binutils run: | echo "deb http://archive.ubuntu.com/ubuntu plucky main universe" | sudo tee /etc/apt/sources.list.d/plucky-copies.list - sudo apt-get update + sudo apt-get update -o Acquire::Retries=3 sudo apt-get install binutils + installed="$(dpkg-query --showformat='${Version}' --show binutils)" + echo "Installed binutils: $installed" + if dpkg --compare-versions "$installed" lt "2.44"; then + echo "::error::binutils upgrade failed (got $installed, need >= 2.44); the apt fetch probably failed" + exit 1 + fi - name: Install Intel Software Development Emulator if: ${{ matrix.cargo_runner }} @@ -89,7 +95,8 @@ jobs: - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} run: | - ./y.sh test --release --stdarch-tests + # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. + ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile - name: Run stdarch tests if: ${{ matrix.cargo_runner }} diff --git a/build_system/src/test.rs b/build_system/src/test.rs index cbaf58796983c..6cc2282c8022f 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -788,7 +788,13 @@ fn test_stdarch(env: &Env, args: &TestArg) -> Result<(), String> { format!("{rustflags} -Ainternal_features").trim().to_owned(), ); env.insert("TARGET".to_string(), args.config_info.target_triple.clone()); - run_cargo_command(&[&"test", &"--manifest-path", &manifest_path], None, &env, args)?; + + let mut command: Vec<&dyn AsRef> = + vec![&"test", &"--manifest-path", &manifest_path, &"--"]; + for test_name in &args.test_args { + command.push(test_name); + } + run_cargo_command(&command, None, &env, args)?; Ok(()) } From 8a10ee5bb839dbcd519a08811787ab1c09673481 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sun, 19 Jul 2026 21:48:27 +0800 Subject: [PATCH 125/166] gcc: locate codegen-backends via host_tuple() `file_path` builds the `lib/rustlib//codegen-backends` path used to load the codegen backend. It passed `&sess.host.llvm_target`, but that is the host's LLVM target string, not its rustc target tuple. The two can differ (e.g. `arm64-apple-macosx` vs `aarch64-apple-darwin`), so the lookup can miss the directory that actually holds the backend. Use `rustc_session::config::host_tuple()` instead. --- src/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9a75aef25bc05..9e86a8b8f215d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -197,8 +197,10 @@ impl CodegenBackend for GccCodegenBackend { fn init(&self, sess: &Session) { fn file_path(sysroot_path: &Path, sess: &Session) -> PathBuf { - let rustlib_path = - rustc_target::relative_target_rustlib_path(sysroot_path, &sess.host.llvm_target); + let rustlib_path = rustc_target::relative_target_rustlib_path( + sysroot_path, + rustc_session::config::host_tuple(), + ); sysroot_path .join(rustlib_path) .join("codegen-backends") From dcf4a3d67dd092b755de9b7cde4e57bba08a1b44 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 22 Jul 2026 18:24:15 +0200 Subject: [PATCH 126/166] allocations are allowed to grow --- library/core/src/ptr/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index c758d5f4b89d6..9365e6e792f28 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -145,6 +145,13 @@ //! the allocation), `base + o` will not wrap around the address space (in //! other words, will not overflow `usize`) //! +//! Allocations typically have a fixed size that cannot change. However, allocations created by +//! directly invoking page table operations of the operating system, e.g. via `mmap`, are allowed to +//! grow by adding more pages to them at the end. Unmapping parts of an allocation (i.e., shrinking +//! it or punching holes into it) is currently not supported. Allocations created via +//! "compiler-recognized" operations, such as `std::alloc` methods or `libc::malloc`, can never +//! change their size, even if they use `mmap` under the hood. +//! //! [`null()`]: null //! //! # Provenance From ce209dc4b2683a4d3b9d36c4d627689f5d237ef6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Jul 2026 22:20:16 +0200 Subject: [PATCH 127/166] Update `gccjit` version to `3.7.0` --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index edbaacf6ecca0..292f1c43670db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd96d5f5f1752c2f6ff639d19d51f2b64c6169981606f5066808685f75f58b4" +checksum = "37885008422371f81d654ddfbf9b8ab3c5e1b0b54146bf5ff4b74ae91812e8ba" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a34e8df2602945338835eade9ef69a057203197ad32ec512a9c763b96dafab5" +checksum = "1e00d0323f55a3b71b302620571d44cd45fd05b4eb6bba6dd7f716095b8ab8cf" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 02cce3c14a26d..1cc0db7896a91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "3.6.0", features = ["dlopen"] } +gccjit = { version = "3.7.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. From 2ea159960214c188faaf0f2b14e7e966dbf6b19a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jul 2026 00:14:02 +0200 Subject: [PATCH 128/166] Update libgccjit version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index f1882be2c1007..de698d236f277 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -31396c2f72909f5973b6acab17242f4e4fece99a +b794cb99508e7eccd40fa42bb310d5781e09899b From b1a20b9e8779cc7c36e0ff2f8845ea0517f46127 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Jul 2026 15:16:36 +0200 Subject: [PATCH 129/166] Add support for `used` attribute --- src/consts.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 42ff930968501..eadca3ebcdca7 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,6 +1,6 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, VarAttribute, Visibility}; -use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; +use gccjit::{FnAttribute, ToRValue, VarAttribute, Visibility}; +use gccjit::{Function, GlobalKind, LValue, RValue, Type}; use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, @@ -169,20 +169,31 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { // FIXME(antoyo): set link section. } - if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) - || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) - { - self.add_used_global(global.to_rvalue()); + if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { + self.add_retained_global(global); + } else if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) { + self.add_used_global(global); } } } impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { - /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*. - pub fn add_used_global(&mut self, _global: RValue<'gcc>) { - // FIXME(antoyo) + /// Need to have the `SHF_GNU_RETAIN` flag, so needs to use the `retain` attribute instead of + /// `used`. This is used by `#[used(linker)]`. + pub fn add_retained_global(&mut self, global: LValue<'gcc>) { + // We need to add the `used` C attribute in any case. + self.add_used_global(global); + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Retain); + } + + /// This is used by `#[used(compiler)]` and `#[used]`. + pub fn add_used_global(&mut self, _global: LValue<'gcc>) { + #[cfg(feature = "master")] + _global.add_attribute(VarAttribute::Used); } + // No need to have the `SHF_GNU_RETAIN` flag, so `used` attribute is ok. #[cfg_attr(not(feature = "master"), expect(unused_variables))] pub fn add_used_function(&self, function: Function<'gcc>) { #[cfg(feature = "master")] From bcea6f60955e5c193195bac8dd865fe9d1ee24ed Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jul 2026 00:20:27 +0200 Subject: [PATCH 130/166] Add asm test for the `used` attribute --- tests/asm/used.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/asm/used.rs diff --git a/tests/asm/used.rs b/tests/asm/used.rs new file mode 100644 index 0000000000000..73b18323a7f50 --- /dev/null +++ b/tests/asm/used.rs @@ -0,0 +1,12 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu + +#![feature(used_with_arg)] +#![crate_type = "lib"] + +// CHECK: .section .rodata._RNvCslVCd7eQSKhE_4used1X,"a" +#[used(compiler)] +pub static X: u32 = 12; +// CHECK: .section .rodata._RNvCslVCd7eQSKhE_4used1Y,"aR" +#[used(linker)] +pub static Y: u32 = 12; From df4939b867c1eaed9ec1e0b9e2eb8f37ed639377 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jul 2026 14:08:10 +0200 Subject: [PATCH 131/166] Remove newly passing `tests/ui/linking/no-gc-encapsulation-symbols.rs` ui test --- tests/failing-ui-tests.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 512fb2b600ed3..e0970bf96d5ff 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -67,7 +67,6 @@ tests/ui/simd/simd-bitmask-notpow2.rs tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs tests/ui/numbers-arithmetic/u128-as-f32.rs tests/ui/process/nofile-limit.rs -tests/ui/linking/no-gc-encapsulation-symbols.rs tests/ui/panics/unwind-force-no-unwind-tables.rs tests/ui/attributes/fn-align-dyn.rs tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs From 8a05e19e488a63eae5ccd6b6a5ff08efdc31843f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jul 2026 14:27:40 +0200 Subject: [PATCH 132/166] Make code closer to its LLVM equivalent to make it simpler to map both --- src/consts.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index eadca3ebcdca7..807c48633ad7c 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -169,10 +169,15 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { // FIXME(antoyo): set link section. } + if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) { + // To copy the conditions from the LLVM backend... + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)); + self.add_used_global(global); + } if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { + // To copy the conditions from the LLVM backend... + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)); self.add_retained_global(global); - } else if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) { - self.add_used_global(global); } } } From dbc2c2b2e94f2181e03d8ee318e443d7c967d2d4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 24 Jul 2026 09:46:25 -0400 Subject: [PATCH 133/166] Update to nightly-2026-07-24 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index fdd85175e0340..104992b5da46b 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-07-14" +channel = "nightly-2026-07-24" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From b6fd3e80a598ac805a23edb40149faace624398d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jul 2026 15:57:47 +0200 Subject: [PATCH 134/166] Make `tests/asm/used.rs` work more easily --- tests/asm/used.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/asm/used.rs b/tests/asm/used.rs index 73b18323a7f50..deb0c69dc48fa 100644 --- a/tests/asm/used.rs +++ b/tests/asm/used.rs @@ -4,9 +4,11 @@ #![feature(used_with_arg)] #![crate_type = "lib"] -// CHECK: .section .rodata._RNvCslVCd7eQSKhE_4used1X,"a" +// CHECK: .section .rodata.X,"a" #[used(compiler)] +#[no_mangle] pub static X: u32 = 12; -// CHECK: .section .rodata._RNvCslVCd7eQSKhE_4used1Y,"aR" +// CHECK: .section .rodata.Y,"aR" #[used(linker)] +#[no_mangle] pub static Y: u32 = 12; From 4b1043347f3494759187d3ad92bee296eeec664b Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 24 Jul 2026 07:40:03 -0700 Subject: [PATCH 135/166] doc/subtree.md: fix typo ("sync" -> "synced") --- doc/subtree.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/subtree.md b/doc/subtree.md index a81b6c9c74bdd..a392eea687e86 100644 --- a/doc/subtree.md +++ b/doc/subtree.md @@ -1,7 +1,7 @@ # git subtree sync `rustc_codegen_gcc` is a subtree of the rust compiler. As such, it needs to be -sync from time to time to ensure changes that happened on their side are also +synced from time to time to ensure changes that happened on their side are also included on our side. ### How to install a forked git-subtree From d7cb2051b605cc8ff843e83535438d46ef2a02b8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jul 2026 18:04:21 +0200 Subject: [PATCH 136/166] Update doc for subtree sync --- doc/subtree.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/subtree.md b/doc/subtree.md index a81b6c9c74bdd..1a493e942f9ea 100644 --- a/doc/subtree.md +++ b/doc/subtree.md @@ -41,6 +41,8 @@ cd ../rust git pull origin master git checkout -b subtree-update_cg_gcc_YYYY-MM-DD PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master +# Don't forget to update the `gcc` submodule to the same version as the +# one in `rustc_codegen_gcc/libgccjit.version`. git push # Immediately merge the merge commit into cg_gcc to prevent merge conflicts when syncing from rust-lang/rust later. From dccb89fb6a55a53f28cf38664a698ee40f4ac580 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jul 2026 18:27:10 +0200 Subject: [PATCH 137/166] Add support for section linking --- src/consts.rs | 15 +++++++++++---- src/mono_item.rs | 6 ++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 807c48633ad7c..5ebdf91fe20b6 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -160,13 +160,20 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { } // Wasm statics with custom link sections get special treatment as they - // go into custom sections of the wasm executable. - if self.tcx.sess.target.is_like_wasm { + // go into custom sections of the wasm executable. The exception to this + // is the `.init_array` section which are treated specially by the wasm linker. + if self.tcx.sess.target.is_like_wasm + && attrs + .link_section + .map(|link_section| !link_section.as_str().starts_with(".init_array")) + .unwrap_or(true) + { if let Some(_section) = attrs.link_section { unimplemented!(); } - } else { - // FIXME(antoyo): set link section. + } else if let Some(_section) = attrs.link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(_section.as_str())); } if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) { diff --git a/src/mono_item.rs b/src/mono_item.rs index d8b6cae7ee00e..7513978b12272 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -165,8 +165,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { fn_decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); } - // FIXME(GuillaumeGomez): Add support for link section for `Function`. - // fn_decl.set_link_section(&attrs.link_section); + #[cfg(feature = "master")] + if let Some(section) = _attrs.link_section { + fn_decl.add_attribute(FnAttribute::Section(section.as_str())); + } // FIXME(antoyo): set unique comdat. // FIXME(antoyo): use inline attribute from there in linkage.set() above. From 2113ef26d936bc36baf97ffa558358b52621ebbf Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jul 2026 18:27:25 +0200 Subject: [PATCH 138/166] Remove newly passing ui test from the failing list --- tests/failing-ui-tests.txt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index e0970bf96d5ff..2b2f21904abb5 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -11,7 +11,6 @@ tests/ui/mir/mir_match_guard_let_chains_drop_order.rs tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs tests/ui/panic-runtime/abort.rs tests/ui/panic-runtime/link-to-abort.rs -tests/ui/parser/unclosed-delimiter-in-dep.rs tests/ui/consts/missing_span_in_backtrace.rs tests/ui/drop/dynamic-drop.rs tests/ui/simd/issue-17170.rs @@ -24,14 +23,10 @@ tests/ui/panic-runtime/lto-abort.rs tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs tests/ui/async-await/deep-futures-are-freeze.rs tests/ui/coroutine/resume-after-return.rs -tests/ui/simd/masked-load-store.rs tests/ui/simd/repr_packed.rs tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs tests/ui/coroutine/unwind-abort-mix.rs -tests/ui/consts/issue-miri-1910.rs tests/ui/consts/const_cmp_type_id.rs -tests/ui/consts/issue-94675.rs -tests/ui/traits/const-traits/const-drop-fail.rs tests/ui/runtime/on-broken-pipe/child-processes.rs tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs tests/ui/sanitizer/cfi/async-closures.rs @@ -47,7 +42,6 @@ tests/ui/sanitizer/cfi/virtual-auto.rs tests/ui/sanitizer/cfi/sized-associated-ty.rs tests/ui/sanitizer/cfi/can-reveal-opaques.rs tests/ui/sanitizer/kcfi-mangling.rs -tests/ui/delegation/fn-header.rs tests/ui/consts/const-eval/parse_ints.rs tests/ui/simd/intrinsic/generic-as.rs tests/ui/runtime/rt-explody-panic-payloads.rs @@ -76,14 +70,10 @@ tests/ui/sanitizer/kcfi/fn-trait-objects.rs tests/ui/statics/const_generics.rs tests/ui/test-attrs/test-panic-while-printing.rs tests/ui/thir-print/offset_of.rs -tests/ui/iterators/rangefrom-overflow-debug.rs -tests/ui/iterators/rangefrom-overflow-overflow-checks.rs tests/ui/iterators/iter-filter-count-debug-check.rs tests/ui/eii/default/call_impl.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs -tests/ui/traits/inheritance/self-in-supertype.rs -tests/ui/fmt/fmt_debug/shallow.rs tests/ui/eii/static/cross_crate_decl.rs tests/ui/eii/static/cross_crate_def.rs tests/ui/eii/static/same_address.rs From 749dbe68681c704dd9ba1f47035f867fc715770d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jul 2026 18:49:28 +0200 Subject: [PATCH 139/166] If `feature = "master"` is enabled, we use `add_attribute(VarAttribute::Section())` instead of `set_link_section` --- src/declare.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/declare.rs b/src/declare.rs index 2d97c10c5f935..9bf57fbf75bc0 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -1,5 +1,5 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, ToRValue}; +use gccjit::{FnAttribute, ToRValue, VarAttribute}; use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type}; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; use rustc_middle::ty::Ty; @@ -24,6 +24,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(link_section.as_str())); + #[cfg(not(feature = "master"))] global.set_link_section(link_section.as_str()); } global @@ -73,6 +76,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(link_section.as_str())); + #[cfg(not(feature = "master"))] global.set_link_section(link_section.as_str()); } let global_address = global.get_address(None); From 4e6d5285a01bc0c336af390674ff9e8abd9e25b1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 Jul 2026 16:39:03 +0200 Subject: [PATCH 140/166] Simplify parsing of `Command` in `build_system` --- build_system/src/main.rs | 82 +++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 150239cbbb421..33c081ff444e0 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -33,21 +33,21 @@ rustc_codegen_gcc build system Usage: build_system [command] [options] Options: - --help : Displays this help message. + --help : Displays this help message. Commands: - cargo : Executes a cargo command. - rustc : Compiles the program using the GCC compiler. - clean : Cleans the build directory, removing all compiled files and artifacts. - prepare : Prepares the environment for building, including fetching dependencies and setting up configurations. - build : Compiles the project. - test : Runs tests for the project. - info : Displays information about the build environment and project configuration. - clone-gcc : Clones the GCC compiler from a specified source. - fmt : Runs rustfmt - fuzz : Fuzzes `cg_gcc` using rustlantis - abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM - check-todo : Checks todo in the project" + cargo : Executes a cargo command. + rustc : Compiles the program using the GCC compiler. + clean : Cleans the build directory, removing all compiled files and artifacts. + prepare : Prepares the environment for building, including fetching dependencies and setting up configurations. + build : Compiles the project. + test : Runs tests for the project. + info : Displays information about the build environment and project configuration. + clone-gcc : Clones the GCC compiler from a specified source. + fmt : Runs rustfmt + fuzz : Fuzzes `cg_gcc` using rustlantis + abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM + check-todo : Checks todo in the project" ); } @@ -66,6 +66,35 @@ pub enum Command { CheckTodo, } +impl<'a> From> for Command { + fn from(arg: Option<&'a str>) -> Self { + match arg { + Some("cargo") => Self::Cargo, + Some("rustc") => Self::Rustc, + Some("clean") => Self::Clean, + Some("prepare") => Self::Prepare, + Some("build") => Self::Build, + Some("test") => Self::Test, + Some("info") => Self::Info, + Some("clone-gcc") => Self::CloneGcc, + Some("abi-test") => Self::AbiTest, + Some("check-todo") => Self::CheckTodo, + Some("fmt") => Self::Fmt, + Some("fuzz") => Self::Fuzz, + 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 => { + usage(); + process::exit(0); + } + } + } +} + fn main() { if env::var("RUST_BACKTRACE").is_err() { unsafe { @@ -73,32 +102,7 @@ fn main() { } } - let command = match env::args().nth(1).as_deref() { - Some("cargo") => Command::Cargo, - Some("rustc") => Command::Rustc, - Some("clean") => Command::Clean, - Some("prepare") => Command::Prepare, - Some("build") => Command::Build, - Some("test") => Command::Test, - Some("info") => Command::Info, - Some("clone-gcc") => Command::CloneGcc, - Some("abi-test") => Command::AbiTest, - Some("check-todo") => Command::CheckTodo, - Some("fmt") => Command::Fmt, - Some("fuzz") => Command::Fuzz, - 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 => { - usage(); - process::exit(0); - } - }; - - if let Err(e) = match command { + if let Err(e) = match Command::from(env::args().nth(1).as_deref()) { Command::Cargo => rust_tools::run_cargo(), Command::Rustc => rust_tools::run_rustc(), Command::Clean => clean::run(), From 82081ab75a1fdc04fcbc2774f2d8fe085cdccfe9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 Jul 2026 16:46:50 +0200 Subject: [PATCH 141/166] Tie `Command` variant declaration and CLI parsing together --- build_system/src/main.rs | 106 ++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 33c081ff444e0..b4cfbbd6ce195 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -25,9 +25,32 @@ macro_rules! arg_error { }}; } -fn usage() { - println!( - "\ +macro_rules! commands_decl { + ($($variant:ident: $doc_name:literal => $doc:literal ,)+) => { + enum Command { + $($variant),+ + } + + impl<'a> From> for Command { + fn from(arg: Option<&'a str>) -> Self { + match arg { + $(Some($doc_name) => Self::$variant,)+ + 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 => { + usage(); + process::exit(0); + } + } + } + } + + fn usage() { + println!("\ rustc_codegen_gcc build system Usage: build_system [command] [options] @@ -35,66 +58,35 @@ Usage: build_system [command] [options] Options: --help : Displays this help message. -Commands: - cargo : Executes a cargo command. - rustc : Compiles the program using the GCC compiler. - clean : Cleans the build directory, removing all compiled files and artifacts. - prepare : Prepares the environment for building, including fetching dependencies and setting up configurations. - build : Compiles the project. - test : Runs tests for the project. - info : Displays information about the build environment and project configuration. - clone-gcc : Clones the GCC compiler from a specified source. - fmt : Runs rustfmt - fuzz : Fuzzes `cg_gcc` using rustlantis - abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM - check-todo : Checks todo in the project" - ); -} +Commands:", + ); + let mut commands = vec![$(($doc_name, $doc),)+]; + let longest = commands.iter().map(|(name, _)| name.len()).max().unwrap(); -pub enum Command { - Cargo, - Clean, - CloneGcc, - Prepare, - Build, - Rustc, - Test, - Info, - Fmt, - Fuzz, - AbiTest, - CheckTodo, -} - -impl<'a> From> for Command { - fn from(arg: Option<&'a str>) -> Self { - match arg { - Some("cargo") => Self::Cargo, - Some("rustc") => Self::Rustc, - Some("clean") => Self::Clean, - Some("prepare") => Self::Prepare, - Some("build") => Self::Build, - Some("test") => Self::Test, - Some("info") => Self::Info, - Some("clone-gcc") => Self::CloneGcc, - Some("abi-test") => Self::AbiTest, - Some("check-todo") => Self::CheckTodo, - Some("fmt") => Self::Fmt, - Some("fuzz") => Self::Fuzz, - 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 => { - usage(); - process::exit(0); + commands.sort_unstable_by(|a, b| a.0.cmp(b.0)); + for (name, doc) in commands { + let spacing = std::iter::repeat(' ').take(longest - name.len() + 1).collect::(); + eprintln!(" {name}{spacing}: {doc}."); } } } } +commands_decl! { + Cargo: "cargo" => "Executes a cargo command", + Clean: "clean" => "Cleans the build directory, removing all compiled files and artifacts", + CloneGcc: "clone-gcc" => "Clones the GCC compiler from a specified source", + Prepare: "prepare" => "Prepares the environment for building, including fetching dependencies and setting up configurations", + Build: "build" => "Compiles the project", + Rustc: "rustc" => "Compiles the program using the GCC compiler", + Test: "test" => "Runs tests for the project", + Info: "info" => "Displays information about the build environment and project configuration", + Fmt: "fmt" => "Runs rustfmt", + Fuzz: "fuzz" => "Fuzzes `cg_gcc` using `rustlantis`", + AbiTest: "abi-test" => "Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM", + CheckTodo: "check-todo" => "Checks todo in the project", +} + fn main() { if env::var("RUST_BACKTRACE").is_err() { unsafe { From 7a90d915581bceba12fa67fcd56a9f66e7a34e76 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 26 Jul 2026 01:14:43 +0200 Subject: [PATCH 142/166] Automatically install `rustfmt` if not installed when running `y.sh fmt` command --- build_system/src/fmt.rs | 28 ++++++++++++++++++++++++++-- build_system/src/utils.rs | 29 +++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/build_system/src/fmt.rs b/build_system/src/fmt.rs index bf1c4676d0bc3..2ce05e408a2e8 100644 --- a/build_system/src/fmt.rs +++ b/build_system/src/fmt.rs @@ -1,7 +1,9 @@ use std::ffi::OsStr; use std::path::Path; -use crate::utils::{run_command_with_output, walk_dir}; +use crate::utils::{ + check_exit_status, run_command_with_output, run_command_with_output_and_get_it, walk_dir, +}; fn show_usage() { println!( @@ -31,7 +33,29 @@ pub fn run() -> Result<(), String> { let cmd: &[&dyn AsRef] = if check { &[&"cargo", &"fmt", &"--check"] } else { &[&"cargo", &"fmt"] }; - run_command_with_output(cmd, Some(Path::new(".")))?; + let (exit_status, stderr) = run_command_with_output_and_get_it(cmd, Some(Path::new(".")))?; + if !exit_status.success() { + let mut iter = stderr.split('\n'); + if let Some(line) = iter.next() + && line.contains("is not installed for the toolchain") + && let Some(line) = iter.next() + && line.contains("run `rustup component add") + && let Some(cmd) = line.split('`').nth(1) + { + println!("`rustfmt` is not installed for this toolchain, installing it..."); + // A weird round-about way to get a `&&str` so I can get a `&dyn AsRef` but + // as long as it works... + let cmd = cmd.split(' ').collect::>(); + let cmd = cmd.iter().map(|s: &&str| s as &dyn AsRef).collect::>(); + run_command_with_output(cmd.as_slice(), Some(Path::new(".")))?; + } else { + // If the component is installed, then it's something else. In this case we fail like we + // should have and let the user handles the error. + check_exit_status(cmd, Some(Path::new(".")), exit_status, None, true)?; + } + // We retry the command... + run_command_with_output(cmd, Some(Path::new(".")))?; + } run_command_with_output(cmd, Some(Path::new("build_system")))?; run_command_with_output(cmd, Some(Path::new("build_system/asm-tester")))?; diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 6939d93099634..67e6750370506 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -2,10 +2,11 @@ use std::collections::HashMap; use std::ffi::OsStr; use std::fmt::Debug; use std::fs; +use std::io::{BufReader, Read}; #[cfg(unix)] use std::os::unix::process::ExitStatusExt; use std::path::{Path, PathBuf}; -use std::process::{Command, ExitStatus, Output}; +use std::process::{Command, ExitStatus, Output, Stdio}; fn exec_command( input: &[&dyn AsRef], @@ -47,7 +48,7 @@ pub(crate) fn get_command_inner( command } -fn check_exit_status( +pub(crate) fn check_exit_status( input: &[&dyn AsRef], cwd: Option<&Path>, exit_status: ExitStatus, @@ -115,6 +116,30 @@ pub fn run_command_with_output( check_exit_status(input, cwd, exit_status, None, true) } +pub fn run_command_with_output_and_get_it( + input: &[&dyn AsRef], + cwd: Option<&Path>, +) -> Result<(ExitStatus, String), String> { + let mut child = get_command_inner(input, cwd, None) + .stderr(Stdio::piped()) + .spawn() + .map_err(|e| command_error(input, &cwd, e))?; + + let stderr = child.stderr.take().expect("Failed to capture stderr"); + let mut captured = String::new(); + BufReader::new(stderr).read_to_string(&mut captured).expect("failed to read stderr"); + + let status = child.wait().map_err(|e| command_error(input, &cwd, e))?; + #[cfg(unix)] + { + if let Some(signal) = status.signal() { + // In case the signal didn't kill the current process. + return Err(command_error(input, &cwd, format!("Process received signal {signal}"))); + } + } + Ok((status, captured)) +} + pub fn run_command_with_output_and_env( input: &[&dyn AsRef], cwd: Option<&Path>, From 550d70a8573fe3a3cc30b2a3f761d543112733d6 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sun, 26 Jul 2026 12:50:18 +0800 Subject: [PATCH 143/166] asm: seed the in_value for inout When performing an "inout" operation, the "in" value isn't assigned. This results in incorrect asm being generated. Signed-off-by: Sean Cross --- src/asm.rs | 4 +++- tests/run/asm.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/asm.rs b/src/asm.rs index 5f906dc1c349f..2d14fb0c62995 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -291,7 +291,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { out_place, }); - if !readwrite { + if readwrite { + self.llbb().add_assignment(None, tmp_var, in_value.immediate()); + } else { let out_gcc_idx = outputs.len() - 1; let constraint = Cow::Owned(out_gcc_idx.to_string()); diff --git a/tests/run/asm.rs b/tests/run/asm.rs index adbf8465b171e..42141c671b596 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -252,6 +252,22 @@ fn asm() { ); } + // Make sure the input value from inout is assigned to the input value + unsafe { + // Use a very distinctive value unlikely to live in any register. + let input: u64 = 0x1234567890ABCDEF; + let mut output: u64; + + asm!( + "push {1}", + "pop {0}", + out(reg) output, + inout(reg) input => _, + ); + + assert_eq!(output, 0x1234567890ABCDEF); + } + asm_goto_test(0); } From f5dc6be964d75a23a2e81489e20cd0d4b1df483a Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Sun, 26 Jul 2026 12:12:20 +0800 Subject: [PATCH 144/166] int: implement signed comparison for unsigned integers Implement signed comparison for unsigned integers, which is very similar to unsigned integers but uses `to_signed()` rather than `to_unsigned()`. This fixes a case where niche optimization causes the discriminant to sometimes compare signed and unsigned values. Signed-off-by: Sean Cross --- src/int.rs | 26 ++++++++++++++++++++------ tests/run/int.rs | 25 +++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/int.rs b/src/int.rs index 13a867ab32366..0c9a755694577 100644 --- a/src/int.rs +++ b/src/int.rs @@ -462,9 +462,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { lhs_high = self.context.new_cast(self.location, lhs_high, unsigned_type); rhs_high = self.context.new_cast(self.location, rhs_high, unsigned_type); } - // FIXME(antoyo): we probably need to handle signed comparison for unsigned - // integers. - _ => (), + IntPredicate::IntSGT + | IntPredicate::IntSGE + | IntPredicate::IntSLT + | IntPredicate::IntSLE => { + let signed_type = native_int_type.to_signed(self.cx); + lhs_high = self.context.new_cast(self.location, lhs_high, signed_type); + rhs_high = self.context.new_cast(self.location, rhs_high, signed_type); + } + IntPredicate::IntEQ | IntPredicate::IntNE => (), } let condition = self.context.new_comparison( @@ -602,9 +608,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { rhs = self.context.new_cast(self.location, rhs, unsigned_type); } } - // FIXME(antoyo): we probably need to handle signed comparison for unsigned - // integers. - _ => (), + IntPredicate::IntSGT + | IntPredicate::IntSGE + | IntPredicate::IntSLT + | IntPredicate::IntSLE => { + if !a_type.is_vector() { + let signed_type = a_type.to_signed(self.cx); + lhs = self.context.new_cast(self.location, lhs, signed_type); + rhs = self.context.new_cast(self.location, rhs, signed_type); + } + } + IntPredicate::IntEQ | IntPredicate::IntNE => (), } self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs) } diff --git a/tests/run/int.rs b/tests/run/int.rs index 78675acb5447b..ef825b4d80185 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -319,4 +319,29 @@ fn main() { const VAL5: T = 73236519889708027473620326106273939584_i128; check_ops128!(); } + + { + #[allow(dead_code)] + #[repr(u8)] + enum Inner { + L0 = 0, + H255 = 255, + } + #[allow(dead_code)] + enum O { + A(Inner), + B, + C, + } + + #[inline(never)] + fn which(o: &O) -> &'static str { + match o { + O::A(_) => "a", + O::B => "b", + O::C => "c", + } + } + assert_eq!(which(black_box(&O::A(Inner::H255))), "a"); + } } From f0b02246ede49da79be51b1fbdc1ba361ae8b752 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 26 Jul 2026 22:39:05 +0200 Subject: [PATCH 145/166] Create a new util function `run_tool_and_install_it_if_not_present` --- build_system/src/fmt.rs | 28 ++-------------------------- build_system/src/utils.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/build_system/src/fmt.rs b/build_system/src/fmt.rs index 2ce05e408a2e8..dc1ca1d3e82ae 100644 --- a/build_system/src/fmt.rs +++ b/build_system/src/fmt.rs @@ -1,9 +1,7 @@ use std::ffi::OsStr; use std::path::Path; -use crate::utils::{ - check_exit_status, run_command_with_output, run_command_with_output_and_get_it, walk_dir, -}; +use crate::utils::{run_command_with_output, run_tool_and_install_it_if_not_present, walk_dir}; fn show_usage() { println!( @@ -33,29 +31,7 @@ pub fn run() -> Result<(), String> { let cmd: &[&dyn AsRef] = if check { &[&"cargo", &"fmt", &"--check"] } else { &[&"cargo", &"fmt"] }; - let (exit_status, stderr) = run_command_with_output_and_get_it(cmd, Some(Path::new(".")))?; - if !exit_status.success() { - let mut iter = stderr.split('\n'); - if let Some(line) = iter.next() - && line.contains("is not installed for the toolchain") - && let Some(line) = iter.next() - && line.contains("run `rustup component add") - && let Some(cmd) = line.split('`').nth(1) - { - println!("`rustfmt` is not installed for this toolchain, installing it..."); - // A weird round-about way to get a `&&str` so I can get a `&dyn AsRef` but - // as long as it works... - let cmd = cmd.split(' ').collect::>(); - let cmd = cmd.iter().map(|s: &&str| s as &dyn AsRef).collect::>(); - run_command_with_output(cmd.as_slice(), Some(Path::new(".")))?; - } else { - // If the component is installed, then it's something else. In this case we fail like we - // should have and let the user handles the error. - check_exit_status(cmd, Some(Path::new(".")), exit_status, None, true)?; - } - // We retry the command... - run_command_with_output(cmd, Some(Path::new(".")))?; - } + run_tool_and_install_it_if_not_present(cmd)?; run_command_with_output(cmd, Some(Path::new("build_system")))?; run_command_with_output(cmd, Some(Path::new("build_system/asm-tester")))?; diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 67e6750370506..4c67156a85fb2 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -443,6 +443,34 @@ pub fn get_sysroot_dir() -> PathBuf { Path::new(crate::BUILD_DIR).join("build_sysroot") } +pub fn run_tool_and_install_it_if_not_present(cmd: &[&dyn AsRef]) -> Result<(), String> { + let (exit_status, stderr) = run_command_with_output_and_get_it(cmd, Some(Path::new(".")))?; + if exit_status.success() { + return Ok(()); + } + let mut iter = stderr.split('\n'); + if let Some(line) = iter.next() + && line.contains("is not installed for the toolchain") + && let Some(line) = iter.next() + && line.contains("run `rustup component add") + && let Some(cmd) = line.split('`').nth(1) + && let Some(tool_name) = cmd.rsplit(' ').next() + { + println!("`{tool_name}` is not installed for this toolchain, installing it..."); + // A weird round-about way to get a `&&str` so I can get a `&dyn AsRef` but + // as long as it works... + let cmd = cmd.split(' ').collect::>(); + let cmd = cmd.iter().map(|s: &&str| s as &dyn AsRef).collect::>(); + run_command_with_output(cmd.as_slice(), Some(Path::new(".")))?; + } else { + // If the component is installed, then it's something else. In this case we fail like we + // should have and let the user handles the error. + return check_exit_status(cmd, Some(Path::new(".")), exit_status, None, true); + } + // We retry the command... + run_command_with_output(cmd, Some(Path::new("."))) +} + #[cfg(test)] mod tests { use super::*; From a1f0a6c9ee45ec85bae96145f9826c4c072c6869 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 26 Jul 2026 22:53:21 +0200 Subject: [PATCH 146/166] Add new `y.sh clippy` command --- build_system/src/clippy.rs | 62 ++++++++++++++++++++++++++++++++++++++ build_system/src/main.rs | 3 ++ 2 files changed, 65 insertions(+) create mode 100644 build_system/src/clippy.rs diff --git a/build_system/src/clippy.rs b/build_system/src/clippy.rs new file mode 100644 index 0000000000000..813d4b9141e1c --- /dev/null +++ b/build_system/src/clippy.rs @@ -0,0 +1,62 @@ +use std::path::Path; + +use crate::utils::{run_command_with_output, run_tool_and_install_it_if_not_present}; + +fn show_usage() { + println!( + r#" +`clippy` command help: + + --help : Show this help"# + ); +} + +pub fn run() -> Result<(), String> { + // We skip binary name and the `info` command. + let args = std::env::args().skip(2); + #[allow(clippy::never_loop)] + for arg in args { + match arg.as_str() { + "--help" => { + show_usage(); + return Ok(()); + } + _ => return Err(format!("Unknown option {arg}")), + } + } + + run_tool_and_install_it_if_not_present(&[ + &"cargo", + &"clippy", + &"--all-targets", + &"--", + &"-D", + &"warnings", + ])?; + run_command_with_output( + &[ + &"cargo", + &"clippy", + &"--all-targets", + &"--no-default-features", + &"--", + &"-D", + &"warnings", + ], + Some(Path::new(".")), + )?; + run_command_with_output( + &[ + &"cargo", + &"clippy", + &"--all-targets", + &"--manifest-path", + &"build_system/Cargo.toml", + &"--", + &"-D", + &"warnings", + ], + Some(Path::new(".")), + )?; + Ok(()) +} diff --git a/build_system/src/main.rs b/build_system/src/main.rs index b4cfbbd6ce195..83f07a758d659 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -3,6 +3,7 @@ use std::{env, process}; mod abi_test; mod build; mod clean; +mod clippy; mod clone_gcc; mod config; mod fmt; @@ -75,6 +76,7 @@ Commands:", commands_decl! { Cargo: "cargo" => "Executes a cargo command", Clean: "clean" => "Cleans the build directory, removing all compiled files and artifacts", + Clippy: "clippy" => "Runs clippy", CloneGcc: "clone-gcc" => "Clones the GCC compiler from a specified source", Prepare: "prepare" => "Prepares the environment for building, including fetching dependencies and setting up configurations", Build: "build" => "Compiles the project", @@ -106,6 +108,7 @@ fn main() { Command::Fmt => fmt::run(), Command::Fuzz => fuzz::run(), Command::AbiTest => abi_test::run(), + Command::Clippy => clippy::run(), Command::CheckTodo => todo::run(), } { eprintln!("Command failed to run: {e}"); From 6cb6c64c1ec3d8a55832f42ef01db76a86d13eeb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 26 Jul 2026 22:56:18 +0200 Subject: [PATCH 147/166] Simplify CI workflows by removing installation of rustfmt/clippy and running clippy through `y.sh` --- .github/workflows/ci.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4463a6bd53c38..b76c79fd10870 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,9 +53,6 @@ jobs: # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. run: sudo apt-get install ninja-build ripgrep llvm-14-tools llvm - - name: Install rustfmt & clippy - run: rustup component add rustfmt clippy - - name: Download artifact run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/${{ matrix.libgccjit_version.gcc }} @@ -92,11 +89,8 @@ jobs: - name: Check todo run: ./y.sh check-todo - - name: clippy - run: | - cargo clippy --all-targets -- -D warnings - cargo clippy --all-targets --no-default-features -- -D warnings - cargo clippy --manifest-path build_system/Cargo.toml --all-targets -- -D warnings + - name: Check lints + run: ./y.sh clippy - name: Build run: | From 922cec75eb19bdc3c58945254d175030b87e8259 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 26 Jul 2026 22:56:36 +0200 Subject: [PATCH 148/166] Update contribution docs to mention `y.sh` commands for clippy and fmt --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8f81ecca445a8..c5c2a783b1ee7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -112,7 +112,7 @@ Full list of debugging options can be found in the [README](Readme.md#env-vars). ### Code Style Guidelines - Follow Rust standard coding conventions -- Ensure your code passes `rustfmt` and `clippy` +- Ensure your code passes `rustfmt` and `clippy` (you can run them with `y.sh fmt` and `y.sh clippy`) - Add comments explaining complex logic, especially in GCC interface code ## Additional Resources From 56f6073ea2b5d2c4d3fa9ccf623b2405ee88a9fb Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 9 Jan 2023 16:33:34 +0000 Subject: [PATCH 149/166] Allow only implementing `Read::read_buf` --- library/alloc/src/io/read.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/io/read.rs b/library/alloc/src/io/read.rs index c0123c860b453..80b9838df1a72 100644 --- a/library/alloc/src/io/read.rs +++ b/library/alloc/src/io/read.rs @@ -84,6 +84,7 @@ use crate::vec::Vec; #[stable(feature = "rust1", since = "1.0.0")] #[doc(notable_trait)] #[cfg_attr(not(test), rustc_diagnostic_item = "IoRead")] +#[rustc_must_implement_one_of(read, read_buf)] pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. @@ -164,7 +165,10 @@ pub trait Read { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn read(&mut self, buf: &mut [u8]) -> Result; + fn read(&mut self, buf: &mut [u8]) -> Result { + let mut buf = BorrowedBuf::from(buf); + self.read_buf(buf.unfilled()).map(|()| buf.len()) + } /// Like `read`, except that it reads into a slice of buffers. /// From 39429fd245eb2cb2aad95ac867cae656709079f4 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 28 Jul 2026 15:02:38 -0700 Subject: [PATCH 150/166] Fix links to `std::io::Read::read` --- library/core/src/io/util.rs | 2 +- tests/rustdoc-html/jump-to-def/non-local-method.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/io/util.rs b/library/core/src/io/util.rs index b022d876eb8f5..07173f13eb08b 100644 --- a/library/core/src/io/util.rs +++ b/library/core/src/io/util.rs @@ -130,7 +130,7 @@ impl Seek for Empty { /// [`Ok(0)`]: Ok /// /// [`write`]: crate::io::Write::write -/// [`read`]: ../../std/io/trait.Read.html#tymethod.read +/// [`read`]: ../../std/io/trait.Read.html#method.read /// /// # Examples /// diff --git a/tests/rustdoc-html/jump-to-def/non-local-method.rs b/tests/rustdoc-html/jump-to-def/non-local-method.rs index e785ab8d204f9..db85d31bf656c 100644 --- a/tests/rustdoc-html/jump-to-def/non-local-method.rs +++ b/tests/rustdoc-html/jump-to-def/non-local-method.rs @@ -16,7 +16,7 @@ use std::cmp::Ordering; use std::marker::PhantomData; pub fn bar2(readable: T) { - //@ has - '//a[@href="{{channel}}/alloc/io/read/trait.Read.html#tymethod.read"]' 'read' + //@ has - '//a[@href="{{channel}}/alloc/io/read/trait.Read.html#method.read"]' 'read' let _ = readable.read(&mut []); } From e9adb63dafeac5e878c7a0af6a26812e8e20c96f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 Jul 2026 17:39:49 +0200 Subject: [PATCH 151/166] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index de698d236f277..37af6404836df 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -b794cb99508e7eccd40fa42bb310d5781e09899b +f4e8afdf96ef77e2cb2cb07db370379b7f5c4f6f From cd9781b7156fbd971dab3fe13afabf1552239d88 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 Jul 2026 17:47:32 +0200 Subject: [PATCH 152/166] Update `gccjit` version to `4.0.0` --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 292f1c43670db..060509e51a6f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.7.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37885008422371f81d654ddfbf9b8ab3c5e1b0b54146bf5ff4b74ae91812e8ba" +checksum = "be5dafc4e649cb4a363e95a5960ef50b0c6f1b8e136ff8eb2e928b40353b5d8b" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.7.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e00d0323f55a3b71b302620571d44cd45fd05b4eb6bba6dd7f716095b8ab8cf" +checksum = "ab6a00a243aba2a45442bfd72b28d871137d4dac094f13de7f48cf9705112ffe" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 1cc0db7896a91..63a20d46b9d2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "3.7.0", features = ["dlopen"] } +gccjit = { version = "4.0.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. From d3f4209d8c31ca453eef0e114bc6eb03763042ae Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 Jul 2026 17:47:40 +0200 Subject: [PATCH 153/166] Update code to new `gccjit` version --- src/intrinsic/llvm.rs | 10 ++++++---- src/type_.rs | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index bdd5a71533ae9..6ad19d5af095e 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1,5 +1,7 @@ use std::borrow::Cow; +#[cfg(feature = "master")] +use gccjit::TypeAttribute; use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type}; use rustc_codegen_ssa::traits::BuilderMethods; @@ -23,7 +25,7 @@ fn encode_key_128_type<'a, 'gcc, 'tcx>( &[field1, field2, field3, field4, field5, field6, field7], ); #[cfg(feature = "master")] - encode_type.as_type().set_packed(); + encode_type.as_type().add_attribute(TypeAttribute::Packed); (encode_type.as_type(), field1, field2) } @@ -45,7 +47,7 @@ fn encode_key_256_type<'a, 'gcc, 'tcx>( &[field1, field2, field3, field4, field5, field6, field7, field8], ); #[cfg(feature = "master")] - encode_type.as_type().set_packed(); + encode_type.as_type().add_attribute(TypeAttribute::Packed); (encode_type.as_type(), field1, field2) } @@ -58,7 +60,7 @@ fn aes_output_type<'a, 'gcc, 'tcx>( let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]); let typ = aes_output_type.as_type(); #[cfg(feature = "master")] - typ.set_packed(); + typ.add_attribute(TypeAttribute::Packed); (typ, field1, field2) } @@ -81,7 +83,7 @@ fn wide_aes_output_type<'a, 'gcc, 'tcx>( &[field1, field2, field3, field4, field5, field6, field7, field8, field9], ); #[cfg(feature = "master")] - aes_output_type.as_type().set_packed(); + aes_output_type.as_type().add_attribute(TypeAttribute::Packed); (aes_output_type.as_type(), field1, field2) } diff --git a/src/type_.rs b/src/type_.rs index 514bcbe3bffd6..f008be67e39cb 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -2,7 +2,7 @@ use std::convert::TryInto; #[cfg(feature = "master")] -use gccjit::CType; +use gccjit::{CType, TypeAttribute}; use gccjit::{RValue, Struct, Type}; use rustc_abi::{AddressSpace, Align, Integer, Size}; use rustc_codegen_ssa::common::TypeKind; @@ -116,7 +116,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); if packed { #[cfg(feature = "master")] - typ.set_packed(); + typ.add_attribute(TypeAttribute::Packed); } self.struct_types.borrow_mut().insert(types, typ); typ @@ -333,7 +333,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { typ.set_fields(None, &fields); if packed { #[cfg(feature = "master")] - typ.as_type().set_packed(); + typ.as_type().add_attribute(TypeAttribute::Packed); } } From 7d0aafd7e64e9090f35d3ccd1a6f9f81d966ec0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Sat, 1 Aug 2026 16:16:32 +0200 Subject: [PATCH 154/166] Specialize `advance_by` method of `Fuse` --- library/core/src/iter/adapters/fuse.rs | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index ef956e8bdef5d..f614c31430745 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -4,6 +4,7 @@ use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::{ FusedIterator, TrustedFused, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; +use crate::num::NonZero; use crate::ops::Try; /// An iterator that yields `None` forever after the underlying iterator @@ -50,6 +51,10 @@ where FuseImpl::next(self) } + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + FuseImpl::advance_by(self, n) + } + #[inline] fn nth(&mut self, n: usize) -> Option { FuseImpl::nth(self, n) @@ -259,6 +264,7 @@ trait FuseImpl { // Functions specific to any normal Iterators fn next(&mut self) -> Option; + fn advance_by(&mut self, n: usize) -> Result<(), NonZero>; fn nth(&mut self, n: usize) -> Option; fn try_fold(&mut self, acc: Acc, fold: Fold) -> R where @@ -301,6 +307,22 @@ where and_then_or_clear(&mut self.iter, Iterator::next) } + #[inline] + default fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + let Some(iter) = &mut self.iter else { + return match NonZero::new(n) { + Some(n) => Err(n), + None => Ok(()), + }; + }; + + let res = iter.advance_by(n); + if res.is_err() { + self.iter = None; + } + res + } + #[inline] default fn nth(&mut self, n: usize) -> Option { and_then_or_clear(&mut self.iter, |iter| iter.nth(n)) @@ -381,6 +403,17 @@ where self.iter.as_mut()?.next() } + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + match &mut self.iter { + Some(iter) => iter.advance_by(n), + None => match NonZero::new(n) { + Some(n) => Err(n), + None => Ok(()), + }, + } + } + #[inline] fn nth(&mut self, n: usize) -> Option { self.iter.as_mut()?.nth(n) From f489477a895890109f44127a54045ecd1a0641b6 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 1 Aug 2026 15:26:40 -0400 Subject: [PATCH 155/166] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index 37af6404836df..7c141c20c4d3d 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -f4e8afdf96ef77e2cb2cb07db370379b7f5c4f6f +dfbee712e611693596ffec1de22177089c537491 From 1bd110c231134d401220a603dfc5a3bb0c2e9ea4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 Jul 2026 14:54:24 +0200 Subject: [PATCH 156/166] Only keep minimum required info for `cpuid.def` --- tests/cpuid.def | 43 ++++--------------------------------------- 1 file changed, 4 insertions(+), 39 deletions(-) diff --git a/tests/cpuid.def b/tests/cpuid.def index 342f7d83a63e3..05fe8e94a8282 100644 --- a/tests/cpuid.def +++ b/tests/cpuid.def @@ -1,38 +1,11 @@ -# Copyright (C) 2017-2025 Intel Corporation. -# -# This software and the related documents are Intel copyrighted materials, and your -# use of them is governed by the express license under which they were provided to -# you ("License"). Unless the License provides otherwise, you may not use, modify, -# copy, publish, distribute, disclose or transmit this software or the related -# documents without Intel's prior written permission. -# -# This software and the related documents are provided as is, with no express or -# implied warranties, other than those that are expressly stated in the License. -# -# CPUID_VERSION = 1.0 # Input => Output # EAX ECX => EAX EBX ECX EDX -00000000 ******** => 00000024 756e6547 6c65746e 49656e69 +00000000 ******** => 00000024 756e6547 6c65746e 49656e69 #Processor ID and Manufacturer 00000001 ******** => 00400f10 00100800 7ffaf3ff bfebfbff -00000002 ******** => 76035a01 00f0b6ff 00000000 00c10000 -00000003 ******** => 00000000 00000000 00000000 00000000 -00000004 00000000 => 7c004121 01c0003f 0000003f 00000000 #Deterministic Cache -00000004 00000001 => 7c004122 01c0003f 0000003f 00000000 -00000004 00000002 => 7c004143 03c0003f 000003ff 00000000 -00000004 00000003 => 7c0fc163 0280003f 0000dfff 00000004 -00000004 00000004 => 00000000 00000000 00000000 00000000 -00000005 ******** => 00000040 00000040 00000003 00042120 #MONITOR/MWAIT -00000006 ******** => 00000077 00000002 00000001 00000000 #Thermal and Power -00000007 00000000 => 00000001 f3bfbfbf bac05ffe 03d54130 #Extended Features +00000007 00000000 => 00000002 f3bfbfbf bac05ffe 03d54130 #Extended Features 00000007 00000001 => 98ee00bf 00000002 00000020 1d29cd3e -00000008 ******** => 00000000 00000000 00000000 00000000 -00000009 ******** => 00000000 00000000 00000000 00000000 #Direct Cache -0000000a ******** => 07300403 00000000 00000000 00000603 -0000000b 00000000 => 00000001 00000002 00000100 00000000 #Extended Topology -0000000b 00000001 => 00000004 00000002 00000201 00000000 -0000000c ******** => 00000000 00000000 00000000 00000000 0000000d 00000000 => 000e02e7 00002b00 00002b00 00000000 #xcr0 -0000000d 00000001 => 0000001f 00000240 00000100 00000000 +0000000d 00000001 => 0000001f 00000240 00000100 00000000 #Supervisor State 0000000d 00000002 => 00000100 00000240 00000000 00000000 0000000d 00000005 => 00000040 00000440 00000000 00000000 #zmasks 0000000d 00000006 => 00000200 00000480 00000000 00000000 #zmmh @@ -40,7 +13,6 @@ 0000000d 00000011 => 00000040 00000ac0 00000002 00000000 #tileconfig 0000000d 00000012 => 00002000 00000b00 00000006 00000000 #tiles 0000000d 00000013 => 00000080 000003c0 00000000 00000000 #APX -00000014 00000000 => 00000000 00000010 00000000 00000000 #ptwrite 00000019 ******** => 00000000 00000005 00000000 00000000 #Key Locker 0000001d 00000000 => 00000001 00000000 00000000 00000000 #AMX Tile 0000001d 00000001 => 04002000 00080040 00000010 00000000 #AMX Palette1 @@ -48,15 +20,8 @@ 0000001e 00000001 => 000001ff 00000000 00000000 00000000 00000024 00000000 => 00000001 00070002 00000000 00000000 #AVX10 00000024 00000001 => 00000000 00000000 00000004 00000000 -80000000 ******** => 80000008 00000000 00000000 00000000 +80000000 ******** => 80000004 00000000 00000000 00000000 80000001 ******** => 00000000 00000000 00000121 2c100000 80000002 ******** => 00000000 00000000 00000000 00000000 80000003 ******** => 00000000 00000000 00000000 00000000 80000004 ******** => 00000000 00000000 00000000 00000000 -80000005 ******** => 00000000 00000000 00000000 00000000 -80000006 ******** => 00000000 00000000 01006040 00000000 -80000007 ******** => 00000000 00000000 00000000 00000100 -80000008 ******** => 00003028 00000200 00000200 00000000 - -# This file was copied from intel-sde/misc/cpuid/future/cpuid.def, and modified to -# add support for `AVX512_VP2INTERSECT` From c4d12cba88de290cc5ef6b64ef0c12ab4995e640 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 22 May 2026 08:38:41 +1000 Subject: [PATCH 157/166] Setup `core::io::prelude` --- library/core/src/io/mod.rs | 2 ++ library/core/src/io/prelude.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 library/core/src/io/prelude.rs diff --git a/library/core/src/io/mod.rs b/library/core/src/io/mod.rs index 0134540ae86c8..a44d271535a9e 100644 --- a/library/core/src/io/mod.rs +++ b/library/core/src/io/mod.rs @@ -5,6 +5,8 @@ mod cursor; mod error; mod impls; mod io_slice; +#[unstable(feature = "core_io", issue = "154046")] +pub mod prelude; mod seek; mod size_hint; mod util; diff --git a/library/core/src/io/prelude.rs b/library/core/src/io/prelude.rs new file mode 100644 index 0000000000000..15dacaa3a4fa0 --- /dev/null +++ b/library/core/src/io/prelude.rs @@ -0,0 +1,12 @@ +//! The I/O Prelude. +//! +//! The purpose of this module is to alleviate imports of many common I/O traits +//! by adding a glob import to the top of I/O heavy modules: +//! +//! ``` +//! # #![allow(unused_imports)] +//! use std::io::prelude::*; +//! ``` + +#[stable(feature = "rust1", since = "1.0.0")] +pub use crate::io::{Seek, Write}; From 0791c08ecbef1e98f72fcf42792e6017d8a4684b Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 22 May 2026 08:38:58 +1000 Subject: [PATCH 158/166] Setup `alloc::io::prelude` --- library/alloc/src/io/mod.rs | 2 ++ library/alloc/src/io/prelude.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 library/alloc/src/io/prelude.rs diff --git a/library/alloc/src/io/mod.rs b/library/alloc/src/io/mod.rs index 5c043240daba8..be2d17bb5a9e6 100644 --- a/library/alloc/src/io/mod.rs +++ b/library/alloc/src/io/mod.rs @@ -6,6 +6,8 @@ mod copy; mod cursor; mod error; mod impls; +#[unstable(feature = "alloc_io", issue = "154046")] +pub mod prelude; mod read; mod util; diff --git a/library/alloc/src/io/prelude.rs b/library/alloc/src/io/prelude.rs new file mode 100644 index 0000000000000..86ae040d1d6f6 --- /dev/null +++ b/library/alloc/src/io/prelude.rs @@ -0,0 +1,12 @@ +//! The I/O Prelude. +//! +//! The purpose of this module is to alleviate imports of many common I/O traits +//! by adding a glob import to the top of I/O heavy modules: +//! +//! ``` +//! # #![allow(unused_imports)] +//! use std::io::prelude::*; +//! ``` + +#[stable(feature = "rust1", since = "1.0.0")] +pub use crate::io::{BufRead, Read, Seek, Write}; From d95198739c2623c9e0b4f26d26c54ccd70d8e0a9 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Sun, 19 Jul 2026 21:13:23 +1000 Subject: [PATCH 159/166] Expand documentation for `alloc::io` --- library/alloc/src/io/mod.rs | 175 ++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/library/alloc/src/io/mod.rs b/library/alloc/src/io/mod.rs index be2d17bb5a9e6..44d780292317f 100644 --- a/library/alloc/src/io/mod.rs +++ b/library/alloc/src/io/mod.rs @@ -1,4 +1,179 @@ //! Traits, helpers, and type definitions for core I/O functionality. +//! +//! The `io` module contains a number of common things you'll need +//! when doing input and output. The most core part of this module is +//! the [`Read`] and [`Write`] traits, which provide the +//! most general interface for reading and writing input and output. +//! +//! ## Read and Write +//! +//! Because they are traits, [`Read`] and [`Write`] are implemented by a number +//! of other types, and you can implement them for your types too. As such, +//! you'll see a few different types of I/O throughout the documentation in +//! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec`]s. For +//! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on +//! [`File`]s: +//! +//! ```no_run +//! use std::io; +//! use std::io::prelude::*; +//! use std::fs::File; +//! +//! fn main() -> io::Result<()> { +//! let mut f = File::open("foo.txt")?; +//! let mut buffer = [0; 10]; +//! +//! // read up to 10 bytes +//! let n = f.read(&mut buffer)?; +//! +//! println!("The bytes: {:?}", &buffer[..n]); +//! Ok(()) +//! } +//! ``` +//! +//! [`Read`] and [`Write`] are so important, implementors of the two traits have a +//! nickname: readers and writers. So you'll sometimes see 'a reader' instead +//! of 'a type that implements the [`Read`] trait'. Much easier! +//! +//! ## Seek and BufRead +//! +//! Beyond that, there are two important traits that are provided: [`Seek`] +//! and [`BufRead`]. Both of these build on top of a reader to control +//! how the reading happens. [`Seek`] lets you control where the next byte is +//! coming from: +//! +//! ```no_run +//! use std::io; +//! use std::io::prelude::*; +//! use std::io::SeekFrom; +//! use std::fs::File; +//! +//! fn main() -> io::Result<()> { +//! let mut f = File::open("foo.txt")?; +//! let mut buffer = [0; 10]; +//! +//! // skip to the last 10 bytes of the file +//! f.seek(SeekFrom::End(-10))?; +//! +//! // read up to 10 bytes +//! let n = f.read(&mut buffer)?; +//! +//! println!("The bytes: {:?}", &buffer[..n]); +//! Ok(()) +//! } +//! ``` +//! +//! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but +//! to show it off, we'll need to talk about buffers in general. Keep reading! +//! +//! ## BufReader and BufWriter +//! +//! Byte-based interfaces are unwieldy and can be inefficient, as we'd need to be +//! making near-constant calls to the operating system. To help with this, +//! `std::io` comes with two structs, [`BufReader`] and [`BufWriter`], which wrap +//! readers and writers. The wrapper uses a buffer, reducing the number of +//! calls and providing nicer methods for accessing exactly what you want. +//! +//! For example, [`BufReader`] works with the [`BufRead`] trait to add extra +//! methods to any reader: +//! +//! ```no_run +//! use std::io; +//! use std::io::prelude::*; +//! use std::io::BufReader; +//! use std::fs::File; +//! +//! fn main() -> io::Result<()> { +//! let f = File::open("foo.txt")?; +//! let mut reader = BufReader::new(f); +//! let mut buffer = String::new(); +//! +//! // read a line into buffer +//! reader.read_line(&mut buffer)?; +//! +//! println!("{buffer}"); +//! Ok(()) +//! } +//! ``` +//! +//! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call +//! to [`write`][`Write::write`]: +//! +//! ```no_run +//! use std::io; +//! use std::io::prelude::*; +//! use std::io::BufWriter; +//! use std::fs::File; +//! +//! fn main() -> io::Result<()> { +//! let f = File::create("foo.txt")?; +//! { +//! let mut writer = BufWriter::new(f); +//! +//! // write a byte to the buffer +//! writer.write(&[42])?; +//! +//! } // the buffer is flushed once writer goes out of scope +//! +//! Ok(()) +//! } +//! ``` +//! +//! ## Iterator types +//! +//! A large number of the structures provided by `std::io` are for various +//! ways of iterating over I/O. For example, [`Lines`] is used to split over +//! lines: +//! +//! ```no_run +//! use std::io; +//! use std::io::prelude::*; +//! use std::io::BufReader; +//! use std::fs::File; +//! +//! fn main() -> io::Result<()> { +//! let f = File::open("foo.txt")?; +//! let reader = BufReader::new(f); +//! +//! for line in reader.lines() { +//! println!("{}", line?); +//! } +//! Ok(()) +//! } +//! ``` +//! +//! ## io::Result +//! +//! Last, but certainly not least, is [`io::Result`]. This type is used +//! as the return type of many `std::io` functions that can cause an error, and +//! can be returned from your own functions as well. Many of the examples in this +//! module use the [`?` operator]: +//! +//! ```no_run +//! use std::io; +//! +//! # #[allow(dead_code)] +//! fn read_input() -> io::Result<()> { +//! let mut input = String::new(); +//! +//! io::stdin().read_line(&mut input)?; +//! +//! println!("You typed: {}", input.trim()); +//! +//! Ok(()) +//! } +//! ``` +//! +//! The return type of `read_input()`, [`io::Result<()>`][`io::Result`], is a very +//! common type for functions which don't have a 'real' return value, but do want to +//! return errors if they happen. In this case, the only purpose of this function is +//! to read the line and print it, so we use `()`. +//! +//! [`File`]: ../../std/fs/struct.File.html +//! [`TcpStream`]: ../../std/net/struct.TcpStream.html +//! [`Vec`]: crate::vec::Vec +//! [`io::Result`]: self::Result +//! [`?` operator]: ../../book/appendix-02-operators.html mod buf_read; mod buffered; From 32117cda49c21aecbe8d0430f766b53211e73094 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Thu, 21 May 2026 11:18:11 +1000 Subject: [PATCH 160/166] Move general IO tests to `alloctests` --- .../io/tests.rs => alloctests/tests/io/mod.rs} | 16 ++++++++++------ library/alloctests/tests/lib.rs | 12 ++++++++++++ library/std/src/io/mod.rs | 3 --- 3 files changed, 22 insertions(+), 9 deletions(-) rename library/{std/src/io/tests.rs => alloctests/tests/io/mod.rs} (98%) diff --git a/library/std/src/io/tests.rs b/library/alloctests/tests/io/mod.rs similarity index 98% rename from library/std/src/io/tests.rs rename to library/alloctests/tests/io/mod.rs index 3b4f871268cd1..fcc27dbbd73f7 100644 --- a/library/std/src/io/tests.rs +++ b/library/alloctests/tests/io/mod.rs @@ -1,7 +1,11 @@ -use super::{BorrowedBuf, Cursor, SeekFrom, repeat}; -use crate::cmp::{self, min}; -use crate::io::{self, BufRead, BufReader, DEFAULT_BUF_SIZE, IoSlice, Read, Seek, Write}; -use crate::mem::MaybeUninit; +use alloc::io::{ + self, BorrowedBuf, BufRead, BufReader, Cursor, DEFAULT_BUF_SIZE, IoSlice, Read, Seek, SeekFrom, + Write, repeat, +}; +use core::cmp::{self, min}; +use core::mem::MaybeUninit; + +extern crate test; #[test] fn read_until() { @@ -270,7 +274,7 @@ fn chain_bufread() { #[test] fn chain_splitted_char() { let chain = b"\xc3".chain(b"\xa9".as_slice()); - assert_eq!(crate::io::read_to_string(chain).unwrap(), "é"); + assert_eq!(alloc::io::read_to_string(chain).unwrap(), "é"); let mut chain = b"\xc3".chain(b"\xa9\n".as_slice()); let mut buf = String::new(); @@ -360,7 +364,7 @@ fn bench_read_to_end(b: &mut test::Bencher) { b.iter(|| { let mut lr = repeat(1).take(10000000); let mut vec = Vec::with_capacity(1024); - super::default_read_to_end(&mut lr, &mut vec, None) + alloc::io::default_read_to_end(&mut lr, &mut vec, None) }); } diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 7ccc8d9c6a115..e787e3af9b636 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -2,23 +2,30 @@ #![allow(internal_features)] #![deny(implicit_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] +#![feature(alloc_io)] #![feature(allocator_api)] #![feature(binary_heap_drain_sorted)] #![feature(binary_heap_into_iter_sorted)] #![feature(binary_heap_pop_if)] +#![feature(borrowed_buf_init)] +#![feature(buf_read_has_data_left)] #![feature(casefold)] #![feature(const_btree_len)] #![feature(const_cmp)] #![feature(const_heap)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] +#![feature(core_io_borrowed_buf)] +#![feature(core_io_internals)] #![feature(cow_is_borrowed)] +#![feature(cursor_split)] #![feature(deque_extend_front)] #![feature(downcast_unchecked)] #![feature(drain_keep_rest)] #![feature(exact_size_is_empty)] #![feature(hashmap_internals)] #![feature(inplace_iteration)] +#![feature(io_const_error)] #![feature(iter_advance_by)] #![feature(iter_array_chunks)] #![feature(iter_next_chunk)] @@ -28,6 +35,9 @@ #![feature(map_try_insert)] #![feature(pattern)] #![feature(ptr_cast_slice)] +#![feature(read_buf)] +#![feature(seek_io_take_position)] +#![feature(seek_stream_len)] #![feature(slice_partial_sort_unstable)] #![feature(slice_partition_dedup)] #![feature(slice_ptr_get)] @@ -48,6 +58,7 @@ #![feature(vec_deque_retain_range)] #![feature(vec_peek_mut)] #![feature(vec_try_remove)] +#![feature(write_all_vectored)] // tidy-alphabetical-end extern crate alloc; @@ -67,6 +78,7 @@ mod const_fns; mod cow_str; mod fmt; mod heap; +mod io; mod linked_list; mod misc_tests; mod num; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 203572c9067b6..d9cbe15c1d4f6 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -294,9 +294,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[cfg(test)] -mod tests; - use alloc_crate::io::OsFunctions; #[unstable(feature = "raw_os_error_ty", issue = "107792")] pub use alloc_crate::io::RawOsError; From 125be4beff372ce676908a5e7de60c6bcac7daa7 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Thu, 21 May 2026 11:31:20 +1000 Subject: [PATCH 161/166] Move `std::io::util` tests to `alloctests` --- library/alloctests/tests/io/mod.rs | 2 ++ .../io/util/tests.rs => alloctests/tests/io/util.rs} | 10 +++++----- library/alloctests/tests/lib.rs | 1 + library/std/src/io/mod.rs | 1 - library/std/src/io/util.rs | 2 -- 5 files changed, 8 insertions(+), 8 deletions(-) rename library/{std/src/io/util/tests.rs => alloctests/tests/io/util.rs} (96%) delete mode 100644 library/std/src/io/util.rs diff --git a/library/alloctests/tests/io/mod.rs b/library/alloctests/tests/io/mod.rs index fcc27dbbd73f7..77fd3723ff158 100644 --- a/library/alloctests/tests/io/mod.rs +++ b/library/alloctests/tests/io/mod.rs @@ -1,3 +1,5 @@ +mod util; + use alloc::io::{ self, BorrowedBuf, BufRead, BufReader, Cursor, DEFAULT_BUF_SIZE, IoSlice, Read, Seek, SeekFrom, Write, repeat, diff --git a/library/std/src/io/util/tests.rs b/library/alloctests/tests/io/util.rs similarity index 96% rename from library/std/src/io/util/tests.rs rename to library/alloctests/tests/io/util.rs index ed1d6891577da..52e0c3013dde7 100644 --- a/library/std/src/io/util/tests.rs +++ b/library/alloctests/tests/io/util.rs @@ -1,9 +1,9 @@ -use crate::fmt; -use crate::io::prelude::*; -use crate::io::{ - BorrowedBuf, Empty, ErrorKind, IoSlice, IoSliceMut, Repeat, SeekFrom, Sink, empty, repeat, sink, +use alloc::io::{ + BorrowedBuf, Empty, ErrorKind, IoSlice, IoSliceMut, Read, Repeat, Seek, SeekFrom, Sink, Write, + empty, repeat, sink, }; -use crate::mem::MaybeUninit; +use core::fmt; +use core::mem::MaybeUninit; struct ErrorDisplay; diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index e787e3af9b636..eb9ea287d950f 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -9,6 +9,7 @@ #![feature(binary_heap_pop_if)] #![feature(borrowed_buf_init)] #![feature(buf_read_has_data_left)] +#![feature(can_vector)] #![feature(casefold)] #![feature(const_btree_len)] #![feature(const_cmp)] diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index d9cbe15c1d4f6..385b8081a33ff 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -349,4 +349,3 @@ mod impls; mod pipe; pub mod prelude; mod stdio; -mod util; diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs deleted file mode 100644 index 87c2771955a9d..0000000000000 --- a/library/std/src/io/util.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(test)] -mod tests; From 39bf757d697baad2fae42fc2df9d59bd8e1d7a55 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Thu, 21 May 2026 11:42:23 +1000 Subject: [PATCH 162/166] Move `std::io::cursor` tests to `alloctests` --- .../src/io/cursor/tests.rs => alloctests/tests/io/cursor.rs} | 5 +++-- library/alloctests/tests/io/mod.rs | 1 + library/std/src/io/cursor.rs | 2 -- library/std/src/io/mod.rs | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) rename library/{std/src/io/cursor/tests.rs => alloctests/tests/io/cursor.rs} (99%) delete mode 100644 library/std/src/io/cursor.rs diff --git a/library/std/src/io/cursor/tests.rs b/library/alloctests/tests/io/cursor.rs similarity index 99% rename from library/std/src/io/cursor/tests.rs rename to library/alloctests/tests/io/cursor.rs index d7c203c297fe6..5e863f29af53c 100644 --- a/library/std/src/io/cursor/tests.rs +++ b/library/alloctests/tests/io/cursor.rs @@ -1,5 +1,6 @@ -use crate::io::prelude::*; -use crate::io::{Cursor, IoSlice, IoSliceMut, SeekFrom}; +use alloc::io::{Cursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; + +extern crate test; #[test] fn test_vec_writer() { diff --git a/library/alloctests/tests/io/mod.rs b/library/alloctests/tests/io/mod.rs index 77fd3723ff158..a3fbbf96653cb 100644 --- a/library/alloctests/tests/io/mod.rs +++ b/library/alloctests/tests/io/mod.rs @@ -1,3 +1,4 @@ +mod cursor; mod util; use alloc::io::{ diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs deleted file mode 100644 index 87c2771955a9d..0000000000000 --- a/library/std/src/io/cursor.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(test)] -mod tests; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 385b8081a33ff..9cb63ebe9cd72 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -343,7 +343,6 @@ pub use self::stdio::{set_output_capture, try_set_output_capture}; mod buffered; mod copy; -mod cursor; mod error; mod impls; mod pipe; From f67f57d68c00f11620ddaf7736d86e199a341583 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Thu, 21 May 2026 11:45:18 +1000 Subject: [PATCH 163/166] Move `std::io::buffered` tests to `alloctests` --- .../tests/io/buffered.rs} | 31 ++++++++++--------- library/alloctests/tests/io/mod.rs | 1 + library/std/src/io/buffered/mod.rs | 4 --- library/std/src/io/mod.rs | 1 - 4 files changed, 18 insertions(+), 19 deletions(-) rename library/{std/src/io/buffered/tests.rs => alloctests/tests/io/buffered.rs} (98%) delete mode 100644 library/std/src/io/buffered/mod.rs diff --git a/library/std/src/io/buffered/tests.rs b/library/alloctests/tests/io/buffered.rs similarity index 98% rename from library/std/src/io/buffered/tests.rs rename to library/alloctests/tests/io/buffered.rs index ff4585a60cae9..0abaa63870e15 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/alloctests/tests/io/buffered.rs @@ -1,10 +1,14 @@ -use crate::io::prelude::*; -use crate::io::{ - self, BorrowedBuf, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom, +//! Tests for buffering wrappers for I/O traits + +use alloc::io::{ + self, BorrowedBuf, BufRead, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, Read, Seek, + SeekFrom, Write, }; -use crate::mem::MaybeUninit; -use crate::sync::atomic::{AtomicUsize, Ordering}; -use crate::{panic, thread}; +use core::mem::MaybeUninit; +use core::sync::atomic::{AtomicUsize, Ordering}; +use std::{panic, thread}; + +extern crate test; /// A dummy reader intended at testing short-reads propagation. pub struct ShortReader { @@ -488,7 +492,7 @@ fn dont_panic_in_drop_on_panicked_flush() { } #[test] -#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn panic_in_write_doesnt_flush_in_drop() { static WRITES: AtomicUsize = AtomicUsize::new(0); @@ -504,12 +508,11 @@ fn panic_in_write_doesnt_flush_in_drop() { } } - thread::spawn(|| { + panic::catch_unwind(panic::AssertUnwindSafe(|| { let mut writer = BufWriter::new(PanicWriter); let _ = writer.write(b"hello world"); let _ = writer.flush(); - }) - .join() + })) .unwrap_err(); assert_eq!(WRITES.load(Ordering::SeqCst), 1); @@ -681,7 +684,7 @@ fn line_vectored() { #[test] fn line_vectored_partial_and_errors() { - use crate::collections::VecDeque; + use alloc::collections::VecDeque; enum Call { Write { inputs: Vec<&'static [u8]>, output: io::Result }, @@ -1150,7 +1153,7 @@ struct WriteRecorder { impl Write for WriteRecorder { fn write(&mut self, buf: &[u8]) -> io::Result { - use crate::str::from_utf8; + use core::str::from_utf8; self.events.push(RecordedEvent::Write(from_utf8(buf).unwrap().to_string())); Ok(buf.len()) @@ -1183,7 +1186,7 @@ fn single_formatted_write() { fn bufreader_full_initialize() { struct OneByteReader; impl Read for OneByteReader { - fn read(&mut self, buf: &mut [u8]) -> crate::io::Result { + fn read(&mut self, buf: &mut [u8]) -> alloc::io::Result { if buf.len() > 0 { buf[0] = 0; Ok(1) @@ -1206,7 +1209,7 @@ fn bufreader_full_initialize() { /// This is a regression test for https://github.com/rust-lang/rust/issues/127584. #[test] fn bufwriter_aliasing() { - use crate::io::{BufWriter, Cursor}; + use alloc::io::{BufWriter, Cursor}; let mut v = vec![0; 1024]; let c = Cursor::new(&mut v); let w = BufWriter::new(Box::new(c)); diff --git a/library/alloctests/tests/io/mod.rs b/library/alloctests/tests/io/mod.rs index a3fbbf96653cb..b0df3b51094ca 100644 --- a/library/alloctests/tests/io/mod.rs +++ b/library/alloctests/tests/io/mod.rs @@ -1,3 +1,4 @@ +mod buffered; mod cursor; mod util; diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs deleted file mode 100644 index 1d09ff7d8dc1c..0000000000000 --- a/library/std/src/io/buffered/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! Buffering wrappers for I/O traits - -#[cfg(test)] -mod tests; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 9cb63ebe9cd72..945de19424f3b 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -341,7 +341,6 @@ pub(crate) use self::stdio::{attempt_print_to_stderr, cleanup}; #[doc(no_inline, hidden)] pub use self::stdio::{set_output_capture, try_set_output_capture}; -mod buffered; mod copy; mod error; mod impls; From 29da936fe337721cdb5c320e2229339cdaa6dd7f Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Mon, 25 May 2026 13:29:57 +1000 Subject: [PATCH 164/166] Move `std::io::impls` benchmarks to `alloctests` --- library/{std/src/io/impls/tests.rs => alloctests/benches/io.rs} | 2 +- library/alloctests/benches/lib.rs | 1 + library/std/src/io/impls.rs | 2 -- library/std/src/io/mod.rs | 1 - 4 files changed, 2 insertions(+), 4 deletions(-) rename library/{std/src/io/impls/tests.rs => alloctests/benches/io.rs} (97%) delete mode 100644 library/std/src/io/impls.rs diff --git a/library/std/src/io/impls/tests.rs b/library/alloctests/benches/io.rs similarity index 97% rename from library/std/src/io/impls/tests.rs rename to library/alloctests/benches/io.rs index d1cd84a67ada5..5ee8263b8cea4 100644 --- a/library/std/src/io/impls/tests.rs +++ b/library/alloctests/benches/io.rs @@ -1,4 +1,4 @@ -use crate::io::prelude::*; +use std::io::prelude::*; #[bench] fn bench_read_slice(b: &mut test::Bencher) { diff --git a/library/alloctests/benches/lib.rs b/library/alloctests/benches/lib.rs index 4b7139d943593..974b389a765d5 100644 --- a/library/alloctests/benches/lib.rs +++ b/library/alloctests/benches/lib.rs @@ -12,6 +12,7 @@ extern crate test; mod binary_heap; mod btree; +mod io; mod linked_list; mod slice; mod str; diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs deleted file mode 100644 index 87c2771955a9d..0000000000000 --- a/library/std/src/io/impls.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(test)] -mod tests; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 945de19424f3b..ebd69e93fa98f 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -343,7 +343,6 @@ pub use self::stdio::{set_output_capture, try_set_output_capture}; mod copy; mod error; -mod impls; mod pipe; pub mod prelude; mod stdio; From 5b49a9daf874ea1779139d9bf48bec98e9bc4b62 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Sun, 2 Aug 2026 07:08:45 +1000 Subject: [PATCH 165/166] Move `std::io::copy` tests to `alloctests` --- library/alloctests/benches/io.rs | 23 +++++++++++ .../tests.rs => alloctests/tests/io/copy.rs} | 40 +++---------------- library/alloctests/tests/io/mod.rs | 1 + library/std/src/io/copy.rs | 2 - library/std/src/io/mod.rs | 1 - 5 files changed, 29 insertions(+), 38 deletions(-) rename library/{std/src/io/copy/tests.rs => alloctests/tests/io/copy.rs} (74%) delete mode 100644 library/std/src/io/copy.rs diff --git a/library/alloctests/benches/io.rs b/library/alloctests/benches/io.rs index 5ee8263b8cea4..f2e3f2cd3c998 100644 --- a/library/alloctests/benches/io.rs +++ b/library/alloctests/benches/io.rs @@ -55,3 +55,26 @@ fn bench_write_vec(b: &mut test::Bencher) { } }) } + +#[bench] +#[cfg(unix)] +#[cfg_attr(target_os = "emscripten", ignore)] // no /dev +fn bench_copy_buf_reader(b: &mut test::Bencher) { + use std::fs::{File, OpenOptions}; + + let mut file_in = File::open("/dev/zero").expect("opening /dev/zero failed"); + // use dyn to avoid specializations unrelated to readbuf + let dyn_in = &mut file_in as &mut dyn Read; + let mut reader = std::io::BufReader::with_capacity(256 * 1024, dyn_in.take(0)); + let mut writer = + OpenOptions::new().write(true).open("/dev/null").expect("opening /dev/null failed"); + + const BYTES: u64 = 1024 * 1024; + + b.bytes = BYTES; + + b.iter(|| { + reader.get_mut().set_limit(BYTES); + std::io::copy(&mut reader, &mut writer).unwrap() + }); +} diff --git a/library/std/src/io/copy/tests.rs b/library/alloctests/tests/io/copy.rs similarity index 74% rename from library/std/src/io/copy/tests.rs rename to library/alloctests/tests/io/copy.rs index 7bdba3a04416e..485deeaea80e7 100644 --- a/library/std/src/io/copy/tests.rs +++ b/library/alloctests/tests/io/copy.rs @@ -1,7 +1,6 @@ -use crate::cmp::{max, min}; -use crate::collections::VecDeque; -use crate::io; -use crate::io::*; +use alloc::collections::VecDeque; +use alloc::io::{self, *}; +use core::cmp::{max, min}; #[test] fn copy_copies() { @@ -65,7 +64,7 @@ fn copy_specializes_bufreader() { let mut buffered = BufReader::with_capacity(256 * 1024, Cursor::new(&mut source)); let mut sink = Vec::new(); - assert_eq!(crate::io::copy(&mut buffered, &mut sink).unwrap(), source.len() as u64); + assert_eq!(io::copy(&mut buffered, &mut sink).unwrap(), source.len() as u64); assert_eq!(source.as_slice(), sink.as_slice()); let buf_sz = 71 * 1024; @@ -73,7 +72,7 @@ fn copy_specializes_bufreader() { let mut buffered = BufReader::with_capacity(buf_sz, Cursor::new(&mut source)); let mut sink = WriteObserver { observed_buffer: 0 }; - assert_eq!(crate::io::copy(&mut buffered, &mut sink).unwrap(), source.len() as u64); + assert_eq!(io::copy(&mut buffered, &mut sink).unwrap(), source.len() as u64); assert_eq!( sink.observed_buffer, buf_sz, "expected a large buffer to be provided to the writer" @@ -117,32 +116,3 @@ fn copy_specializes_from_slice() { assert_eq!(60 * 1024u64, io::copy(&mut source, &mut sink).unwrap()); assert_eq!(60 * 1024, sink.observed_buffer); } - -#[cfg(unix)] -mod io_benches { - use test::Bencher; - - use crate::fs::{File, OpenOptions}; - use crate::io::BufReader; - use crate::io::prelude::*; - - #[bench] - #[cfg_attr(target_os = "emscripten", ignore)] // no /dev - fn bench_copy_buf_reader(b: &mut Bencher) { - let mut file_in = File::open("/dev/zero").expect("opening /dev/zero failed"); - // use dyn to avoid specializations unrelated to readbuf - let dyn_in = &mut file_in as &mut dyn Read; - let mut reader = BufReader::with_capacity(256 * 1024, dyn_in.take(0)); - let mut writer = - OpenOptions::new().write(true).open("/dev/null").expect("opening /dev/null failed"); - - const BYTES: u64 = 1024 * 1024; - - b.bytes = BYTES; - - b.iter(|| { - reader.get_mut().set_limit(BYTES); - crate::io::copy(&mut reader, &mut writer).unwrap() - }); - } -} diff --git a/library/alloctests/tests/io/mod.rs b/library/alloctests/tests/io/mod.rs index b0df3b51094ca..712e322d79f1c 100644 --- a/library/alloctests/tests/io/mod.rs +++ b/library/alloctests/tests/io/mod.rs @@ -1,4 +1,5 @@ mod buffered; +mod copy; mod cursor; mod util; diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs deleted file mode 100644 index 87c2771955a9d..0000000000000 --- a/library/std/src/io/copy.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(test)] -mod tests; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index ebd69e93fa98f..c0ed06d5311bc 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -341,7 +341,6 @@ pub(crate) use self::stdio::{attempt_print_to_stderr, cleanup}; #[doc(no_inline, hidden)] pub use self::stdio::{set_output_capture, try_set_output_capture}; -mod copy; mod error; mod pipe; pub mod prelude; From fe87d159dc3fe5ff908ed79b069a87e929189cd7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 2 Aug 2026 00:08:26 +0200 Subject: [PATCH 166/166] Update GCC submodule --- src/gcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gcc b/src/gcc index 6f155cc3f5a2d..dfbee712e6116 160000 --- a/src/gcc +++ b/src/gcc @@ -1 +1 @@ -Subproject commit 6f155cc3f5a2dff33afe6cc3ed6c2e0e605ae6a3 +Subproject commit dfbee712e611693596ffec1de22177089c537491