From 6a44cfa01c023597cc4d4707759d926bd649839e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 17 Jul 2026 18:30:11 -0400 Subject: [PATCH 1/8] 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 43f01fdf35e..ec2092ee92e 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 2/8] 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 fcbc09b2708..7e46389e46f 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 3/8] 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 79bbb8a72df..0e5992c7a43 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 4/8] 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 97a58cc89af..997255a9571 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 5/8] 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 4c62c35a512..e98d2aab936 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 d017855c7de000fe0e355de9178b7c57badb448b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 18 Jul 2026 19:19:11 -0400 Subject: [PATCH 6/8] 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 7e46389e46f..cbaf5879698 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 7/8] 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 67c6616b519..064527787c7 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 8b84d7176cf..13a867ab323 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 c922d5cc416..bdd5a71533a 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 56f07661a28..c9f3b57ec5f 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 8/8] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index 01a3f834658..f1882be2c10 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -6249f1b21d0c17856c6fa87def9edd0eaa968caf +31396c2f72909f5973b6acab17242f4e4fece99a