diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 98f1111627949..44bcdeacc1ec0 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -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"); } diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 6685add461e77..5c3ae359ba0bf 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -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: diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index c83070aaba7b6..12084fa0b15df 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -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 { + 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, } } diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 513716357f42e..1397c87ab075b 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -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( 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") diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index f3b3605a120d4..41bed8ed8a0a5 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -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) -> 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) -> 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) -> Config { diff_command: matches.opt_str("compiletest-diff-tool"), minicore_path: opt_path(matches, "minicore-path"), + + codegen_backend, } }