diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index f83fc29577bfb..d2507bf2e6dcd 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1396,17 +1396,22 @@ impl<'hir> LoweringContext<'_, 'hir> { // features. We check that at least one type is available for // the current target. let reg_class = reg.reg_class(); - for &(_, feature) in reg_class.supported_types(asm_arch) { - if let Some(feature) = feature { - if self.sess.target_features.contains(&Symbol::intern(feature)) { - required_features.clear(); - break; - } else { - required_features.push(feature); + match reg_class.supported_types(asm_arch) { + asm::InlineAsmSupportedTypes::Any => {} + asm::InlineAsmSupportedTypes::OneOf(types) => { + for &(_, feature) in types { + if let Some(feature) = feature { + if self.sess.target_features.contains(&Symbol::intern(feature)) { + required_features.clear(); + break; + } else { + required_features.push(feature); + } + } else { + required_features.clear(); + break; + } } - } else { - required_features.clear(); - break; } } // We are sorting primitive strs here and can use unstable sort here diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 04aac780125d9..95f4d24194298 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -28,12 +28,12 @@ pub(crate) fn codegen_inline_asm<'tcx>( let mut outputs = Vec::new(); let mut new_slot = |reg_class: InlineAsmRegClass| { - let reg_size = reg_class - .supported_types(InlineAsmArch::X86_64) - .iter() - .map(|(ty, _)| ty.size()) - .max() - .unwrap(); + let reg_size = match reg_class.supported_types(InlineAsmArch::X86_64) { + InlineAsmSupportedTypes::OneOf(supported_tys) => { + supported_tys.iter().map(|(ty, _)| ty.size()).max().unwrap() + } + _ => unreachable!(), + }; let align = rustc_target::abi::Align::from_bytes(reg_size.bytes()).unwrap(); slot_size = slot_size.align_to(align); let offset = slot_size; diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs index 956be925be815..829a10900672a 100644 --- a/compiler/rustc_passes/src/intrinsicck.rs +++ b/compiler/rustc_passes/src/intrinsicck.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::lint; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::{Pointer, VariantIdx}; -use rustc_target::asm::{InlineAsmRegOrRegClass, InlineAsmType}; +use rustc_target::asm::{InlineAsmRegOrRegClass, InlineAsmSupportedTypes, InlineAsmType}; use rustc_target::spec::abi::Abi::RustIntrinsic; fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { @@ -255,10 +255,18 @@ impl ExprVisitor<'tcx> { // register class. let asm_arch = self.tcx.sess.asm_arch.unwrap(); let reg_class = reg.reg_class(); - let supported_tys = reg_class.supported_types(asm_arch); - let feature = match supported_tys.iter().find(|&&(t, _)| t == asm_ty) { - Some((_, feature)) => feature, - None => { + let found_supported_ty = match reg_class.supported_types(asm_arch) { + // FIXME(eddyb) consider skipping the "cannot use value of type" error + // above, letting the codegen backend handle non-scalar/vector types. + InlineAsmSupportedTypes::Any => Ok((asm_ty, None)), + + InlineAsmSupportedTypes::OneOf(supported_tys) => { + supported_tys.iter().find(|&&(t, _)| t == asm_ty).copied().ok_or(supported_tys) + } + }; + let feature = match found_supported_ty { + Ok((_, feature)) => feature, + Err(supported_tys) => { let msg = &format!("type `{}` cannot be used with this register class", ty); let mut err = self.tcx.sess.struct_span_err(expr.span, msg); let supported_tys: Vec<_> = diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index e7c9edea7653a..de9b8187f1f6a 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -1,4 +1,4 @@ -use super::{InlineAsmArch, InlineAsmType}; +use super::{InlineAsmArch, InlineAsmSupportedTypes, InlineAsmType}; use rustc_macros::HashStable_Generic; use std::fmt; @@ -50,10 +50,7 @@ impl AArch64InlineAsmRegClass { } } - pub fn supported_types( - self, - _arch: InlineAsmArch, - ) -> &'static [(InlineAsmType, Option<&'static str>)] { + pub fn supported_types(self, _arch: InlineAsmArch) -> InlineAsmSupportedTypes { match self { Self::reg => types! { _: I8, I16, I32, I64, F32, F64; }, Self::vreg | Self::vreg_low16 => types! { diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 28000916e0c30..0520a1744907d 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -1,4 +1,4 @@ -use super::{InlineAsmArch, InlineAsmType}; +use super::{InlineAsmArch, InlineAsmSupportedTypes, InlineAsmType}; use crate::spec::Target; use rustc_macros::HashStable_Generic; use std::fmt; @@ -42,10 +42,7 @@ impl ArmInlineAsmRegClass { None } - pub fn supported_types( - self, - _arch: InlineAsmArch, - ) -> &'static [(InlineAsmType, Option<&'static str>)] { + pub fn supported_types(self, _arch: InlineAsmArch) -> InlineAsmSupportedTypes { match self { Self::reg | Self::reg_thumb => types! { _: I8, I16, I32, F32; }, Self::sreg | Self::sreg_low16 => types! { "vfp2": I32, F32; }, diff --git a/compiler/rustc_target/src/asm/hexagon.rs b/compiler/rustc_target/src/asm/hexagon.rs index d41941d0b4cd7..a5e541433620e 100644 --- a/compiler/rustc_target/src/asm/hexagon.rs +++ b/compiler/rustc_target/src/asm/hexagon.rs @@ -1,4 +1,4 @@ -use super::{InlineAsmArch, InlineAsmType}; +use super::{InlineAsmArch, InlineAsmSupportedTypes, InlineAsmType}; use rustc_macros::HashStable_Generic; use std::fmt; @@ -29,10 +29,7 @@ impl HexagonInlineAsmRegClass { None } - pub fn supported_types( - self, - _arch: InlineAsmArch, - ) -> &'static [(InlineAsmType, Option<&'static str>)] { + pub fn supported_types(self, _arch: InlineAsmArch) -> InlineAsmSupportedTypes { match self { Self::reg => types! { _: I8, I16, I32, F32; }, } diff --git a/compiler/rustc_target/src/asm/mips.rs b/compiler/rustc_target/src/asm/mips.rs index b19489aa439bf..38e1b85b52272 100644 --- a/compiler/rustc_target/src/asm/mips.rs +++ b/compiler/rustc_target/src/asm/mips.rs @@ -1,4 +1,4 @@ -use super::{InlineAsmArch, InlineAsmType}; +use super::{InlineAsmArch, InlineAsmSupportedTypes, InlineAsmType}; use rustc_macros::HashStable_Generic; use std::fmt; @@ -30,10 +30,7 @@ impl MipsInlineAsmRegClass { None } - pub fn supported_types( - self, - arch: InlineAsmArch, - ) -> &'static [(InlineAsmType, Option<&'static str>)] { + pub fn supported_types(self, arch: InlineAsmArch) -> InlineAsmSupportedTypes { match (self, arch) { (Self::reg, InlineAsmArch::Mips64) => types! { _: I8, I16, I32, I64, F32, F64; }, (Self::reg, _) => types! { _: I8, I16, I32, F32; }, diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 5ebd6c4a2349f..ab8301424b957 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -137,14 +137,14 @@ macro_rules! types { ) => { { use super::InlineAsmType::*; - &[ + super::InlineAsmSupportedTypes::OneOf(&[ $($( ($ty, None), )*)? $($( ($ty2, Some($feature)), )*)* - ] + ]) } }; } @@ -389,12 +389,10 @@ impl InlineAsmRegClass { } } - /// Returns a list of supported types for this register class, each with a - /// options target feature required to use this type. - pub fn supported_types( - self, - arch: InlineAsmArch, - ) -> &'static [(InlineAsmType, Option<&'static str>)] { + /// Returns either `InlineAsmSupportedTypes::OneOf`, containing a list of + /// supported types for this register class, each with an optional target + /// feature required to use that type, or `InlineAsmSupportedTypes::Any`. + pub fn supported_types(self, arch: InlineAsmArch) -> InlineAsmSupportedTypes { match self { Self::X86(r) => r.supported_types(arch), Self::Arm(r) => r.supported_types(arch), @@ -473,6 +471,17 @@ impl fmt::Display for InlineAsmRegOrRegClass { } } +/// Type constrains for a particular register class. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum InlineAsmSupportedTypes { + /// Any type is allowed. + Any, + + /// Only the listed types are supported, and each is paired with + /// an optional target feature required to use that type. + OneOf(&'static [(InlineAsmType, Option<&'static str>)]), +} + /// Set of types which can be used with a particular register class. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum InlineAsmType { diff --git a/compiler/rustc_target/src/asm/nvptx.rs b/compiler/rustc_target/src/asm/nvptx.rs index 43d16ae0f5d10..8f1083270bf2a 100644 --- a/compiler/rustc_target/src/asm/nvptx.rs +++ b/compiler/rustc_target/src/asm/nvptx.rs @@ -1,4 +1,4 @@ -use super::{InlineAsmArch, InlineAsmType}; +use super::{InlineAsmArch, InlineAsmSupportedTypes, InlineAsmType}; use rustc_macros::HashStable_Generic; def_reg_class! { @@ -30,10 +30,7 @@ impl NvptxInlineAsmRegClass { None } - pub fn supported_types( - self, - _arch: InlineAsmArch, - ) -> &'static [(InlineAsmType, Option<&'static str>)] { + pub fn supported_types(self, _arch: InlineAsmArch) -> InlineAsmSupportedTypes { match self { Self::reg16 => types! { _: I8, I16; }, Self::reg32 => types! { _: I8, I16, I32, F32; }, diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs index ced7483b00571..e40dd34280264 100644 --- a/compiler/rustc_target/src/asm/riscv.rs +++ b/compiler/rustc_target/src/asm/riscv.rs @@ -1,4 +1,4 @@ -use super::{InlineAsmArch, InlineAsmType}; +use super::{InlineAsmArch, InlineAsmSupportedTypes, InlineAsmType}; use crate::spec::Target; use rustc_macros::HashStable_Generic; use std::fmt; @@ -31,10 +31,7 @@ impl RiscVInlineAsmRegClass { None } - pub fn supported_types( - self, - arch: InlineAsmArch, - ) -> &'static [(InlineAsmType, Option<&'static str>)] { + pub fn supported_types(self, arch: InlineAsmArch) -> InlineAsmSupportedTypes { match self { Self::reg => { if arch == InlineAsmArch::RiscV64 { diff --git a/compiler/rustc_target/src/asm/spirv.rs b/compiler/rustc_target/src/asm/spirv.rs index da82749e96a16..78771c018f059 100644 --- a/compiler/rustc_target/src/asm/spirv.rs +++ b/compiler/rustc_target/src/asm/spirv.rs @@ -1,4 +1,4 @@ -use super::{InlineAsmArch, InlineAsmType}; +use super::{InlineAsmArch, InlineAsmSupportedTypes, InlineAsmType}; use rustc_macros::HashStable_Generic; def_reg_class! { @@ -28,15 +28,8 @@ impl SpirVInlineAsmRegClass { None } - pub fn supported_types( - self, - _arch: InlineAsmArch, - ) -> &'static [(InlineAsmType, Option<&'static str>)] { - match self { - Self::reg => { - types! { _: I8, I16, I32, I64, F32, F64; } - } - } + pub fn supported_types(self, _arch: InlineAsmArch) -> InlineAsmSupportedTypes { + InlineAsmSupportedTypes::Any } } diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs index 0f62c19e1a3cd..fb894f87832af 100644 --- a/compiler/rustc_target/src/asm/x86.rs +++ b/compiler/rustc_target/src/asm/x86.rs @@ -1,4 +1,4 @@ -use super::{InlineAsmArch, InlineAsmType}; +use super::{InlineAsmArch, InlineAsmSupportedTypes, InlineAsmType}; use crate::spec::Target; use rustc_macros::HashStable_Generic; use std::fmt; @@ -93,10 +93,7 @@ impl X86InlineAsmRegClass { } } - pub fn supported_types( - self, - arch: InlineAsmArch, - ) -> &'static [(InlineAsmType, Option<&'static str>)] { + pub fn supported_types(self, arch: InlineAsmArch) -> InlineAsmSupportedTypes { match self { Self::reg | Self::reg_abcd => { if arch == InlineAsmArch::X86_64 {