From f66cdb342b5555b44dcf589fb864b39da210cc23 Mon Sep 17 00:00:00 2001 From: nxsaken Date: Wed, 19 Nov 2025 13:19:22 +0400 Subject: [PATCH 1/7] Stabilize `unchecked_neg` and `unchecked_shifts` --- tests/fail/intrinsics/unchecked_shl.rs | 2 -- tests/fail/intrinsics/unchecked_shr.rs | 2 -- 2 files changed, 4 deletions(-) diff --git a/tests/fail/intrinsics/unchecked_shl.rs b/tests/fail/intrinsics/unchecked_shl.rs index abb345938f..e22d36c024 100644 --- a/tests/fail/intrinsics/unchecked_shl.rs +++ b/tests/fail/intrinsics/unchecked_shl.rs @@ -1,5 +1,3 @@ -#![feature(unchecked_shifts)] - fn main() { unsafe { let _n = 1i8.unchecked_shl(8); diff --git a/tests/fail/intrinsics/unchecked_shr.rs b/tests/fail/intrinsics/unchecked_shr.rs index cdc10185e4..59402be499 100644 --- a/tests/fail/intrinsics/unchecked_shr.rs +++ b/tests/fail/intrinsics/unchecked_shr.rs @@ -1,5 +1,3 @@ -#![feature(unchecked_shifts)] - fn main() { unsafe { let _n = 1i64.unchecked_shr(64); From 637b6ac4d53e88139e0992114ce962868b046bea Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:57:42 +0000 Subject: [PATCH 2/7] Use cg_llvm's target_config in miri --- src/bin/miri.rs | 36 ++++++++++++++++++- src/lib.rs | 1 - .../pass/target-cpu-implies-target-feature.rs | 12 +++++++ 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/pass/target-cpu-implies-target-feature.rs diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 9f1ff23835..f5d06c9f8c 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -10,6 +10,7 @@ // The rustc crates we need extern crate rustc_abi; +extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_hir; @@ -19,6 +20,7 @@ extern crate rustc_log; extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; +extern crate rustc_target; /// See docs in https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc/src/main.rs /// and https://github.com/rust-lang/rust/pull/146627 for why we need this. @@ -36,6 +38,7 @@ use std::num::{NonZero, NonZeroI32}; use std::ops::Range; use std::rc::Rc; use std::str::FromStr; +use std::sync::Once; use std::sync::atomic::{AtomicU32, Ordering}; use miri::{ @@ -43,12 +46,14 @@ use miri::{ ProvenanceMode, TreeBorrowsParams, ValidationMode, run_genmc_mode, }; use rustc_abi::ExternAbi; +use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::sync::{self, DynSync}; use rustc_driver::Compilation; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::{self as hir, Node}; use rustc_hir_analysis::check::check_function_signature; use rustc_interface::interface::Config; +use rustc_interface::util::DummyCodegenBackend; use rustc_log::tracing::debug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::exported_symbols::{ @@ -58,8 +63,9 @@ use rustc_middle::query::LocalCrate; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::EarlyDiagCtxt; -use rustc_session::config::{CrateType, ErrorOutputType, OptLevel}; +use rustc_session::config::{CrateType, ErrorOutputType, OptLevel, Options}; use rustc_span::def_id::DefId; +use rustc_target::spec::Target; use crate::log::setup::{deinit_loggers, init_early_loggers, init_late_loggers}; @@ -161,7 +167,31 @@ fn run_many_seeds( } } +/// Generates the codegen backend for code that Miri will interpret: we basically +/// use the dummy backend, except that we put the LLVM backend in charge of +/// target features. +fn make_miri_codegen_backend(opts: &Options, target: &Target) -> Box { + let early_dcx = EarlyDiagCtxt::new(opts.error_format); + + // Use the target_config method of the default codegen backend (eg LLVM) to ensure the + // calculated target features match said backend by respecting eg -Ctarget-cpu. + let target_config_backend = + rustc_interface::util::get_codegen_backend(&early_dcx, &opts.sysroot, None, &target); + let target_config_backend_init = Once::new(); + + Box::new(DummyCodegenBackend { + target_config_override: Some(Box::new(move |sess| { + target_config_backend_init.call_once(|| target_config_backend.init(sess)); + target_config_backend.target_config(sess) + })), + }) +} + impl rustc_driver::Callbacks for MiriCompilerCalls { + fn config(&mut self, config: &mut rustc_interface::interface::Config) { + config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend)); + } + fn after_analysis<'tcx>( &mut self, _: &rustc_interface::interface::Compiler, @@ -244,6 +274,10 @@ struct MiriBeRustCompilerCalls { impl rustc_driver::Callbacks for MiriBeRustCompilerCalls { #[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint fn config(&mut self, config: &mut Config) { + if self.target_crate { + config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend)); + } + if config.opts.prints.is_empty() && self.target_crate { #[allow(rustc::bad_opt_access)] // tcx does not exist yet { diff --git a/src/lib.rs b/src/lib.rs index 5ec2e8edd8..b30395b738 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -165,7 +165,6 @@ pub use crate::shims::unwind::{CatchUnwindData, EvalContextExt as _}; /// Also disable the MIR pass that inserts an alignment check on every pointer dereference. Miri /// does that too, and with a better error message. pub const MIRI_DEFAULT_ARGS: &[&str] = &[ - "-Zcodegen-backend=dummy", "--cfg=miri", "-Zalways-encode-mir", "-Zextra-const-ub-checks", diff --git a/tests/pass/target-cpu-implies-target-feature.rs b/tests/pass/target-cpu-implies-target-feature.rs new file mode 100644 index 0000000000..a55517c02e --- /dev/null +++ b/tests/pass/target-cpu-implies-target-feature.rs @@ -0,0 +1,12 @@ +// Test that target-cpu implies the correct target features +//@only-target: x86_64 +//@compile-flags: -C target-cpu=x86-64-v4 + +fn main() { + assert!(is_x86_feature_detected!("avx512bw")); + assert!(is_x86_feature_detected!("avx512cd")); + assert!(is_x86_feature_detected!("avx512dq")); + assert!(is_x86_feature_detected!("avx512f")); + assert!(is_x86_feature_detected!("avx512vl")); + assert!(!is_x86_feature_detected!("avx512vpopcntdq")); +} From b770d93d7a9697ad574685946f4af5b1a7e0ca3f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 27 Nov 2025 19:46:01 +0100 Subject: [PATCH 3/7] simplify and explain MiriBeRustCompilerCalls logic for crate types --- src/bin/miri.rs | 128 ++++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 63 deletions(-) diff --git a/src/bin/miri.rs b/src/bin/miri.rs index f5d06c9f8c..57b052d0df 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -274,15 +274,20 @@ struct MiriBeRustCompilerCalls { impl rustc_driver::Callbacks for MiriBeRustCompilerCalls { #[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint fn config(&mut self, config: &mut Config) { - if self.target_crate { - config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend)); + if !self.target_crate { + // For a host crate, we fully behave like rustc. + return; } + // For a target crate, we emit an rlib that Miri can later consume. + config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend)); - if config.opts.prints.is_empty() && self.target_crate { + // Avoid warnings about unsupported crate types. However, only do that we we are *not* being + // queried by cargo about the supported crate types so that cargo still receives the + // warnings it expects. + if config.opts.prints.is_empty() { #[allow(rustc::bad_opt_access)] // tcx does not exist yet { let any_crate_types = !config.opts.crate_types.is_empty(); - // Avoid warnings about unsupported crate types. config .opts .crate_types @@ -293,66 +298,63 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls { assert!(!config.opts.crate_types.is_empty()); } } - - // Queries overridden here affect the data stored in `rmeta` files of dependencies, - // which will be used later in non-`MIRI_BE_RUSTC` mode. - config.override_queries = Some(|_, local_providers| { - // We need to add #[used] symbols to exported_symbols for `lookup_link_section`. - // FIXME handle this somehow in rustc itself to avoid this hack. - local_providers.exported_non_generic_symbols = |tcx, LocalCrate| { - let reachable_set = tcx.with_stable_hashing_context(|hcx| { - tcx.reachable_set(()).to_sorted(&hcx, true) - }); - tcx.arena.alloc_from_iter( - // This is based on: - // https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L62-L63 - // https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L174 - reachable_set.into_iter().filter_map(|&local_def_id| { - // Do the same filtering that rustc does: - // https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L84-L102 - // Otherwise it may cause unexpected behaviours and ICEs - // (https://github.com/rust-lang/rust/issues/86261). - let is_reachable_non_generic = matches!( - tcx.hir_node_by_def_id(local_def_id), - Node::Item(&hir::Item { - kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn{ .. }, - .. - }) | Node::ImplItem(&hir::ImplItem { - kind: hir::ImplItemKind::Fn(..), - .. - }) - if !tcx.generics_of(local_def_id).requires_monomorphization(tcx) - ); - if !is_reachable_non_generic { - return None; - } - let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id); - if codegen_fn_attrs.contains_extern_indicator() - || codegen_fn_attrs - .flags - .contains(CodegenFnAttrFlags::USED_COMPILER) - || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) - { - Some(( - ExportedSymbol::NonGeneric(local_def_id.to_def_id()), - // Some dummy `SymbolExportInfo` here. We only use - // `exported_symbols` in shims/foreign_items.rs and the export info - // is ignored. - SymbolExportInfo { - level: SymbolExportLevel::C, - kind: SymbolExportKind::Text, - used: false, - rustc_std_internal_symbol: false, - }, - )) - } else { - None - } - }), - ) - } - }); } + + // Queries overridden here affect the data stored in `rmeta` files of dependencies, + // which will be used later in non-`MIRI_BE_RUSTC` mode. + config.override_queries = Some(|_, local_providers| { + // We need to add #[used] symbols to exported_symbols for `lookup_link_section`. + // FIXME handle this somehow in rustc itself to avoid this hack. + local_providers.exported_non_generic_symbols = |tcx, LocalCrate| { + let reachable_set = tcx + .with_stable_hashing_context(|hcx| tcx.reachable_set(()).to_sorted(&hcx, true)); + tcx.arena.alloc_from_iter( + // This is based on: + // https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L62-L63 + // https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L174 + reachable_set.into_iter().filter_map(|&local_def_id| { + // Do the same filtering that rustc does: + // https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L84-L102 + // Otherwise it may cause unexpected behaviours and ICEs + // (https://github.com/rust-lang/rust/issues/86261). + let is_reachable_non_generic = matches!( + tcx.hir_node_by_def_id(local_def_id), + Node::Item(&hir::Item { + kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn{ .. }, + .. + }) | Node::ImplItem(&hir::ImplItem { + kind: hir::ImplItemKind::Fn(..), + .. + }) + if !tcx.generics_of(local_def_id).requires_monomorphization(tcx) + ); + if !is_reachable_non_generic { + return None; + } + let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id); + if codegen_fn_attrs.contains_extern_indicator() + || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) + || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) + { + Some(( + ExportedSymbol::NonGeneric(local_def_id.to_def_id()), + // Some dummy `SymbolExportInfo` here. We only use + // `exported_symbols` in shims/foreign_items.rs and the export info + // is ignored. + SymbolExportInfo { + level: SymbolExportLevel::C, + kind: SymbolExportKind::Text, + used: false, + rustc_std_internal_symbol: false, + }, + )) + } else { + None + } + }), + ) + } + }); } fn after_analysis<'tcx>( From ff39c40059992eee5c7b1aac052fb278b1ccae8d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 27 Nov 2025 19:30:17 +0000 Subject: [PATCH 4/7] Improve test --- tests/pass/target-cpu-implies-target-feature.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/pass/target-cpu-implies-target-feature.rs b/tests/pass/target-cpu-implies-target-feature.rs index a55517c02e..1acbd51ae8 100644 --- a/tests/pass/target-cpu-implies-target-feature.rs +++ b/tests/pass/target-cpu-implies-target-feature.rs @@ -3,10 +3,14 @@ //@compile-flags: -C target-cpu=x86-64-v4 fn main() { + assert!(cfg!(target_feature = "avx2")); + assert!(cfg!(target_feature = "avx512bw")); + assert!(cfg!(target_feature = "avx512cd")); + assert!(cfg!(target_feature = "avx512dq")); + assert!(cfg!(target_feature = "avx512f")); + assert!(cfg!(target_feature = "avx512vl")); assert!(is_x86_feature_detected!("avx512bw")); - assert!(is_x86_feature_detected!("avx512cd")); - assert!(is_x86_feature_detected!("avx512dq")); - assert!(is_x86_feature_detected!("avx512f")); - assert!(is_x86_feature_detected!("avx512vl")); + + assert!(cfg!(not(target_feature = "avx512vpopcntdq"))); assert!(!is_x86_feature_detected!("avx512vpopcntdq")); } From cf5b7da0f2be3d233cf364128fe7356f3ccc3712 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Nov 2025 10:33:33 +0100 Subject: [PATCH 5/7] Prepare for merging from rust-lang/rust This updates the rust-version file to 88bd39beb342e2ae7ded1eb7d58697416686d679. --- rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-version b/rust-version index 1a95b8557d..ba869b1667 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -c871d09d1cc32a649f4c5177bb819646260ed120 +88bd39beb342e2ae7ded1eb7d58697416686d679 From 4f65c5d794a5d029897f1d9c9f2faab078ab1a60 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 27 Nov 2025 20:35:26 +0100 Subject: [PATCH 6/7] test that target features given in the target spec are enabled --- tests/pass/target-spec-implies-target-feature.rs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/pass/target-spec-implies-target-feature.rs diff --git a/tests/pass/target-spec-implies-target-feature.rs b/tests/pass/target-spec-implies-target-feature.rs new file mode 100644 index 0000000000..24eee21c2f --- /dev/null +++ b/tests/pass/target-spec-implies-target-feature.rs @@ -0,0 +1,8 @@ +//! Ensure that the target features given in the target spec are actually enabled. +//@only-target: armv7 + +fn main() { + assert!(cfg!(target_feature = "v7")); + assert!(cfg!(target_feature = "vfp2")); + assert!(cfg!(target_feature = "thumb2")); +} From 4868afb875e8e138731b79f9810a6895843b8f21 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Nov 2025 10:37:52 +0100 Subject: [PATCH 7/7] clippy --- src/bin/miri.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 4e692365a8..4bf51f83c4 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -181,7 +181,7 @@ fn make_miri_codegen_backend(opts: &Options, target: &Target) -> Box