From 26b0560b6db4f7116809c81532c2d64f43b74998 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 28 Oct 2025 19:48:56 -0400 Subject: [PATCH] rustc_target: allow unenumerated architectures --- .../rustc_codegen_cranelift/src/abi/mod.rs | 2 +- compiler/rustc_codegen_gcc/src/abi.rs | 8 +-- compiler/rustc_codegen_gcc/src/context.rs | 2 +- compiler/rustc_codegen_gcc/src/gcc_util.rs | 62 +++++++++---------- compiler/rustc_codegen_llvm/src/abi.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 2 +- .../rustc_codegen_ssa/src/back/archive.rs | 4 +- compiler/rustc_codegen_ssa/src/base.rs | 2 +- compiler/rustc_session/src/session.rs | 2 +- compiler/rustc_target/src/asm/mod.rs | 4 +- compiler/rustc_target/src/callconv/mod.rs | 6 +- compiler/rustc_target/src/lib.rs | 61 ++++++++++++++++++ .../rustc_target/src/spec/base/apple/mod.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 16 +++-- compiler/rustc_target/src/target_features.rs | 14 +++-- compiler/rustc_target/src/tests.rs | 25 ++++++++ src/tools/miri/src/shims/alloc.rs | 5 +- tests/ui/check-cfg/my-awesome-platform.json | 2 +- tests/ui/check-cfg/values-target-json.rs | 15 +++-- 19 files changed, 169 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 6ea26b02c261..d7f17795815d 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -788,7 +788,7 @@ pub(crate) fn codegen_drop<'tcx>( pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam { let param = AbiParam::new(ty); if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size().bits() { - match (tcx.sess.target.arch, tcx.sess.target.vendor.as_ref()) { + match (&tcx.sess.target.arch, tcx.sess.target.vendor.as_ref()) { (Arch::X86_64, _) | (Arch::AArch64, "apple") => match (ty, is_signed) { (types::I8 | types::I16, true) => param.sext(), (types::I8 | types::I16, false) => param.uext(), diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs index b7d0e19ee272..bcc28e476dba 100644 --- a/compiler/rustc_codegen_gcc/src/abi.rs +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -235,12 +235,12 @@ 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(self.conv, &cx.tcx.sess.target.arch) } } #[cfg(feature = "master")] -pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: Arch) -> Option> { +pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &Arch) -> Option> { let attribute = match conv { CanonAbi::C | CanonAbi::Rust => return None, CanonAbi::RustCold => FnAttribute::Cold, @@ -254,8 +254,8 @@ pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: Arch) -> Option FnAttribute::ArmPcs("aapcs"), }, CanonAbi::GpuKernel => match arch { - Arch::AmdGpu => FnAttribute::GcnAmdGpuHsaKernel, - Arch::Nvptx64 => FnAttribute::NvptxKernel, + &Arch::AmdGpu => FnAttribute::GcnAmdGpuHsaKernel, + &Arch::Nvptx64 => FnAttribute::NvptxKernel, arch => panic!("Arch {arch} does not support GpuKernel calling convention"), }, // TODO(antoyo): check if those AVR attributes are mapped correctly. diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 6084b4fc07fa..c9ae96777de4 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -487,7 +487,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { 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); + let conv = conv_to_fn_attribute(self.sess().target.entry_abi, &self.sess().target.arch); #[cfg(not(feature = "master"))] let conv = None; Some(self.declare_entry_fn(entry_name, fn_type, conv)) diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 83d54472e5de..e33b6c92d637 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -67,46 +67,46 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { // cSpell:disable - match (sess.target.arch, s) { + match (&sess.target.arch, s) { // FIXME: seems like x87 does not exist? - (Arch::X86 | Arch::X86_64, "x87") => smallvec![], - (Arch::X86 | Arch::X86_64, "sse4.2") => smallvec!["sse4.2", "crc32"], - (Arch::X86 | Arch::X86_64, "pclmulqdq") => smallvec!["pclmul"], - (Arch::X86 | Arch::X86_64, "rdrand") => smallvec!["rdrnd"], - (Arch::X86 | Arch::X86_64, "bmi1") => smallvec!["bmi"], - (Arch::X86 | Arch::X86_64, "cmpxchg16b") => smallvec!["cx16"], - (Arch::X86 | Arch::X86_64, "avx512vaes") => smallvec!["vaes"], - (Arch::X86 | Arch::X86_64, "avx512gfni") => smallvec!["gfni"], - (Arch::X86 | Arch::X86_64, "avx512vpclmulqdq") => smallvec!["vpclmulqdq"], + (&Arch::X86 | &Arch::X86_64, "x87") => smallvec![], + (&Arch::X86 | &Arch::X86_64, "sse4.2") => smallvec!["sse4.2", "crc32"], + (&Arch::X86 | &Arch::X86_64, "pclmulqdq") => smallvec!["pclmul"], + (&Arch::X86 | &Arch::X86_64, "rdrand") => smallvec!["rdrnd"], + (&Arch::X86 | &Arch::X86_64, "bmi1") => smallvec!["bmi"], + (&Arch::X86 | &Arch::X86_64, "cmpxchg16b") => smallvec!["cx16"], + (&Arch::X86 | &Arch::X86_64, "avx512vaes") => smallvec!["vaes"], + (&Arch::X86 | &Arch::X86_64, "avx512gfni") => smallvec!["gfni"], + (&Arch::X86 | &Arch::X86_64, "avx512vpclmulqdq") => smallvec!["vpclmulqdq"], // NOTE: seems like GCC requires 'avx512bw' for 'avx512vbmi2'. - (Arch::X86 | Arch::X86_64, "avx512vbmi2") => { + (&Arch::X86 | &Arch::X86_64, "avx512vbmi2") => { smallvec!["avx512vbmi2", "avx512bw"] } // NOTE: seems like GCC requires 'avx512bw' for 'avx512bitalg'. - (Arch::X86 | Arch::X86_64, "avx512bitalg") => { + (&Arch::X86 | &Arch::X86_64, "avx512bitalg") => { smallvec!["avx512bitalg", "avx512bw"] } - (Arch::AArch64, "rcpc2") => smallvec!["rcpc-immo"], - (Arch::AArch64, "dpb") => smallvec!["ccpp"], - (Arch::AArch64, "dpb2") => smallvec!["ccdp"], - (Arch::AArch64, "frintts") => smallvec!["fptoint"], - (Arch::AArch64, "fcma") => smallvec!["complxnum"], - (Arch::AArch64, "pmuv3") => smallvec!["perfmon"], - (Arch::AArch64, "paca") => smallvec!["pauth"], - (Arch::AArch64, "pacg") => smallvec!["pauth"], + (&Arch::AArch64, "rcpc2") => smallvec!["rcpc-immo"], + (&Arch::AArch64, "dpb") => smallvec!["ccpp"], + (&Arch::AArch64, "dpb2") => smallvec!["ccdp"], + (&Arch::AArch64, "frintts") => smallvec!["fptoint"], + (&Arch::AArch64, "fcma") => smallvec!["complxnum"], + (&Arch::AArch64, "pmuv3") => smallvec!["perfmon"], + (&Arch::AArch64, "paca") => smallvec!["pauth"], + (&Arch::AArch64, "pacg") => smallvec!["pauth"], // Rust ties fp and neon together. In GCC neon implicitly enables fp, // but we manually enable neon when a feature only implicitly enables fp - (Arch::AArch64, "f32mm") => smallvec!["f32mm", "neon"], - (Arch::AArch64, "f64mm") => smallvec!["f64mm", "neon"], - (Arch::AArch64, "fhm") => smallvec!["fp16fml", "neon"], - (Arch::AArch64, "fp16") => smallvec!["fullfp16", "neon"], - (Arch::AArch64, "jsconv") => smallvec!["jsconv", "neon"], - (Arch::AArch64, "sve") => smallvec!["sve", "neon"], - (Arch::AArch64, "sve2") => smallvec!["sve2", "neon"], - (Arch::AArch64, "sve2-aes") => smallvec!["sve2-aes", "neon"], - (Arch::AArch64, "sve2-sm4") => smallvec!["sve2-sm4", "neon"], - (Arch::AArch64, "sve2-sha3") => smallvec!["sve2-sha3", "neon"], - (Arch::AArch64, "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"], + (&Arch::AArch64, "f32mm") => smallvec!["f32mm", "neon"], + (&Arch::AArch64, "f64mm") => smallvec!["f64mm", "neon"], + (&Arch::AArch64, "fhm") => smallvec!["fp16fml", "neon"], + (&Arch::AArch64, "fp16") => smallvec!["fullfp16", "neon"], + (&Arch::AArch64, "jsconv") => smallvec!["jsconv", "neon"], + (&Arch::AArch64, "sve") => smallvec!["sve", "neon"], + (&Arch::AArch64, "sve2") => smallvec!["sve2", "neon"], + (&Arch::AArch64, "sve2-aes") => smallvec!["sve2-aes", "neon"], + (&Arch::AArch64, "sve2-sm4") => smallvec!["sve2-sm4", "neon"], + (&Arch::AArch64, "sve2-sha3") => smallvec!["sve2-sha3", "neon"], + (&Arch::AArch64, "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"], (_, s) => smallvec![s], } // cSpell:enable diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index b045af3161dc..e6b76f74158b 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -698,7 +698,7 @@ pub(crate) fn to_llvm_calling_convention(sess: &Session, abi: CanonAbi) -> llvm: // possible to declare an `extern "custom"` block, so the backend still needs a calling // convention for declaring foreign functions. CanonAbi::Custom => llvm::CCallConv, - CanonAbi::GpuKernel => match sess.target.arch { + CanonAbi::GpuKernel => match &sess.target.arch { Arch::AmdGpu => llvm::AmdgpuKernel, Arch::Nvptx64 => llvm::PtxKernel, arch => panic!("Architecture {arch} does not support GpuKernel calling convention"), diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 8f8a3a3aef2f..32ea3987f968 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -342,7 +342,7 @@ pub(crate) fn target_config(sess: &Session) -> TargetConfig { /// Determine whether or not experimental float types are reliable based on known bugs. fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) { - let target_arch = sess.target.arch; + let target_arch = &sess.target.arch; let target_os = sess.target.options.os.as_ref(); let target_env = sess.target.options.env.as_ref(); let target_abi = sess.target.options.abi.as_ref(); diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index cef7df44abe3..93f6cb3b87e6 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -118,7 +118,7 @@ pub trait ArchiveBuilderBuilder { let exports = items.into_iter().map(|item| item.into_coff_short_export(sess)).collect::>(); - let machine = match sess.target.arch { + let machine = match &sess.target.arch { Arch::X86_64 => MachineTypes::AMD64, Arch::X86 => MachineTypes::I386, Arch::AArch64 => MachineTypes::ARM64, @@ -224,7 +224,7 @@ fn create_mingw_dll_import_lib( }; // dlltool target architecture args from: // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69 - let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch { + let (dlltool_target_arch, dlltool_target_bitness) = match &sess.target.arch { Arch::X86_64 => ("i386:x86-64", "--64"), Arch::X86 => ("i386", "--32"), Arch::AArch64 => ("arm64", "--64"), diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index a50054758729..ed2815b06c18 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -983,7 +983,7 @@ impl CrateInfo { // by the compiler, but that's ok because all this stuff is unstable anyway. let target = &tcx.sess.target; if !are_upstream_rust_objects_already_included(tcx.sess) { - let add_prefix = match (target.is_like_windows, target.arch) { + let add_prefix = match (target.is_like_windows, &target.arch) { (true, Arch::X86) => |name: String, _: SymbolExportKind| format!("_{name}"), (true, Arch::Arm64EC) => { // Only functions are decorated for arm64ec. diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 63d64b410950..16f9774554e1 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1112,7 +1112,7 @@ pub fn build_session( _ => CtfeBacktrace::Disabled, }); - let asm_arch = if target.allow_asm { InlineAsmArch::from_arch(target.arch) } else { None }; + let asm_arch = if target.allow_asm { InlineAsmArch::from_arch(&target.arch) } else { None }; let target_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &target_tlib_path, &target); let host_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &host_tlib_path, &host); diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index e5c140a848c3..cd7d9125d7b5 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -245,7 +245,7 @@ pub enum InlineAsmArch { } impl InlineAsmArch { - pub fn from_arch(arch: Arch) -> Option { + pub fn from_arch(arch: &Arch) -> Option { match arch { Arch::X86 => Some(Self::X86), Arch::X86_64 => Some(Self::X86_64), @@ -273,7 +273,7 @@ impl InlineAsmArch { Arch::Msp430 => Some(Self::Msp430), Arch::M68k => Some(Self::M68k), Arch::CSky => Some(Self::CSKY), - Arch::AmdGpu | Arch::Xtensa => None, + Arch::AmdGpu | Arch::Xtensa | Arch::Unknown(_) => None, } } } diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index ef55bc45a774..43e1ca3ef9ce 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -633,7 +633,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { } let spec = cx.target_spec(); - match spec.arch { + match &spec.arch { Arch::X86 => { let (flavor, regparm) = match abi { ExternAbi::Fastcall { .. } | ExternAbi::Vectorcall { .. } => { @@ -701,7 +701,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { Arch::RiscV32 | Arch::RiscV64 => riscv::compute_abi_info(cx, self), Arch::Wasm32 | Arch::Wasm64 => wasm::compute_abi_info(cx, self), Arch::Bpf => bpf::compute_abi_info(cx, self), - arch @ (Arch::PowerPC64LE | Arch::SpirV) => { + arch @ (Arch::PowerPC64LE | Arch::SpirV | Arch::Unknown(_)) => { panic!("no lowering implemented for {arch}") } } @@ -713,7 +713,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { C: HasDataLayout + HasTargetSpec, { let spec = cx.target_spec(); - match spec.arch { + match &spec.arch { Arch::X86 => x86::compute_rust_abi_info(cx, self), Arch::RiscV32 | Arch::RiscV64 => riscv::compute_rust_abi_info(cx, self), Arch::LoongArch32 | Arch::LoongArch64 => loongarch::compute_rust_abi_info(cx, self), diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index f664bbb874d6..b38ce20e6095 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -118,6 +118,67 @@ macro_rules! target_spec_enum { } } + crate::target_spec_enum!(@common_impls $Name); + }; + + ( + $( #[$attr:meta] )* + pub enum $Name:ident { + $( + $( #[$variant_attr:meta] )* + $Variant:ident = $string:literal, + )* + } + $( #[$other_variant_attr:meta] )* + other_variant = $OtherVariant:ident; + ) => { + $( #[$attr] )* + #[derive(Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] + pub enum $Name { + $( + $( #[$variant_attr:meta] )* + $Variant, + )* + $( #[$other_variant_attr] )* + $OtherVariant(crate::spec::StaticCow), + } + + impl schemars::JsonSchema for $Name { + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed(stringify!($Name)) + } + + fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { + schemars::json_schema!({ + "type": "string" + }) + } + } + + impl FromStr for $Name { + type Err = core::convert::Infallible; + + fn from_str(s: &str) -> Result { + Ok(match s { + $( $string => Self::$Variant, )* + _ => Self::$OtherVariant(s.to_owned().into()), + }) + } + } + + impl $Name { + pub fn desc(&self) -> &str { + match self { + $( Self::$Variant => $string, )* + Self::$OtherVariant(name) => name.as_ref(), + } + } + } + + crate::target_spec_enum!(@common_impls $Name); + }; + + (@common_impls $Name:ident) => { impl crate::json::ToJson for $Name { fn to_json(&self) -> crate::json::Json { self.desc().to_json() diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index cf147e48c501..047bc9b8518b 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -311,7 +311,7 @@ impl OSVersion { /// This matches what LLVM does, see in part: /// pub fn minimum_deployment_target(target: &Target) -> Self { - let (major, minor, patch) = match (&*target.os, target.arch, &*target.env) { + let (major, minor, patch) = match (&*target.os, &target.arch, &*target.env) { ("macos", crate::spec::Arch::AArch64, _) => (11, 0, 0), ("ios", crate::spec::Arch::AArch64, "macabi") => (14, 0, 0), ("ios", crate::spec::Arch::AArch64, "sim") => (14, 0, 0), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 7f3fea1d7da7..74048d351802 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1881,12 +1881,18 @@ crate::target_spec_enum! { X86_64 = "x86_64", Xtensa = "xtensa", } - - parse_error_type = "architecture"; + /// The vast majority of the time, the compiler deals with a fixed set of + /// target architectures, so it is convenient for them to be represented in + /// an enum. However, it is possible to have arbitrary values for the "arch" + /// field in a target JSON file (which can be parsed when `--target` is + /// specified). This might occur, for example, for an out-of-tree codegen + /// backend that supports an architecture that rustc currently doesn't know + /// about. This variant exists as an escape hatch for such cases. + other_variant = Unknown; } impl Arch { - pub const fn desc_symbol(&self) -> Symbol { + pub fn desc_symbol(&self) -> Symbol { match self { Self::AArch64 => sym::aarch64, Self::AmdGpu => sym::amdgpu, @@ -1919,6 +1925,7 @@ impl Arch { Self::X86 => sym::x86, Self::X86_64 => sym::x86_64, Self::Xtensa => sym::xtensa, + Self::Unknown(name) => rustc_span::Symbol::intern(name), } } } @@ -3274,7 +3281,8 @@ impl Target { | Arch::PowerPC64LE | Arch::SpirV | Arch::Wasm32 - | Arch::Wasm64 => return None, + | Arch::Wasm64 + | Arch::Unknown(_) => return None, }) } diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 16c3558d535b..fd95bd062be6 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -955,7 +955,7 @@ pub struct FeatureConstraints { impl Target { pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] { - match self.arch { + match &self.arch { Arch::Arm => ARM_FEATURES, Arch::AArch64 | Arch::Arm64EC => AARCH64_FEATURES, Arch::X86 | Arch::X86_64 => X86_FEATURES, @@ -976,12 +976,13 @@ impl Target { | Arch::Msp430 | Arch::PowerPC64LE | Arch::SpirV - | Arch::Xtensa => &[], + | Arch::Xtensa + | Arch::Unknown(_) => &[], } } pub fn features_for_correct_vector_abi(&self) -> &'static [(u64, &'static str)] { - match self.arch { + match &self.arch { Arch::X86 | Arch::X86_64 => X86_FEATURES_FOR_CORRECT_VECTOR_ABI, Arch::AArch64 | Arch::Arm64EC => AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI, Arch::Arm => ARM_FEATURES_FOR_CORRECT_VECTOR_ABI, @@ -1004,12 +1005,13 @@ impl Target { | Arch::Msp430 | Arch::PowerPC64LE | Arch::SpirV - | Arch::Xtensa => &[], + | Arch::Xtensa + | Arch::Unknown(_) => &[], } } pub fn tied_target_features(&self) -> &'static [&'static [&'static str]] { - match self.arch { + match &self.arch { Arch::AArch64 | Arch::Arm64EC => AARCH64_TIED_FEATURES, _ => &[], } @@ -1050,7 +1052,7 @@ impl Target { // defined by target features. When that is the case, those target features must be // "forbidden" in the list above to ensure that there is a consistent answer to the // questions "which ABI is used". - match self.arch { + match &self.arch { Arch::X86 => { // We use our own ABI indicator here; LLVM does not have anything native. // Every case should require or forbid `soft-float`! diff --git a/compiler/rustc_target/src/tests.rs b/compiler/rustc_target/src/tests.rs index a2692ea6be5e..bb17dd151b58 100644 --- a/compiler/rustc_target/src/tests.rs +++ b/compiler/rustc_target/src/tests.rs @@ -1,3 +1,4 @@ +use crate::json::ToJson; use crate::spec::Target; #[test] @@ -15,3 +16,27 @@ fn report_unused_fields() { eprintln!("{result:#?}"); assert!(result.is_err()); } + +#[test] +fn custom_arch_propagates_from_json() { + let json = r#" + { + "llvm-target": "x86_64-unknown-none-gnu", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + "arch": "customarch", + "target-endian": "little", + "target-pointer-width": 64, + "os": "customos", + "linker-flavor": "ld.lld", + "linker": "rust-lld", + "executables": true + } + "#; + rustc_span::create_session_if_not_set_then(rustc_span::edition::DEFAULT_EDITION, |_| { + let (target, warnings) = Target::from_json(json).expect("json target parses"); + assert!(warnings.warning_messages().is_empty()); + assert_eq!(target.arch.desc(), "customarch"); + let serialized = target.to_json(); + assert_eq!(serialized["arch"], "customarch"); + }); +} diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs index f85ca4cfa424..217069b8b5d9 100644 --- a/src/tools/miri/src/shims/alloc.rs +++ b/src/tools/miri/src/shims/alloc.rs @@ -20,7 +20,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `library/std/src/sys/alloc/mod.rs` (where this is called `MIN_ALIGN`) and should // be kept in sync. let os = this.tcx.sess.target.os.as_ref(); - let max_fundamental_align = match this.tcx.sess.target.arch { + let max_fundamental_align = match &this.tcx.sess.target.arch { Arch::RiscV32 if matches!(os, "espidf" | "zkvm") => 4, Arch::Xtensa if matches!(os, "espidf") => 4, Arch::X86 @@ -53,7 +53,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | Arch::Msp430 | Arch::Nvptx64 | Arch::PowerPC64LE - | Arch::SpirV) => bug!("unsupported target architecture for malloc: `{arch}`"), + | Arch::SpirV + | Arch::Unknown(_)) => bug!("unsupported target architecture for malloc: `{arch}`"), }; // The C standard only requires sufficient alignment for any *type* with size less than or // equal to the size requested. Types one can define in standard C seem to never have an alignment diff --git a/tests/ui/check-cfg/my-awesome-platform.json b/tests/ui/check-cfg/my-awesome-platform.json index 3a1f6b1a54c6..c3b3b89a08cf 100644 --- a/tests/ui/check-cfg/my-awesome-platform.json +++ b/tests/ui/check-cfg/my-awesome-platform.json @@ -1,7 +1,7 @@ { "llvm-target": "x86_64-unknown-none-gnu", "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", - "arch": "x86_64", + "arch": "tamirdarch", "target-endian": "little", "target-pointer-width": 64, "os": "ericos", diff --git a/tests/ui/check-cfg/values-target-json.rs b/tests/ui/check-cfg/values-target-json.rs index ddfcb24c640c..2912c83b58de 100644 --- a/tests/ui/check-cfg/values-target-json.rs +++ b/tests/ui/check-cfg/values-target-json.rs @@ -6,14 +6,19 @@ //@ needs-llvm-components: x86 //@ compile-flags: --crate-type=lib --check-cfg=cfg() --target={{src-base}}/check-cfg/my-awesome-platform.json -#![feature(lang_items, no_core, auto_traits)] +#![feature(lang_items, no_core, auto_traits, rustc_attrs)] #![no_core] extern crate minicore; use minicore::*; -#[cfg(target_os = "linux")] -fn target_os_linux() {} +#[rustc_builtin_macro] +macro_rules! compile_error { + () => {}; +} -#[cfg(target_os = "ericos")] -fn target_os_ericos() {} +#[cfg(not(target_os = "ericos"))] +compile_error!("target_os from target JSON not wired through"); + +#[cfg(not(target_arch = "tamirdarch"))] +compile_error!("target_arch from target JSON not wired through");