Auto merge of #144219 - GuillaumeGomez:rollup-ha29sql, r=GuillaumeGomez

Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#143282 (Add `uX::strict_sub_signed`)
 - rust-lang/rust#143423 (address clippy formatting nits)
 - rust-lang/rust#143720 (Allow `Rvalue::Repeat` to return true in `rvalue_creates_operand` too)
 - rust-lang/rust#144011 (bootstrap: Don't trigger an unnecessary LLVM build from check builds)
 - rust-lang/rust#144112 (bootstrap: Ignore `rust.debuginfo-level-tests` for codegen tests)
 - rust-lang/rust#144125 (Add new `ignore-backends` and `needs-backends` tests annotations)
 - rust-lang/rust#144143 (Fix `-Ctarget-feature`s getting ignored after `crt-static`)
 - rust-lang/rust#144150 (tests: assembly: cstring-merging: Disable GlobalMerge pass)
 - rust-lang/rust#144190 (Give a message with a span on MIR validation error)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2025-07-20 13:52:48 +00:00
31 changed files with 350 additions and 88 deletions

View File

@@ -630,7 +630,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
OperandRef { val: OperandValue::Immediate(static_), layout }
}
mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
mir::Rvalue::Repeat(..) => bug!("{rvalue:?} in codegen_rvalue_operand"),
mir::Rvalue::Repeat(ref elem, len_const) => {
// All arrays have `BackendRepr::Memory`, so only the ZST cases
// end up here. Anything else forces the destination local to be
// `Memory`, and thus ends up handled in `codegen_rvalue` instead.
let operand = self.codegen_operand(bx, elem);
let array_ty = Ty::new_array_with_const_len(bx.tcx(), operand.layout.ty, len_const);
let array_ty = self.monomorphize(array_ty);
let array_layout = bx.layout_of(array_ty);
assert!(array_layout.is_zst());
OperandRef { val: OperandValue::ZeroSized, layout: array_layout }
}
mir::Rvalue::Aggregate(ref kind, ref fields) => {
let (variant_index, active_field_index) = match **kind {
mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
@@ -1000,12 +1010,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::Rvalue::NullaryOp(..) |
mir::Rvalue::ThreadLocalRef(_) |
mir::Rvalue::Use(..) |
mir::Rvalue::Repeat(..) | // (*)
mir::Rvalue::Aggregate(..) | // (*)
mir::Rvalue::WrapUnsafeBinder(..) => // (*)
true,
// Arrays are always aggregates, so it's not worth checking anything here.
// (If it's really `[(); N]` or `[T; 0]` and we use the place path, fine.)
mir::Rvalue::Repeat(..) => false,
}
// (*) this is only true if the type is suitable

View File

@@ -149,14 +149,14 @@ fn parse_rust_feature_flag<'a>(
if let Some(base_feature) = feature.strip_prefix('+') {
// Skip features that are not target features, but rustc features.
if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) {
return;
continue;
}
callback(base_feature, sess.target.implied_target_features(base_feature), true)
} else if let Some(base_feature) = feature.strip_prefix('-') {
// Skip features that are not target features, but rustc features.
if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) {
return;
continue;
}
// If `f1` implies `f2`, then `!f2` implies `!f1` -- this is standard logical

View File

@@ -119,8 +119,9 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
#[track_caller]
fn fail(&self, location: Location, msg: impl AsRef<str>) {
// We might see broken MIR when other errors have already occurred.
assert!(
self.tcx.dcx().has_errors().is_some(),
if self.tcx.dcx().has_errors().is_none() {
span_bug!(
self.body.source_info(location).span,
"broken MIR in {:?} ({}) at {:?}:\n{}",
self.body.source.instance,
self.when,
@@ -128,6 +129,7 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
msg.as_ref(),
);
}
}
fn check_edge(&mut self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
if bb == START_BLOCK {

View File

@@ -1482,13 +1482,14 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
}
}
fn default_chaining_impl<T: PointeeSized, U: PointeeSized>(
fn default_chaining_impl<T, U>(
lhs: &T,
rhs: &U,
p: impl FnOnce(Ordering) -> bool,
) -> ControlFlow<bool>
where
T: PartialOrd<U>,
T: PartialOrd<U> + PointeeSized,
U: PointeeSized,
{
// It's important that this only call `partial_cmp` once, not call `eq` then
// one of the relational operators. We don't want to `bcmp`-then-`memcp` a

View File

@@ -854,7 +854,6 @@ impl Display for Arguments<'_> {
/// }";
/// assert_eq!(format!("The origin is: {origin:#?}"), expected);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
on(

View File

@@ -436,7 +436,6 @@ pub trait Extend<A> {
/// **For implementors:** For a collection to unsafely rely on this method's safety precondition (that is,
/// invoke UB if they are violated), it must implement `extend_reserve` correctly. In other words,
/// callers may assume that if they `extend_reserve`ed enough space they can call this method.
// This method is for internal usage only. It is only on the trait because of specialization's limitations.
#[unstable(feature = "extend_one_unchecked", issue = "none")]
#[doc(hidden)]

View File

@@ -3414,10 +3414,10 @@ pub trait Iterator {
/// ```
#[stable(feature = "iter_copied", since = "1.36.0")]
#[rustc_diagnostic_item = "iter_copied"]
fn copied<'a, T: 'a>(self) -> Copied<Self>
fn copied<'a, T>(self) -> Copied<Self>
where
T: Copy + 'a,
Self: Sized + Iterator<Item = &'a T>,
T: Copy,
{
Copied::new(self)
}
@@ -3462,10 +3462,10 @@ pub trait Iterator {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "iter_cloned"]
fn cloned<'a, T: 'a>(self) -> Cloned<Self>
fn cloned<'a, T>(self) -> Cloned<Self>
where
T: Clone + 'a,
Self: Sized + Iterator<Item = &'a T>,
T: Clone,
{
Cloned::new(self)
}

View File

@@ -787,7 +787,6 @@ impl Ipv4Addr {
/// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
/// [unspecified address]: Ipv4Addr::UNSPECIFIED
/// [broadcast address]: Ipv4Addr::BROADCAST
///
/// # Examples
///

View File

@@ -1,5 +1,5 @@
/// These functions compute the integer logarithm of their type, assuming
/// that someone has already checked that the value is strictly positive.
//! These functions compute the integer logarithm of their type, assuming
//! that someone has already checked that the value is strictly positive.
// 0 < val <= u8::MAX
#[inline]

View File

@@ -805,6 +805,43 @@ macro_rules! uint_impl {
}
}
/// Strict subtraction with a signed integer. Computes `self - rhs`,
/// panicking if overflow occurred.
///
/// # Panics
///
/// ## Overflow behavior
///
/// This function will always panic on overflow, regardless of whether overflow checks are enabled.
///
/// # Examples
///
/// ```
/// #![feature(strict_overflow_ops)]
#[doc = concat!("assert_eq!(3", stringify!($SelfT), ".strict_sub_signed(2), 1);")]
/// ```
///
/// The following panic because of overflow:
///
/// ```should_panic
/// #![feature(strict_overflow_ops)]
#[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_sub_signed(2);")]
/// ```
///
/// ```should_panic
/// #![feature(strict_overflow_ops)]
#[doc = concat!("let _ = (", stringify!($SelfT), "::MAX).strict_sub_signed(-1);")]
/// ```
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn strict_sub_signed(self, rhs: $SignedT) -> Self {
let (a, b) = self.overflowing_sub_signed(rhs);
if b { overflow_panic::sub() } else { a }
}
#[doc = concat!(
"Checked integer subtraction. Computes `self - rhs` and checks if the result fits into an [`",
stringify!($SignedT), "`], returning `None` if overflow occurred."

View File

@@ -1363,7 +1363,6 @@ mod prim_f16 {}
/// x = a + b + c + d; // As written
/// x = (a + c) + (b + d); // Reordered to shorten critical path and enable vectorization
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_f32 {}

View File

@@ -2651,7 +2651,6 @@ impl str {
/// you're trying to parse into.
///
/// `parse` can parse into any type that implements the [`FromStr`] trait.
///
/// # Errors
///

View File

@@ -355,7 +355,7 @@ impl Step for CodegenBackend {
cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
rustc_cargo_env(builder, &mut cargo, target, build_compiler.stage);
rustc_cargo_env(builder, &mut cargo, target);
let _guard = builder.msg_check(format!("rustc_codegen_{backend}"), target, None);

View File

@@ -1316,15 +1316,10 @@ pub fn rustc_cargo(
cargo.env("RUSTC_WRAPPER", ccache);
}
rustc_cargo_env(builder, cargo, target, build_compiler.stage);
rustc_cargo_env(builder, cargo, target);
}
pub fn rustc_cargo_env(
builder: &Builder<'_>,
cargo: &mut Cargo,
target: TargetSelection,
build_stage: u32,
) {
pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
// Set some configuration variables picked up by build scripts and
// the compiler alike
cargo
@@ -1379,18 +1374,24 @@ pub fn rustc_cargo_env(
cargo.rustflag("--cfg=llvm_enzyme");
}
// Note that this is disabled if LLVM itself is disabled or we're in a check
// build. If we are in a check build we still go ahead here presuming we've
// detected that LLVM is already built and good to go which helps prevent
// busting caches (e.g. like #71152).
// These conditionals represent a tension between three forces:
// - For non-check builds, we need to define some LLVM-related environment
// variables, requiring LLVM to have been built.
// - For check builds, we want to avoid building LLVM if possible.
// - Check builds and non-check builds should have the same environment if
// possible, to avoid unnecessary rebuilds due to cache-busting.
//
// Therefore we try to avoid building LLVM for check builds, but only if
// building LLVM would be expensive. If "building" LLVM is cheap
// (i.e. it's already built or is downloadable), we prefer to maintain a
// consistent environment between check and non-check builds.
if builder.config.llvm_enabled(target) {
let building_is_expensive =
let building_llvm_is_expensive =
crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
.should_build();
// `top_stage == stage` might be false for `check --stage 1`, if we are building the stage 1 compiler
let can_skip_build = builder.kind == Kind::Check && builder.top_stage == build_stage;
let should_skip_build = building_is_expensive && can_skip_build;
if !should_skip_build {
let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
if !skip_llvm {
rustc_llvm_env(builder, cargo, target)
}
}
@@ -1407,6 +1408,9 @@ pub fn rustc_cargo_env(
/// Pass down configuration from the LLVM build into the build of
/// rustc_llvm and rustc_codegen_llvm.
///
/// Note that this has the side-effect of _building LLVM_, which is sometimes
/// unwanted (e.g. for check builds).
fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
if builder.config.is_rust_llvm(target) {
cargo.env("LLVM_RUSTLLVM", "1");
@@ -1665,7 +1669,7 @@ impl Step for CodegenBackend {
cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
rustc_cargo_env(builder, &mut cargo, target);
// Ideally, we'd have a separate step for the individual codegen backends,
// like we have in tests (test::CodegenGCC) but that would require a lot of restructuring.

View File

@@ -1757,6 +1757,10 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
cmd.arg("--host").arg(&*compiler.host.triple);
cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
if let Some(codegen_backend) = builder.config.default_codegen_backend(compiler.host) {
cmd.arg("--codegen-backend").arg(&codegen_backend);
}
if builder.build.config.llvm_enzyme {
cmd.arg("--has-enzyme");
}
@@ -1810,7 +1814,24 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
}
let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
flags.push(format!(
"-Cdebuginfo={}",
if suite == "codegen" {
// codegen tests typically check LLVM IR and are sensitive to additional debuginfo.
// So do not apply `rust.debuginfo-level-tests` for codegen tests.
if builder.config.rust_debuginfo_level_tests
!= crate::core::config::DebuginfoLevel::None
{
println!(
"NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
builder.config.rust_debuginfo_level_tests
);
}
crate::core::config::DebuginfoLevel::None
} else {
builder.config.rust_debuginfo_level_tests
}
));
flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
if suite != "mir-opt" {
@@ -3387,7 +3408,7 @@ impl Step for CodegenCranelift {
cargo
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
compile::rustc_cargo_env(builder, &mut cargo, target);
// Avoid incremental cache issues when changing rustc
cargo.env("CARGO_BUILD_INCREMENTAL", "false");
@@ -3519,7 +3540,7 @@ impl Step for CodegenGCC {
cargo
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
compile::rustc_cargo_env(builder, &mut cargo, target);
add_cg_gcc_cargo_flags(&mut cargo, &gcc);
// Avoid incremental cache issues when changing rustc

View File

@@ -712,7 +712,11 @@ mod snapshot {
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
");
}
#[test]
fn build_rustc_no_explicit_stage() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
ctx.config("build")
.path("rustc")
@@ -1303,17 +1307,19 @@ mod snapshot {
ctx.config("check")
.path("compiler")
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
");
}
#[test]
fn check_rustc_no_explicit_stage() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
ctx.config("check")
.path("rustc")
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
");
}
@@ -1333,7 +1339,6 @@ mod snapshot {
.path("compiler")
.stage(1)
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
@@ -1465,7 +1470,6 @@ mod snapshot {
.paths(&["library", "compiler"])
.args(&args)
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
@@ -1479,7 +1483,6 @@ mod snapshot {
ctx.config("check")
.path("miri")
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> Miri 1 <host>
");
@@ -1500,7 +1503,6 @@ mod snapshot {
.path("miri")
.stage(1)
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> Miri 1 <host>
");
@@ -1553,7 +1555,6 @@ mod snapshot {
ctx.config("check")
.path("rustc_codegen_cranelift")
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
@@ -1567,7 +1568,6 @@ mod snapshot {
ctx.config("check")
.path("rust-analyzer")
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> rust-analyzer 1 <host>
");

View File

@@ -205,6 +205,8 @@ settings:
on `wasm32-unknown-unknown` target because the target does not support the
`proc-macro` crate type.
- `needs-target-std` — ignores if target platform does not have std support.
- `ignore-backends` — ignores the listed backends, separated by whitespace characters.
- `needs-backends` — only runs the test if current codegen backend is listed.
The following directives will check LLVM support:

View File

@@ -175,6 +175,36 @@ pub enum Sanitizer {
Hwaddress,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum CodegenBackend {
Cranelift,
Gcc,
Llvm,
}
impl<'a> TryFrom<&'a str> for CodegenBackend {
type Error = &'static str;
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
match value.to_lowercase().as_str() {
"cranelift" => Ok(Self::Cranelift),
"gcc" => Ok(Self::Gcc),
"llvm" => Ok(Self::Llvm),
_ => Err("unknown backend"),
}
}
}
impl CodegenBackend {
pub fn as_str(self) -> &'static str {
match self {
Self::Cranelift => "cranelift",
Self::Gcc => "gcc",
Self::Llvm => "llvm",
}
}
}
/// Configuration for `compiletest` *per invocation*.
///
/// In terms of `bootstrap`, this means that `./x test tests/ui tests/run-make` actually correspond
@@ -651,6 +681,9 @@ pub struct Config {
/// need `core` stubs in cross-compilation scenarios that do not otherwise want/need to
/// `-Zbuild-std`. Used in e.g. ABI tests.
pub minicore_path: Utf8PathBuf,
/// Current codegen backend used.
pub codegen_backend: CodegenBackend,
}
impl Config {
@@ -753,6 +786,7 @@ impl Config {
profiler_runtime: Default::default(),
diff_command: Default::default(),
minicore_path: Default::default(),
codegen_backend: CodegenBackend::Llvm,
}
}

View File

@@ -9,7 +9,7 @@ use camino::{Utf8Path, Utf8PathBuf};
use semver::Version;
use tracing::*;
use crate::common::{Config, Debugger, FailMode, PassMode, RunFailMode, TestMode};
use crate::common::{CodegenBackend, Config, Debugger, FailMode, PassMode, RunFailMode, TestMode};
use crate::debuggers::{extract_cdb_version, extract_gdb_version};
use crate::directives::auxiliary::{AuxProps, parse_and_update_aux};
use crate::directives::needs::CachedNeedsConditions;
@@ -818,6 +818,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"ignore-arm-unknown-linux-musleabihf",
"ignore-auxiliary",
"ignore-avr",
"ignore-backends",
"ignore-beta",
"ignore-cdb",
"ignore-compare-mode-next-solver",
@@ -907,6 +908,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"min-llvm-version",
"min-system-llvm-version",
"needs-asm-support",
"needs-backends",
"needs-crate-type",
"needs-deterministic-layouts",
"needs-dlltool",
@@ -1669,6 +1671,8 @@ pub(crate) fn make_test_description<R: Read>(
decision!(cfg::handle_only(config, ln));
decision!(needs::handle_needs(&cache.needs, config, ln));
decision!(ignore_llvm(config, path, ln));
decision!(ignore_backends(config, path, ln));
decision!(needs_backends(config, path, ln));
decision!(ignore_cdb(config, ln));
decision!(ignore_gdb(config, ln));
decision!(ignore_lldb(config, ln));
@@ -1795,6 +1799,49 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
IgnoreDecision::Continue
}
fn ignore_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
if let Some(backends_to_ignore) = config.parse_name_value_directive(line, "ignore-backends") {
for backend in backends_to_ignore.split_whitespace().map(|backend| {
match CodegenBackend::try_from(backend) {
Ok(backend) => backend,
Err(error) => {
panic!("Invalid ignore-backends value `{backend}` in `{path}`: {error}")
}
}
}) {
if config.codegen_backend == backend {
return IgnoreDecision::Ignore {
reason: format!("{} backend is marked as ignore", backend.as_str()),
};
}
}
}
IgnoreDecision::Continue
}
fn needs_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
if let Some(needed_backends) = config.parse_name_value_directive(line, "needs-backends") {
if !needed_backends
.split_whitespace()
.map(|backend| match CodegenBackend::try_from(backend) {
Ok(backend) => backend,
Err(error) => {
panic!("Invalid needs-backends value `{backend}` in `{path}`: {error}")
}
})
.any(|backend| config.codegen_backend == backend)
{
return IgnoreDecision::Ignore {
reason: format!(
"{} backend is not part of required backends",
config.codegen_backend.as_str()
),
};
}
}
IgnoreDecision::Continue
}
fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
if let Some(needed_components) =
config.parse_name_value_directive(line, "needs-llvm-components")

View File

@@ -39,7 +39,7 @@ use walkdir::WalkDir;
use self::directives::{EarlyProps, make_test_description};
use crate::common::{
CompareMode, Config, Debugger, PassMode, TestMode, TestPaths, UI_EXTENSIONS,
CodegenBackend, CompareMode, Config, Debugger, PassMode, TestMode, TestPaths, UI_EXTENSIONS,
expected_output_path, output_base_dir, output_relative_path,
};
use crate::directives::DirectivesCache;
@@ -203,6 +203,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
"debugger",
"only test a specific debugger in debuginfo tests",
"gdb | lldb | cdb",
)
.optopt(
"",
"codegen-backend",
"the codegen backend currently used",
"CODEGEN BACKEND NAME",
);
let (argv0, args_) = args.split_first().unwrap();
@@ -264,6 +270,15 @@ pub fn parse_config(args: Vec<String>) -> Config {
|| directives::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
);
let codegen_backend = match matches.opt_str("codegen-backend").as_deref() {
Some(backend) => match CodegenBackend::try_from(backend) {
Ok(backend) => backend,
Err(error) => panic!("invalid value `{backend}` for `--codegen-backend`: {error}"),
},
// By default, it's always llvm.
None => CodegenBackend::Llvm,
};
let run_ignored = matches.opt_present("ignored");
let with_rustc_debug_assertions = matches.opt_present("with-rustc-debug-assertions");
let with_std_debug_assertions = matches.opt_present("with-std-debug-assertions");
@@ -449,6 +464,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
diff_command: matches.opt_str("compiletest-diff-tool"),
minicore_path: opt_path(matches, "minicore-path"),
codegen_backend,
}
}

View File

@@ -1,11 +1,15 @@
error: internal compiler error: compiler/rustc_mir_transform/src/validate.rs:LL:CC: broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]:
place (*(_2.0: *mut i32)) has deref as a later projection (it is only permitted as the first projection)
--> tests/panic/mir-validation.rs:LL:CC
|
LL | *(tuple.0) = 1;
| ^^^^^^^^^^^^^^
thread 'rustc' panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC:
broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]:
place (*(_2.0: *mut i32)) has deref as a later projection (it is only permitted as the first projection)
Box<dyn Any>
stack backtrace:
error: the compiler unexpectedly panicked. this is a bug.
@@ -20,3 +24,5 @@ LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
error: aborting due to 1 previous error

View File

@@ -2,7 +2,7 @@
// other architectures (including ARM and x86-64) use the prefix `.Lanon.`
//@ only-linux
//@ assembly-output: emit-asm
//@ compile-flags: --crate-type=lib -Copt-level=3
//@ compile-flags: --crate-type=lib -Copt-level=3 -Cllvm-args=-enable-global-merge=0
//@ edition: 2024
use std::ffi::CStr;

View File

@@ -0,0 +1,28 @@
//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes
// This test is here to hit the `Rvalue::Repeat` case in `codegen_rvalue_operand`.
// It only applies when the resulting array is a ZST, so the test is written in
// such a way as to keep MIR optimizations from seeing that fact and removing
// the local and statement altogether. (At the time of writing, no other codegen
// test hit that code path, nor did a stage 2 build of the compiler.)
#![crate_type = "lib"]
#[repr(transparent)]
pub struct Wrapper<T, const N: usize>([T; N]);
// CHECK-LABEL: define {{.+}}do_repeat{{.+}}(i32 noundef %x)
// CHECK-NEXT: start:
// CHECK-NOT: alloca
// CHECK-NEXT: ret void
#[inline(never)]
pub fn do_repeat<T: Copy, const N: usize>(x: T) -> Wrapper<T, N> {
Wrapper([x; N])
}
// CHECK-LABEL: @trigger_repeat_zero_len
#[no_mangle]
pub fn trigger_repeat_zero_len() -> Wrapper<u32, 0> {
// CHECK: call void {{.+}}do_repeat{{.+}}(i32 noundef 4)
do_repeat(4)
}

View File

@@ -0,0 +1,28 @@
//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes
// This test is here to hit the `Rvalue::Repeat` case in `codegen_rvalue_operand`.
// It only applies when the resulting array is a ZST, so the test is written in
// such a way as to keep MIR optimizations from seeing that fact and removing
// the local and statement altogether. (At the time of writing, no other codegen
// test hit that code path, nor did a stage 2 build of the compiler.)
#![crate_type = "lib"]
#[repr(transparent)]
pub struct Wrapper<T, const N: usize>([T; N]);
// CHECK-LABEL: define {{.+}}do_repeat{{.+}}()
// CHECK-NEXT: start:
// CHECK-NOT: alloca
// CHECK-NEXT: ret void
#[inline(never)]
pub fn do_repeat<T: Copy, const N: usize>(x: T) -> Wrapper<T, N> {
Wrapper([x; N])
}
// CHECK-LABEL: @trigger_repeat_zst_elem
#[no_mangle]
pub fn trigger_repeat_zst_elem() -> Wrapper<(), 8> {
// CHECK: call void {{.+}}do_repeat{{.+}}()
do_repeat(())
}

View File

@@ -0,0 +1,24 @@
// Test to ensure that specifying a value for crt-static in target features
// does not result in skipping the features following it.
// This is a regression test for #144143
//@ add-core-stubs
//@ needs-llvm-components: x86
//@ compile-flags: --target=x86_64-unknown-linux-gnu
//@ compile-flags: -Ctarget-feature=+crt-static,+avx2
#![crate_type = "rlib"]
#![feature(no_core, rustc_attrs, lang_items)]
#![no_core]
extern crate minicore;
use minicore::*;
#[rustc_builtin_macro]
macro_rules! compile_error {
() => {};
}
#[cfg(target_feature = "avx2")]
compile_error!("+avx2");
//~^ ERROR: +avx2

View File

@@ -0,0 +1,8 @@
error: +avx2
--> $DIR/crt-static-with-target-features-works.rs:23:1
|
LL | compile_error!("+avx2");
| ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@@ -21,6 +21,8 @@ pub fn f(a: u32) -> u32 {
}
bb1 = {
Call(RET = f(1), ReturnTo(bb2), UnwindTerminate(ReasonAbi))
//~^ ERROR broken MIR in Item
//~| ERROR encountered critical edge in `Call` terminator
}
bb2 = {
@@ -29,5 +31,3 @@ pub fn f(a: u32) -> u32 {
}
}
}
//~? RAW encountered critical edge in `Call` terminator