diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index d4d64cb3fbaf2..cd2b06cc1defb 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -443,11 +443,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { .supported_types(self.arch, true) .iter() .map(|(ty, _)| ty.size()) + .filter_map(InlineAsmSize::fixed_size_bytes) .max() - .unwrap(); - let align = rustc_abi::Align::from_bytes(reg_size.bytes()).unwrap(); + .expect("expected fixed-size type"); + let align = rustc_abi::Align::from_bytes(reg_size).unwrap(); let offset = slot_size.align_to(align); - *slot_size = offset + reg_size; + *slot_size = offset + rustc_abi::Size::from_bytes(reg_size); offset }; let mut new_slot = |x| new_slot_fn(&mut slot_size, x); diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index ee0cef350b42f..99cf9fd5c61d5 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -692,7 +692,9 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r", InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w", InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64( + AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(AmdgpuInlineAsmRegClass::Sgpr(_)) => "Sg", @@ -804,7 +806,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { cx.type_vector(cx.type_i64(), 2) } - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64( + AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(_) => cx.type_i32(), @@ -1048,7 +1052,9 @@ fn modifier_to_gcc( | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { if modifier == Some('v') { None } else { modifier } } - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64( + AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(_) => None, diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 31701acd7bf78..fa544fc8817e2 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -711,18 +711,25 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> format!("{{{}{}}}", class, idx) } } else if let Some(idx) = a64_vreg_index(reg) { - let class = if let Some(layout) = layout { - match layout.size.bytes() { + let class = match layout { + Some(layout) + if matches!( + layout.backend_repr, + BackendRepr::SimdScalableVector { .. } + ) => + { + 'z' + } + Some(layout) => match layout.size.bytes() { 16 => 'q', 8 => 'd', 4 => 's', 2 => 'h', 1 => 'd', // We fixup i8 to i8x8 _ => unreachable!(), - } - } else { + }, // We use i64x2 as the type for discarded outputs - 'q' + None => 'q', }; format!("{{{}{}}}", class, idx) } else if let Some(idx) = hexagon_reg_pair_index(reg) { @@ -744,7 +751,10 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> AArch64(AArch64InlineAsmRegClass::reg) => "r", AArch64(AArch64InlineAsmRegClass::vreg) => "w", AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", - AArch64(AArch64InlineAsmRegClass::preg) => unreachable!("clobber-only"), + // Although the above link suggests its just 'Upa', llvm's own tests seem to suggest its + // '@3Upa'. (see "src/llvm-project/clang/test/CodeGen/AArch64/sve-inline-asm-datatypes.c" line 139) + AArch64(AArch64InlineAsmRegClass::preg) => "@3Upa", + AArch64(AArch64InlineAsmRegClass::ffr) => unreachable!("clobber-only"), Arm(ArmInlineAsmRegClass::reg) => "r", Arm(ArmInlineAsmRegClass::sreg) | Arm(ArmInlineAsmRegClass::dreg_low16) @@ -852,7 +862,7 @@ fn modifier_to_llvm( modifier } } - AArch64(AArch64InlineAsmRegClass::preg) => unreachable!("clobber-only"), + AArch64(AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr) => None, Arm(ArmInlineAsmRegClass::reg) => None, Arm(ArmInlineAsmRegClass::sreg) | Arm(ArmInlineAsmRegClass::sreg_low16) => None, Arm(ArmInlineAsmRegClass::dreg) @@ -955,7 +965,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' AArch64(AArch64InlineAsmRegClass::vreg) | AArch64(AArch64InlineAsmRegClass::vreg_low16) => { cx.type_vector(cx.type_i64(), 2) } - AArch64(AArch64InlineAsmRegClass::preg) => unreachable!("clobber-only"), + AArch64(AArch64InlineAsmRegClass::preg) => cx.type_scalable_vector(cx.type_i1(), 16), + AArch64(AArch64InlineAsmRegClass::ffr) => unreachable!("clobber-only"), Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(), Arm(ArmInlineAsmRegClass::sreg) | Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(), Arm(ArmInlineAsmRegClass::dreg) diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index cfe64fce180e9..7604464f9cf81 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -13,7 +13,8 @@ use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use rustc_target::asm::{ - InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType, ModifierInfo, + InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmSize, InlineAsmType, + ModifierInfo, }; use rustc_trait_selection::infer::InferCtxtExt; @@ -158,6 +159,28 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { _ => Err(NonAsmTypeReason::InvalidElement(field.did, ty)), } } + ty::Adt(adt, _args) if adt.repr().scalable() => { + let (_element_count, elem_ty, _number_of_vectors) = + ty.scalable_vector_parts(self.tcx()).unwrap(); + + match elem_ty.kind() { + ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Ok(InlineAsmType::SveVecI8), + ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Ok(InlineAsmType::SveVecI16), + ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Ok(InlineAsmType::SveVecI32), + ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Ok(InlineAsmType::SveVecI64), + ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Ok(InlineAsmType::SveVecI128), + ty::Float(FloatTy::F16) => Ok(InlineAsmType::SveVecF16), + ty::Float(FloatTy::F32) => Ok(InlineAsmType::SveVecF32), + ty::Float(FloatTy::F64) => Ok(InlineAsmType::SveVecF64), + ty::Float(FloatTy::F128) => Ok(InlineAsmType::SveVecF128), + ty::Bool => Ok(InlineAsmType::SveVecBool), + _ => { + let fields = &adt.non_enum_variant().fields; + let field = &fields[FieldIdx::ZERO]; + Err(NonAsmTypeReason::InvalidElement(field.did, ty)) + } + } + } ty::Infer(_) => bug!("unexpected infer ty in asm operand"), _ => Err(NonAsmTypeReason::Invalid(ty)), } @@ -177,10 +200,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { idx: usize, suggested_modifier: char, suggested_result: &'a str, - suggested_size: u16, + suggested_size: InlineAsmSize, default_modifier: char, default_result: &'a str, - default_size: u16, + default_size: InlineAsmSize, } impl<'a, 'b> Diagnostic<'a, ()> for FormattingSubRegisterArg<'b> { @@ -195,13 +218,24 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { default_result, default_size, } = self; + + fn format_size(size: InlineAsmSize) -> String { + match size { + InlineAsmSize::FixedBytes(size) => format!("{size}-byte values"), + InlineAsmSize::Scalable => "scalable values".to_string(), + } + } Diag::new(dcx, level, "formatting may not be suitable for sub-register argument") .with_span_label(expr_span, "for this argument") .with_help(format!( - "use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}` (for {suggested_size}-bit values)", + "use `{{{idx}:{suggested_modifier}}}` to have the register formatted as \ + `{suggested_result}` (for {})", + format_size(suggested_size) )) .with_help(format!( - "or use `{{{idx}:{default_modifier}}}` to keep the default formatting of `{default_result}` (for {default_size}-bit values)", + "or use `{{{idx}:{default_modifier}}}` to keep the default formatting of \ + `{default_result}` (for {})", + format_size(default_size) )) } } @@ -239,8 +273,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { NonAsmTypeReason::Invalid(ty) => { let msg = format!("cannot use value of type `{ty}` for inline assembly"); self.fcx.dcx().struct_span_err(expr.span, msg).with_note( - "only integers, floats, SIMD vectors, pointers and function pointers \ - can be used as arguments for inline assembly", + "only integers, floats, SIMD vectors, scalable vectors, pointers and function \ + pointers can be used as arguments for inline assembly", ).emit(); } NonAsmTypeReason::NotSizedPtr(ty) => { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b67f0633fb772..6b1baa56587c5 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -965,6 +965,7 @@ symbols! { ffi_const, ffi_pure, ffi_returns_twice, + ffr, field, field_base, field_init_shorthand, @@ -2082,6 +2083,7 @@ symbols! { suggestion, super_let, supertrait_item_shadowing, + sve, sve_cast, sve_tuple_create2, sve_tuple_create3, diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 2db8a7ff3020d..83d249262c104 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -1,9 +1,10 @@ +use core::convert::Into; use std::fmt; use rustc_data_structures::fx::FxIndexSet; use rustc_span::{Symbol, sym}; -use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; +use super::{InlineAsmArch, InlineAsmSize, InlineAsmType, ModifierInfo}; use crate::spec::{Env, Os, RelocModel, Target}; def_reg_class! { @@ -12,6 +13,7 @@ def_reg_class! { vreg, vreg_low16, preg, + ffr, } } @@ -19,8 +21,8 @@ impl AArch64InlineAsmRegClass { pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { match self { Self::reg => &['w', 'x'], - Self::vreg | Self::vreg_low16 => &['b', 'h', 's', 'd', 'q', 'v'], - Self::preg => &[], + Self::vreg | Self::vreg_low16 => &['b', 'h', 's', 'd', 'q', 'v', 'z'], + Self::preg | Self::ffr => &[], } } @@ -30,43 +32,67 @@ impl AArch64InlineAsmRegClass { pub fn suggest_modifier(self, _arch: InlineAsmArch, ty: InlineAsmType) -> Option { match self { - Self::reg => match ty.size().bits() { - 64 => None, - _ => Some(('w', "w0", 32).into()), + Self::reg => match ty.size() { + InlineAsmSize::FixedBytes(8) => None, + _ => Some(('w', "w0", InlineAsmSize::FixedBytes(4)).into()), }, - Self::vreg | Self::vreg_low16 => match ty.size().bits() { - 8 => Some(('b', "b0", 8).into()), - 16 => Some(('h', "h0", 16).into()), - 32 => Some(('s', "s0", 32).into()), - 64 => Some(('d', "d0", 64).into()), - 128 => Some(('q', "q0", 128).into()), + Self::vreg | Self::vreg_low16 => match ty.size() { + InlineAsmSize::FixedBytes(1) => Some(('b', "b0", ty.size()).into()), + InlineAsmSize::FixedBytes(2) => Some(('h', "h0", ty.size()).into()), + InlineAsmSize::FixedBytes(4) => Some(('s', "s0", ty.size()).into()), + InlineAsmSize::FixedBytes(8) => Some(('d', "d0", ty.size()).into()), + InlineAsmSize::FixedBytes(16) => Some(('q', "q0", ty.size()).into()), + InlineAsmSize::Scalable => Some(('z', "z0", InlineAsmSize::Scalable).into()), _ => None, }, - Self::preg => None, + Self::preg | Self::ffr => None, } } pub fn default_modifier(self, _arch: InlineAsmArch) -> Option { match self { - Self::reg => Some(('x', "x0", 64).into()), - Self::vreg | Self::vreg_low16 => Some(('v', "v0", 128).into()), - Self::preg => None, + Self::reg => Some(('x', "x0", InlineAsmSize::FixedBytes(8)).into()), + Self::vreg | Self::vreg_low16 => { + Some(('v', "v0", InlineAsmSize::FixedBytes(16)).into()) + } + Self::preg | Self::ffr => None, } } pub fn supported_types( self, _arch: InlineAsmArch, + allow_experimental_reg: bool, ) -> &'static [(InlineAsmType, Option)] { match self { Self::reg => types! { _: I8, I16, I32, I64, F16, F32, F64; }, - Self::vreg | Self::vreg_low16 => types! { - neon: I8, I16, I32, I64, F16, F32, F64, F128, - VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1), - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); - // Note: When adding support for SVE vector types, they must be rejected for Arm64EC. - }, - Self::preg => &[], + Self::vreg | Self::vreg_low16 => { + if allow_experimental_reg { + types! { + neon: I8, I16, I32, I64, F16, F32, F64, F128, + VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1), + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); + sve: SveVecI8, SveVecI16, SveVecI32, SveVecI64, SveVecI128, SveVecF16, SveVecF32, + SveVecF64, SveVecI128, SveVecF128; + } + } else { + types! { + neon: I8, I16, I32, I64, F16, F32, F64, F128, + VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1), + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); + } + } + } + Self::preg => { + if allow_experimental_reg { + types! { + sve: SveVecBool; + } + } else { + &[] + } + } + Self::ffr => &[], } } } @@ -190,7 +216,7 @@ def_regs! { p13: preg = ["p13"] % restricted_for_arm64ec, p14: preg = ["p14"] % restricted_for_arm64ec, p15: preg = ["p15"] % restricted_for_arm64ec, - ffr: preg = ["ffr"] % restricted_for_arm64ec, + ffr: ffr = ["ffr"] % restricted_for_arm64ec, #error = ["x19", "w19"] => "x19 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["x29", "w29", "fp", "wfp"] => diff --git a/compiler/rustc_target/src/asm/amdgpu.rs b/compiler/rustc_target/src/asm/amdgpu.rs index 0f24ae5dea225..a344ad15bfa21 100644 --- a/compiler/rustc_target/src/asm/amdgpu.rs +++ b/compiler/rustc_target/src/asm/amdgpu.rs @@ -168,7 +168,7 @@ impl AmdgpuInlineAsmRegClass { return None; } - Some(Self::Vgpr(ty.size().bits().try_into().ok()?)) + Some(Self::Vgpr(ty.size().fixed_size_bytes().map(|byte| byte * 8)?.try_into().ok()?)) } pub fn suggest_modifier( diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 8d99035fd0db4..d18cae29e936e 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -1,7 +1,6 @@ use std::borrow::Cow; use std::fmt; -use rustc_abi::Size; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_span::Symbol; @@ -11,11 +10,11 @@ use crate::spec::{Arch, RelocModel, Target}; pub struct ModifierInfo { pub modifier: char, pub result: &'static str, - pub size: u16, + pub size: InlineAsmSize, } -impl From<(char, &'static str, u16)> for ModifierInfo { - fn from((modifier, result, size): (char, &'static str, u16)) -> Self { +impl From<(char, &'static str, InlineAsmSize)> for ModifierInfo { + fn from((modifier, result, size): (char, &'static str, InlineAsmSize)) -> Self { Self { modifier, result, size } } } @@ -649,7 +648,7 @@ impl InlineAsmRegClass { match self { Self::X86(r) => r.supported_types(arch, allow_experimental_reg).into(), Self::Arm(r) => r.supported_types(arch).into(), - Self::AArch64(r) => r.supported_types(arch).into(), + Self::AArch64(r) => r.supported_types(arch, allow_experimental_reg).into(), Self::Amdgpu(r) => r.supported_types(arch).into(), Self::RiscV(r) => r.supported_types(arch).into(), Self::Nvptx(r) => r.supported_types(arch).into(), @@ -796,6 +795,31 @@ pub enum InlineAsmType { VecF32(u64), VecF64(u64), VecF128(u64), + SveVecI8, + SveVecI16, + SveVecI32, + SveVecI64, + SveVecI128, + SveVecF16, + SveVecF32, + SveVecF64, + SveVecF128, + SveVecBool, +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum InlineAsmSize { + FixedBytes(u64), + Scalable, +} + +impl InlineAsmSize { + pub fn fixed_size_bytes(self) -> Option { + match self { + Self::FixedBytes(size) => Some(size), + Self::Scalable => None, + } + } } impl InlineAsmType { @@ -803,27 +827,29 @@ impl InlineAsmType { matches!(self, Self::I8 | Self::I16 | Self::I32 | Self::I64 | Self::I128) } - pub fn size(self) -> Size { - Size::from_bytes(match self { - Self::I8 => 1, - Self::I16 => 2, - Self::I32 => 4, - Self::I64 => 8, - Self::I128 => 16, - Self::F16 => 2, - Self::F32 => 4, - Self::F64 => 8, - Self::F128 => 16, - Self::VecI8(n) => n * 1, - Self::VecI16(n) => n * 2, - Self::VecI32(n) => n * 4, - Self::VecI64(n) => n * 8, - Self::VecI128(n) => n * 16, - Self::VecF16(n) => n * 2, - Self::VecF32(n) => n * 4, - Self::VecF64(n) => n * 8, - Self::VecF128(n) => n * 16, - }) + pub fn size(self) -> InlineAsmSize { + match self { + Self::I8 => InlineAsmSize::FixedBytes(1), + Self::I16 | Self::F16 => InlineAsmSize::FixedBytes(2), + Self::I32 | Self::F32 => InlineAsmSize::FixedBytes(4), + Self::I64 | Self::F64 => InlineAsmSize::FixedBytes(8), + Self::I128 | Self::F128 => InlineAsmSize::FixedBytes(16), + Self::VecI8(n) => InlineAsmSize::FixedBytes(n), + Self::VecI16(n) | Self::VecF16(n) => InlineAsmSize::FixedBytes(n * 2), + Self::VecI32(n) | Self::VecF32(n) => InlineAsmSize::FixedBytes(n * 4), + Self::VecI64(n) | Self::VecF64(n) => InlineAsmSize::FixedBytes(n * 8), + Self::VecI128(n) | Self::VecF128(n) => InlineAsmSize::FixedBytes(n * 16), + Self::SveVecI8 + | Self::SveVecI16 + | Self::SveVecI32 + | Self::SveVecI64 + | Self::SveVecI128 + | Self::SveVecF16 + | Self::SveVecF32 + | Self::SveVecF64 + | Self::SveVecF128 + | Self::SveVecBool => InlineAsmSize::Scalable, + } } } @@ -848,6 +874,16 @@ impl fmt::Display for InlineAsmType { Self::VecF32(n) => write!(f, "f32x{n}"), Self::VecF64(n) => write!(f, "f64x{n}"), Self::VecF128(n) => write!(f, "f128x{n}"), + Self::SveVecI8 => f.write_str("svint8_t"), + Self::SveVecI16 => f.write_str("svint16_t"), + Self::SveVecI32 => f.write_str("svint32_t"), + Self::SveVecI64 => f.write_str("svint64_t"), + Self::SveVecI128 => f.write_str("svint128_t"), + Self::SveVecF16 => f.write_str("svfloat26_t"), + Self::SveVecF32 => f.write_str("svfloat32_t"), + Self::SveVecF64 => f.write_str("svfloat64_t"), + Self::SveVecF128 => f.write_str("svfloat128_t"), + Self::SveVecBool => f.write_str("svbool_t"), } } } diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs index c582c06d8f4bb..a4775db7e79f8 100644 --- a/compiler/rustc_target/src/asm/x86.rs +++ b/compiler/rustc_target/src/asm/x86.rs @@ -3,7 +3,7 @@ use std::fmt; use rustc_data_structures::fx::FxIndexSet; use rustc_span::Symbol; -use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; +use super::{InlineAsmArch, InlineAsmSize, InlineAsmType, ModifierInfo}; use crate::spec::{RelocModel, Target}; def_reg_class! { @@ -49,33 +49,45 @@ impl X86InlineAsmRegClass { pub fn suggest_class(self, _arch: InlineAsmArch, ty: InlineAsmType) -> Option { match self { - Self::reg | Self::reg_abcd if ty.size().bits() == 8 => Some(Self::reg_byte), + Self::reg | Self::reg_abcd if ty.size() == InlineAsmSize::FixedBytes(1) => { + Some(Self::reg_byte) + } _ => None, } } pub fn suggest_modifier(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option { match self { - Self::reg => match ty.size().bits() { - 16 => Some(('x', "ax", 16).into()), - 32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax", 32).into()), + Self::reg => match ty.size() { + InlineAsmSize::FixedBytes(2) => { + Some(('x', "ax", InlineAsmSize::FixedBytes(2)).into()) + } + InlineAsmSize::FixedBytes(4) if arch == InlineAsmArch::X86_64 => { + Some(('e', "eax", InlineAsmSize::FixedBytes(4)).into()) + } _ => None, }, - Self::reg_abcd => match ty.size().bits() { - 16 => Some(('x', "ax", 16).into()), - 32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax", 32).into()), + Self::reg_abcd => match ty.size() { + InlineAsmSize::FixedBytes(2) => { + Some(('x', "ax", InlineAsmSize::FixedBytes(2)).into()) + } + InlineAsmSize::FixedBytes(4) if arch == InlineAsmArch::X86_64 => { + Some(('e', "eax", InlineAsmSize::FixedBytes(4)).into()) + } _ => None, }, Self::reg_byte => None, Self::xmm_reg => None, - Self::ymm_reg => match ty.size().bits() { - 256 => None, - _ => Some(('x', "xmm0", 128).into()), + Self::ymm_reg => match ty.size() { + InlineAsmSize::FixedBytes(32) => None, + _ => Some(('x', "xmm0", InlineAsmSize::FixedBytes(16)).into()), }, - Self::zmm_reg => match ty.size().bits() { - 512 => None, - 256 => Some(('y', "ymm0", 256).into()), - _ => Some(('x', "xmm0", 128).into()), + Self::zmm_reg => match ty.size() { + InlineAsmSize::FixedBytes(64) => None, + InlineAsmSize::FixedBytes(32) => { + Some(('y', "ymm0", InlineAsmSize::FixedBytes(32)).into()) + } + _ => Some(('x', "xmm0", InlineAsmSize::FixedBytes(16)).into()), }, Self::kreg | Self::kreg0 => None, Self::mmx_reg | Self::x87_reg => None, @@ -87,15 +99,15 @@ impl X86InlineAsmRegClass { match self { Self::reg | Self::reg_abcd => { if arch == InlineAsmArch::X86_64 { - Some(('r', "rax", 64).into()) + Some(('r', "rax", InlineAsmSize::FixedBytes(8)).into()) } else { - Some(('e', "eax", 32).into()) + Some(('e', "eax", InlineAsmSize::FixedBytes(4)).into()) } } Self::reg_byte => None, - Self::xmm_reg => Some(('x', "xmm0", 128).into()), - Self::ymm_reg => Some(('y', "ymm0", 256).into()), - Self::zmm_reg => Some(('z', "zmm0", 512).into()), + Self::xmm_reg => Some(('x', "xmm0", InlineAsmSize::FixedBytes(16)).into()), + Self::ymm_reg => Some(('y', "ymm0", InlineAsmSize::FixedBytes(32)).into()), + Self::zmm_reg => Some(('z', "zmm0", InlineAsmSize::FixedBytes(64)).into()), Self::kreg | Self::kreg0 => None, Self::mmx_reg | Self::x87_reg => None, Self::tmm_reg => None, diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-reg.md b/src/doc/unstable-book/src/language-features/asm-experimental-reg.md index db72c44a2dc92..87acb45a1b280 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-reg.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-reg.md @@ -14,6 +14,7 @@ This tracks support for additional registers in architectures where inline assem | ------------ | -------------- | --------- | -------------------- | | LoongArch | `vreg` | `$vr[0-31]` | `f` | | LoongArch | `xreg` | `$xr[0-31]` | `f` | +| AArch64 | `preg` | `p[0-16]` | `Upa` | ## Register class supported types @@ -21,6 +22,8 @@ This tracks support for additional registers in architectures where inline assem | ------------ | -------------- | -------------- | ------------- | | LoongArch | `vreg` | `lsx` | `f32`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | | LoongArch | `xreg` | `lasx` | `f32`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`,
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` | +| AArch64 | `vreg` | `sve` | `i8xN`, `i16xB`, `i32xN`, `i64xN`, `f16xN`, `f32xN`, `f64xN` (scalable vector) | +| AArch64 | `preg` | `sve` | `i1xN` (scalable vector predicate) | ## Register aliases @@ -45,3 +48,4 @@ This tracks support for additional registers in architectures where inline assem | LoongArch | `vreg` | `u` | `$xr0` | `u` | | LoongArch | `xreg` | None | `$xr0` | `u` | | LoongArch | `xreg` | `w` | `$vr0` | `w` | +| AArch64 | `vreg` | `z` | `z0` | `z` | diff --git a/tests/assembly-llvm/asm/aarch64-modifiers.rs b/tests/assembly-llvm/asm/aarch64-modifiers.rs index 6cb028461ddd1..66be35de574f6 100644 --- a/tests/assembly-llvm/asm/aarch64-modifiers.rs +++ b/tests/assembly-llvm/asm/aarch64-modifiers.rs @@ -1,7 +1,7 @@ //@ add-minicore //@ assembly-output: emit-asm //@ compile-flags: -Copt-level=3 -C panic=abort -//@ compile-flags: --target aarch64-unknown-linux-gnu +//@ compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+sve //@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: aarch64 @@ -85,6 +85,12 @@ check!(vreg_q vreg "ldr {:q}, [x0]"); // CHECK: //NO_APP check!(vreg_v vreg "add {0:v}.4s, {0:v}.4s, {0:v}.4s"); +// CHECK-LABEL: vreg_z: +// CHECK: //APP +// CHECK: mov z0.d, z0.d +// CHECK: //NO_APP +check!(vreg_z vreg "mov {0:z}.d, {0:z}.d"); + // CHECK-LABEL: vreg_low16: // CHECK: //APP // CHECK: add v0.4s, v0.4s, v0.4s diff --git a/tests/assembly-llvm/asm/aarch64-types.rs b/tests/assembly-llvm/asm/aarch64-types.rs index c171ba3b11e13..da625b1211602 100644 --- a/tests/assembly-llvm/asm/aarch64-types.rs +++ b/tests/assembly-llvm/asm/aarch64-types.rs @@ -1,7 +1,7 @@ //@ add-minicore //@ revisions: aarch64 aarch64_be arm64ec //@ assembly-output: emit-asm -//@ [aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@ [aarch64] compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+sve //@ [aarch64] needs-llvm-components: aarch64 //@ [aarch64_be] compile-flags: --target aarch64_be-unknown-linux-gnu //@ [aarch64_be] needs-llvm-components: aarch64 @@ -9,7 +9,7 @@ //@ [arm64ec] needs-llvm-components: aarch64 //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, f16, f128)] +#![feature(asm_experimental_reg, no_core, f16, f128, rustc_attrs)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] @@ -20,6 +20,62 @@ use minicore::*; type ptr = *mut u8; +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(16)] +pub struct svint8_t(i8); + +#[cfg(target_feature = "sve")] +impl Copy for svint8_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(8)] +pub struct svint16_t(i16); + +#[cfg(target_feature = "sve")] +impl Copy for svint16_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(4)] +pub struct svint32_t(i32); + +#[cfg(target_feature = "sve")] +impl Copy for svint32_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(2)] +pub struct svint64_t(i64); + +#[cfg(target_feature = "sve")] +impl Copy for svint64_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(8)] +pub struct svfloat16_t(f16); + +#[cfg(target_feature = "sve")] +impl Copy for svfloat16_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(4)] +pub struct svfloat32_t(f32); + +#[cfg(target_feature = "sve")] +impl Copy for svfloat32_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(2)] +pub struct svfloat64_t(f64); + +#[cfg(target_feature = "sve")] +impl Copy for svfloat64_t {} + +#[cfg(target_feature = "sve")] +#[rustc_scalable_vector(16)] +pub struct svbool_t(bool); + +#[cfg(target_feature = "sve")] +impl Copy for svbool_t {} + extern "C" { fn extern_func(); static extern_static: u8; @@ -74,6 +130,25 @@ macro_rules! check { }; } +macro_rules! check_sve { + ($func:ident $ty:ident $class:ident $suffix:literal $zm:literal) => { + #[cfg(target_feature = "sve")] + #[no_mangle] + pub unsafe fn $func(inp: &$ty, pred: &svbool_t) -> $ty { + let x = *inp; + let z = *pred; + let y; + asm!( + concat!("mov {0}.", $suffix, ", p0/", $zm, ", {1}.", $suffix), + out($class) y, + in($class) x, + in("p0") z + ); + y + } + }; +} + macro_rules! check_reg { ($func:ident $ty:ident $reg:tt $mov:literal) => { // FIXME(f128): See FIXME in `check!` @@ -87,6 +162,25 @@ macro_rules! check_reg { }; } +macro_rules! check_reg_sve { + ($func:ident $ty:ident $reg:tt $suffix:literal $zm:literal) => { + #[cfg(target_feature = "sve")] + #[no_mangle] + pub unsafe fn $func(inp: &$ty, pred: &svbool_t) -> $ty { + let x = *inp; + let z = *pred; + let y; + asm!( + concat!("mov ", $reg, ".", $suffix, ", p0/", $zm, ", ", $reg, ".", $suffix), + in("p0") z, + lateout($reg) y, + in($reg) x + ); + y + } + }; +} + // CHECK-LABEL: {{("#)?}}reg_i8{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} @@ -405,6 +499,96 @@ check!(vreg_low16_f32x4 f32x4 vreg_low16 "fmov" "s"); // CHECK: //NO_APP check!(vreg_low16_f64x2 f64x2 vreg_low16 "fmov" "s"); +// aarch64-LABEL: {{("#)?}}vreg_sve_i8{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.b, p0/m, z{{[0-9]+}}.b +// aarch64: //NO_APP +check_sve!(vreg_sve_i8 svint8_t vreg "b" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_i16{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.h, p0/m, z{{[0-9]+}}.h +// aarch64: //NO_APP +check_sve!(vreg_sve_i16 svint16_t vreg "h" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_f16{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.h, p0/m, z{{[0-9]+}}.h +// aarch64: //NO_APP +check_sve!(vreg_sve_f16 svfloat16_t vreg "h" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_i32{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.s, p0/m, z{{[0-9]+}}.s +// aarch64: //NO_APP +check_sve!(vreg_sve_i32 svint32_t vreg "s" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_f32{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.s, p0/m, z{{[0-9]+}}.s +// aarch64: //NO_APP +check_sve!(vreg_sve_f32 svfloat32_t vreg "s" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_i64{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.d, p0/m, z{{[0-9]+}}.d +// aarch64: //NO_APP +check_sve!(vreg_sve_i64 svint64_t vreg "d" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_sve_f64{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.d, p0/m, z{{[0-9]+}}.d +// aarch64: //NO_APP +check_sve!(vreg_sve_f64 svfloat64_t vreg "d" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_i8{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.b, p0/m, z{{[0-9]+}}.b +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_i8 svint8_t vreg_low16 "b" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_i16{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.h, p0/m, z{{[0-9]+}}.h +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_i16 svint16_t vreg_low16 "h" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_f16{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.h, p0/m, z{{[0-9]+}}.h +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_f16 svfloat16_t vreg_low16 "h" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_i32{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.s, p0/m, z{{[0-9]+}}.s +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_i32 svint32_t vreg_low16 "s" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_f32{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.s, p0/m, z{{[0-9]+}}.s +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_f32 svfloat32_t vreg_low16 "s" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_i64{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.d, p0/m, z{{[0-9]+}}.d +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_i64 svint64_t vreg_low16 "d" "m"); + +// aarch64-LABEL: {{("#)?}}vreg_low16_sve_f64{{"?}} +// aarch64: //APP +// aarch64: mov z{{[0-9]+}}.d, p0/m, z{{[0-9]+}}.d +// aarch64: //NO_APP +check_sve!(vreg_low16_sve_f64 svfloat64_t vreg_low16 "d" "m"); + +// aarch64-LABEL: {{("#)?}}preg_bool{{"?}} +// aarch64: //APP +// aarch64: mov p{{[0-9]+}}.b, p0/z, p{{[0-9]+}}.b +// aarch64: //NO_APP +check_sve!(preg_bool svbool_t preg "b" "z"); + // CHECK-LABEL: {{("#)?}}x0_i8{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} @@ -501,6 +685,62 @@ check_reg!(v0_f64 f64 "s0" "fmov"); // CHECK: //NO_APP check_reg!(v0_f128 f128 "s0" "fmov"); +// aarch64-LABEL: {{("#)?}}z0_i8{{"?}} +// aarch64: //APP +// aarch64: mov z0.b, p0/m, z0.b +// aarch64: //NO_APP +check_reg_sve!(z0_i8 svint8_t "z0" "b" "m"); + +// aarch64-LABEL: {{("#)?}}z0_i16{{"?}} +// aarch64: //APP +// aarch64: mov z0.h, p0/m, z0.h +// aarch64: //NO_APP +check_reg_sve!(z0_i16 svint16_t "z0" "h" "m"); + +// aarch64-LABEL: {{("#)?}}z0_f16{{"?}} +// aarch64: //APP +// aarch64: mov z0.h, p0/m, z0.h +// aarch64: //NO_APP +check_reg_sve!(z0_f16 svfloat16_t "z0" "h" "m"); + +// aarch64-LABEL: {{("#)?}}z0_i32{{"?}} +// aarch64: //APP +// aarch64: mov z0.s, p0/m, z0.s +// aarch64: //NO_APP +check_reg_sve!(z0_i32 svint32_t "z0" "s" "m"); + +// aarch64-LABEL: {{("#)?}}z0_f32{{"?}} +// aarch64: //APP +// aarch64: mov z0.s, p0/m, z0.s +// aarch64: //NO_APP +check_reg_sve!(z0_f32 svfloat32_t "z0" "s" "m"); + +// aarch64-LABEL: {{("#)?}}z0_i64{{"?}} +// aarch64: //APP +// aarch64: mov z0.d, p0/m, z0.d +// aarch64: //NO_APP +check_reg_sve!(z0_i64 svint64_t "z0" "d" "m"); + +// aarch64-LABEL: {{("#)?}}z0_f64{{"?}} +// aarch64: //APP +// aarch64: mov z0.d, p0/m, z0.d +// aarch64: //NO_APP +check_reg_sve!(z0_f64 svfloat64_t "z0" "d" "m"); + +// aarch64-LABEL: {{("#)?}}p0_bool{{"?}} +// aarch64: //APP +// aarch64: mov p0.b, p1/z, p0.b +// aarch64: //NO_APP +#[cfg(target_feature = "sve")] +#[no_mangle] +pub unsafe fn p0_bool(inp: &svbool_t, pred: &svbool_t) -> svbool_t { + let x = *inp; + let z = *pred; + let y; + asm!("mov p0.b, p1/z, p0.b", in("p1") z, lateout("p0") y, in("p0") x); + y +} + // CHECK-LABEL: {{("#)?}}v0_ptr{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 diff --git a/tests/ui/asm/aarch64/aarch64-sve.rs b/tests/ui/asm/aarch64/aarch64-sve.rs index a146d73345554..daa4ab98dee75 100644 --- a/tests/ui/asm/aarch64/aarch64-sve.rs +++ b/tests/ui/asm/aarch64/aarch64-sve.rs @@ -15,6 +15,7 @@ use minicore::*; fn f(x: f64) { unsafe { asm!("", out("p0") _); + asm!("", out("z0") _); asm!("", out("ffr") _); } } diff --git a/tests/ui/asm/aarch64/bad-reg.rs b/tests/ui/asm/aarch64/bad-reg.rs index 39a3e386bb6e5..daaca4746cf37 100644 --- a/tests/ui/asm/aarch64/bad-reg.rs +++ b/tests/ui/asm/aarch64/bad-reg.rs @@ -1,5 +1,5 @@ //@ add-minicore -//@ compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+neon +//@ compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+neon,+sve //@ needs-llvm-components: aarch64 //@ ignore-backends: gcc #![crate_type = "lib"] @@ -38,15 +38,15 @@ fn main() { asm!("", in("x19") foo); //~^ ERROR invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm - asm!("", in("p0") foo); - //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + asm!("", in("ffr") foo); + //~^ ERROR register class `ffr` can only be used as a clobber, not as an input or output //~| ERROR type `i32` cannot be used with this register class - asm!("", out("p0") _); - asm!("{}", in(preg) foo); - //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + asm!("", out("ffr") _); + asm!("{}", in(ffr) foo); + //~^ ERROR register class `ffr` can only be used as a clobber, not as an input or output //~| ERROR type `i32` cannot be used with this register class - asm!("{}", out(preg) _); - //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + asm!("{}", out(ffr) _); + //~^ ERROR register class `ffr` can only be used as a clobber, not as an input or output // Explicit register conflicts // (except in/lateout which don't conflict) diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr index 9f3d54eb46660..8937509763dec 100644 --- a/tests/ui/asm/aarch64/bad-reg.stderr +++ b/tests/ui/asm/aarch64/bad-reg.stderr @@ -4,7 +4,7 @@ error: invalid register class `foo`: unknown register class LL | asm!("{}", in(foo) foo); | ^^^^^^^^^^^ | - = note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, and `preg` + = note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, `preg`, and `ffr` error: invalid register `foo`: unknown register --> $DIR/bad-reg.rs:20:18 @@ -30,7 +30,7 @@ LL | asm!("{:r}", in(vreg) foo); | | | template modifier | - = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v` + = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`, and `z` error: invalid asm template modifier `r` for this register class --> $DIR/bad-reg.rs:26:15 @@ -40,7 +40,7 @@ LL | asm!("{:r}", in(vreg_low16) foo); | | | template modifier | - = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v` + = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`, and `z` error: asm template modifiers are not allowed for `const` arguments --> $DIR/bad-reg.rs:28:15 @@ -82,23 +82,23 @@ error: invalid register `x19`: x19 is used internally by LLVM and cannot be used LL | asm!("", in("x19") foo); | ^^^^^^^^^^^^^ -error: register class `preg` can only be used as a clobber, not as an input or output +error: register class `ffr` can only be used as a clobber, not as an input or output --> $DIR/bad-reg.rs:41:18 | -LL | asm!("", in("p0") foo); - | ^^^^^^^^^^^^ +LL | asm!("", in("ffr") foo); + | ^^^^^^^^^^^^^ -error: register class `preg` can only be used as a clobber, not as an input or output +error: register class `ffr` can only be used as a clobber, not as an input or output --> $DIR/bad-reg.rs:45:20 | -LL | asm!("{}", in(preg) foo); - | ^^^^^^^^^^^^ +LL | asm!("{}", in(ffr) foo); + | ^^^^^^^^^^^ -error: register class `preg` can only be used as a clobber, not as an input or output +error: register class `ffr` can only be used as a clobber, not as an input or output --> $DIR/bad-reg.rs:48:20 | -LL | asm!("{}", out(preg) _); - | ^^^^^^^^^^^ +LL | asm!("{}", out(ffr) _); + | ^^^^^^^^^^ error: register `w0` conflicts with register `x0` --> $DIR/bad-reg.rs:54:32 @@ -145,20 +145,20 @@ LL | asm!("", in("v0") foo, out("q0") bar); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:41:27 + --> $DIR/bad-reg.rs:41:28 | -LL | asm!("", in("p0") foo); - | ^^^ +LL | asm!("", in("ffr") foo); + | ^^^ | - = note: register class `preg` supports these types: + = note: register class `ffr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:45:29 + --> $DIR/bad-reg.rs:45:28 | -LL | asm!("{}", in(preg) foo); - | ^^^ +LL | asm!("{}", in(ffr) foo); + | ^^^ | - = note: register class `preg` supports these types: + = note: register class `ffr` supports these types: error: aborting due to 20 previous errors diff --git a/tests/ui/asm/aarch64/type-check-2.stderr b/tests/ui/asm/aarch64/type-check-2.stderr index 2cd767db0334a..325e2c43b3035 100644 --- a/tests/ui/asm/aarch64/type-check-2.stderr +++ b/tests/ui/asm/aarch64/type-check-2.stderr @@ -12,7 +12,7 @@ error: cannot use value of type `{closure@$DIR/type-check-2.rs:32:28: 32:36}` fo LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly --> $DIR/type-check-2.rs:34:28 @@ -20,7 +20,7 @@ error: cannot use value of type `Vec` for inline assembly LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `(i32, i32, i32)` for inline assembly --> $DIR/type-check-2.rs:36:28 @@ -28,7 +28,7 @@ error: cannot use value of type `(i32, i32, i32)` for inline assembly LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly --> $DIR/type-check-2.rs:38:28 @@ -36,7 +36,7 @@ error: cannot use value of type `[i32; 3]` for inline assembly LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly --> $DIR/type-check-2.rs:46:31 @@ -44,7 +44,7 @@ error: cannot use value of type `fn() {main}` for inline assembly LL | asm!("{}", inout(reg) f); | ^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly --> $DIR/type-check-2.rs:49:31 @@ -52,7 +52,7 @@ error: cannot use value of type `&mut i32` for inline assembly LL | asm!("{}", inout(reg) r); | ^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: aborting due to 7 previous errors diff --git a/tests/ui/asm/aarch64/type-check-3.rs b/tests/ui/asm/aarch64/type-check-3.rs index 2f8439d0a0f9e..6c01a3380f169 100644 --- a/tests/ui/asm/aarch64/type-check-3.rs +++ b/tests/ui/asm/aarch64/type-check-3.rs @@ -1,9 +1,9 @@ //@ only-aarch64 -//@ compile-flags: -C target-feature=+neon +//@ compile-flags: -C target-feature=+neon,+sve -#![feature(repr_simd)] +#![feature(asm_experimental_reg, repr_simd, stdarch_aarch64_sve)] -use std::arch::aarch64::float64x2_t; +use std::arch::aarch64::{float64x2_t, svdup_n_f64, svdup_n_s16, svdup_n_s32, svptrue_b8}; use std::arch::{asm, global_asm}; #[repr(simd)] @@ -13,6 +13,10 @@ struct Simd256bit([f64; 4]); fn main() { let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) }; let f64x4 = Simd256bit([0.0, 0.0, 0.0, 0.0]); + let svi16 = unsafe { svdup_n_s16(0i16) }; + let svi32 = unsafe { svdup_n_s32(0i32) }; + let svf64 = unsafe { svdup_n_f64(0f64) }; + let svb8 = unsafe { svptrue_b8() }; unsafe { // Types must be listed in the register class. @@ -33,9 +37,12 @@ fn main() { asm!("{:d}", in(vreg) 0f64); asm!("{:q}", in(vreg) f64x2); asm!("{:v}", in(vreg) f64x2); + asm!("{:z}", in(vreg) svi32); + asm!("{}", in(preg) svb8); // Should be the same as vreg asm!("{:q}", in(vreg_low16) f64x2); + asm!("{:z}", in(vreg_low16) svi32); // Template modifiers of a different size to the argument are fine asm!("{:w}", in(reg) 0u64); @@ -62,6 +69,12 @@ fn main() { //~^ WARN formatting may not be suitable for sub-register argument asm!("{}", in(vreg_low16) 0f64); //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg) svi16); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg) svi32); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg) svf64); + //~^ WARN formatting may not be suitable for sub-register argument asm!("{0} {0}", in(reg) 0i16); //~^ WARN formatting may not be suitable for sub-register argument @@ -76,9 +89,16 @@ fn main() { //~^ ERROR type `float64x2_t` cannot be used with this register class asm!("{}", in(vreg) f64x4); //~^ ERROR type `Simd256bit` cannot be used with this register class + asm!("{}", in(reg) svi32); + //~^ ERROR type `svint32_t` cannot be used with this register class + asm!("{}", in(reg) svb8); + //~^ ERROR type `svbool_t` cannot be used with this register class + asm!("{}", in(vreg) svb8); + //~^ ERROR type `svbool_t` cannot be used with this register class + asm!("{}", in(preg) svi32); + //~^ ERROR type `svint32_t` cannot be used with this register class // Split inout operands must have compatible types - let mut val_i16: i16; let mut val_f32: f32; let mut val_u32: u32; diff --git a/tests/ui/asm/aarch64/type-check-3.stderr b/tests/ui/asm/aarch64/type-check-3.stderr index 9d84d2666b33c..e407ed3a9d3ac 100644 --- a/tests/ui/asm/aarch64/type-check-3.stderr +++ b/tests/ui/asm/aarch64/type-check-3.stderr @@ -1,96 +1,123 @@ warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:48:15 + --> $DIR/type-check-3.rs:55:15 | LL | asm!("{}", in(reg) 0u8); | ^^ --- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) = note: `#[warn(asm_sub_register)]` on by default warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:50:15 + --> $DIR/type-check-3.rs:57:15 | LL | asm!("{}", in(reg) 0u16); | ^^ ---- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:52:15 + --> $DIR/type-check-3.rs:59:15 | LL | asm!("{}", in(reg) 0i32); | ^^ ---- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:54:15 + --> $DIR/type-check-3.rs:61:15 | LL | asm!("{}", in(reg) 0f32); | ^^ ---- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:57:15 + --> $DIR/type-check-3.rs:64:15 | LL | asm!("{}", in(vreg) 0i16); | ^^ ---- for this argument | - = help: use `{0:h}` to have the register formatted as `h0` (for 16-bit values) - = help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values) + = help: use `{0:h}` to have the register formatted as `h0` (for 2-byte values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:59:15 + --> $DIR/type-check-3.rs:66:15 | LL | asm!("{}", in(vreg) 0f32); | ^^ ---- for this argument | - = help: use `{0:s}` to have the register formatted as `s0` (for 32-bit values) - = help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values) + = help: use `{0:s}` to have the register formatted as `s0` (for 4-byte values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:61:15 + --> $DIR/type-check-3.rs:68:15 | LL | asm!("{}", in(vreg) 0f64); | ^^ ---- for this argument | - = help: use `{0:d}` to have the register formatted as `d0` (for 64-bit values) - = help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values) + = help: use `{0:d}` to have the register formatted as `d0` (for 8-byte values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:63:15 + --> $DIR/type-check-3.rs:70:15 | LL | asm!("{}", in(vreg_low16) 0f64); | ^^ ---- for this argument | - = help: use `{0:d}` to have the register formatted as `d0` (for 64-bit values) - = help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values) + = help: use `{0:d}` to have the register formatted as `d0` (for 8-byte values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:66:15 + --> $DIR/type-check-3.rs:72:15 + | +LL | asm!("{}", in(vreg) svi16); + | ^^ ----- for this argument + | + = help: use `{0:z}` to have the register formatted as `z0` (for scalable values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:74:15 + | +LL | asm!("{}", in(vreg) svi32); + | ^^ ----- for this argument + | + = help: use `{0:z}` to have the register formatted as `z0` (for scalable values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:76:15 + | +LL | asm!("{}", in(vreg) svf64); + | ^^ ----- for this argument + | + = help: use `{0:z}` to have the register formatted as `z0` (for scalable values) + = help: or use `{0:v}` to keep the default formatting of `v0` (for 16-byte values) + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:79:15 | LL | asm!("{0} {0}", in(reg) 0i16); | ^^^ ^^^ ---- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) warning: formatting may not be suitable for sub-register argument - --> $DIR/type-check-3.rs:68:15 + --> $DIR/type-check-3.rs:81:15 | LL | asm!("{0} {0:x}", in(reg) 0i16); | ^^^ ---- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) error: type `i128` cannot be used with this register class - --> $DIR/type-check-3.rs:73:28 + --> $DIR/type-check-3.rs:86:28 | LL | asm!("{}", in(reg) 0i128); | ^^^^^ @@ -98,7 +125,7 @@ LL | asm!("{}", in(reg) 0i128); = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 error: type `float64x2_t` cannot be used with this register class - --> $DIR/type-check-3.rs:75:28 + --> $DIR/type-check-3.rs:88:28 | LL | asm!("{}", in(reg) f64x2); | ^^^^^ @@ -106,15 +133,47 @@ LL | asm!("{}", in(reg) f64x2); = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 error: type `Simd256bit` cannot be used with this register class - --> $DIR/type-check-3.rs:77:29 + --> $DIR/type-check-3.rs:90:29 | LL | asm!("{}", in(vreg) f64x4); | ^^^^^ | - = note: register class `vreg` supports these types: i8, i16, i32, i64, f16, f32, f64, f128, i8x8, i16x4, i32x2, i64x1, f16x4, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 + = note: register class `vreg` supports these types: i8, i16, i32, i64, f16, f32, f64, f128, i8x8, i16x4, i32x2, i64x1, f16x4, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2, svint8_t, svint16_t, svint32_t, svint64_t, svint128_t, svfloat26_t, svfloat32_t, svfloat64_t, svint128_t, svfloat128_t + +error: type `svint32_t` cannot be used with this register class + --> $DIR/type-check-3.rs:92:28 + | +LL | asm!("{}", in(reg) svi32); + | ^^^^^ + | + = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 + +error: type `svbool_t` cannot be used with this register class + --> $DIR/type-check-3.rs:94:28 + | +LL | asm!("{}", in(reg) svb8); + | ^^^^ + | + = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 + +error: type `svbool_t` cannot be used with this register class + --> $DIR/type-check-3.rs:96:29 + | +LL | asm!("{}", in(vreg) svb8); + | ^^^^ + | + = note: register class `vreg` supports these types: i8, i16, i32, i64, f16, f32, f64, f128, i8x8, i16x4, i32x2, i64x1, f16x4, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2, svint8_t, svint16_t, svint32_t, svint64_t, svint128_t, svfloat26_t, svfloat32_t, svfloat64_t, svint128_t, svfloat128_t + +error: type `svint32_t` cannot be used with this register class + --> $DIR/type-check-3.rs:98:29 + | +LL | asm!("{}", in(preg) svi32); + | ^^^^^ + | + = note: register class `preg` supports these types: svbool_t error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:88:33 + --> $DIR/type-check-3.rs:108:33 | LL | asm!("{:x}", inout(reg) 0u32 => val_f32); | ^^^^ ^^^^^^^ type `f32` @@ -124,7 +183,7 @@ LL | asm!("{:x}", inout(reg) 0u32 => val_f32); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:90:33 + --> $DIR/type-check-3.rs:110:33 | LL | asm!("{:x}", inout(reg) 0u32 => val_ptr); | ^^^^ ^^^^^^^ type `*mut u8` @@ -134,7 +193,7 @@ LL | asm!("{:x}", inout(reg) 0u32 => val_ptr); = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size error: incompatible types for asm inout argument - --> $DIR/type-check-3.rs:92:33 + --> $DIR/type-check-3.rs:112:33 | LL | asm!("{:x}", inout(reg) main => val_u32); | ^^^^ ^^^^^^^ type `u32` @@ -143,5 +202,5 @@ LL | asm!("{:x}", inout(reg) main => val_u32); | = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size -error: aborting due to 6 previous errors; 10 warnings emitted +error: aborting due to 10 previous errors; 13 warnings emitted diff --git a/tests/ui/asm/bad-template.aarch64.stderr b/tests/ui/asm/bad-template.aarch64.stderr index 5f7ebb539107c..268fcceb14a50 100644 --- a/tests/ui/asm/bad-template.aarch64.stderr +++ b/tests/ui/asm/bad-template.aarch64.stderr @@ -194,8 +194,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{:foo}", in(reg) foo); | ^^^^^^ --- for this argument | - = help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values) - = help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values) + = help: use `{0:w}` to have the register formatted as `w0` (for 4-byte values) + = help: or use `{0:x}` to keep the default formatting of `x0` (for 8-byte values) = note: `#[warn(asm_sub_register)]` on by default error: aborting due to 21 previous errors; 1 warning emitted diff --git a/tests/ui/asm/bad-template.x86_64.stderr b/tests/ui/asm/bad-template.x86_64.stderr index 9947117621f1c..cc8626deeb5fa 100644 --- a/tests/ui/asm/bad-template.x86_64.stderr +++ b/tests/ui/asm/bad-template.x86_64.stderr @@ -194,8 +194,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{:foo}", in(reg) foo); | ^^^^^^ --- for this argument | - = help: use `{0:e}` to have the register formatted as `eax` (for 32-bit values) - = help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values) + = help: use `{0:e}` to have the register formatted as `eax` (for 4-byte values) + = help: or use `{0:r}` to keep the default formatting of `rax` (for 8-byte values) = note: `#[warn(asm_sub_register)]` on by default error: aborting due to 21 previous errors; 1 warning emitted diff --git a/tests/ui/asm/issue-87802.stderr b/tests/ui/asm/issue-87802.stderr index 64e91662919b2..da3f6815cd7da 100644 --- a/tests/ui/asm/issue-87802.stderr +++ b/tests/ui/asm/issue-87802.stderr @@ -4,7 +4,7 @@ error: cannot use value of type `!` for inline assembly LL | asm!("/* {0} */", out(reg) x); | ^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: aborting due to 1 previous error diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr index aa9eed2fce65c..20e7017ee9ad5 100644 --- a/tests/ui/asm/type-check-1.stderr +++ b/tests/ui/asm/type-check-1.stderr @@ -43,7 +43,7 @@ error: cannot use value of type `[u64]` for inline assembly LL | asm!("{}", in(reg) v[..]); | ^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[u64]` for inline assembly --> $DIR/type-check-1.rs:23:29 @@ -51,7 +51,7 @@ error: cannot use value of type `[u64]` for inline assembly LL | asm!("{}", out(reg) v[..]); | ^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[u64]` for inline assembly --> $DIR/type-check-1.rs:26:31 @@ -59,7 +59,7 @@ error: cannot use value of type `[u64]` for inline assembly LL | asm!("{}", inout(reg) v[..]); | ^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: aborting due to 8 previous errors diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr index e5d39b2fbd053..5e54f5af4c6d8 100644 --- a/tests/ui/asm/x86_64/type-check-2.stderr +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -12,7 +12,7 @@ error: cannot use value of type `{closure@$DIR/type-check-2.rs:48:28: 48:36}` fo LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly --> $DIR/type-check-2.rs:50:28 @@ -20,7 +20,7 @@ error: cannot use value of type `Vec` for inline assembly LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `(i32, i32, i32)` for inline assembly --> $DIR/type-check-2.rs:52:28 @@ -28,7 +28,7 @@ error: cannot use value of type `(i32, i32, i32)` for inline assembly LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly --> $DIR/type-check-2.rs:54:28 @@ -36,7 +36,7 @@ error: cannot use value of type `[i32; 3]` for inline assembly LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly --> $DIR/type-check-2.rs:62:31 @@ -44,7 +44,7 @@ error: cannot use value of type `fn() {main}` for inline assembly LL | asm!("{}", inout(reg) f); | ^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly --> $DIR/type-check-2.rs:65:31 @@ -52,7 +52,7 @@ error: cannot use value of type `&mut i32` for inline assembly LL | asm!("{}", inout(reg) r); | ^ | - = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: only integers, floats, SIMD vectors, scalable vectors, pointers and function pointers can be used as arguments for inline assembly error[E0381]: used binding `x` isn't initialized --> $DIR/type-check-2.rs:15:28 diff --git a/tests/ui/asm/x86_64/type-check-3.stderr b/tests/ui/asm/x86_64/type-check-3.stderr index ea9a3955e7078..e3ad64495904b 100644 --- a/tests/ui/asm/x86_64/type-check-3.stderr +++ b/tests/ui/asm/x86_64/type-check-3.stderr @@ -44,8 +44,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{0} {0}", in(reg) 0i16); | ^^^ ^^^ ---- for this argument | - = help: use `{0:x}` to have the register formatted as `ax` (for 16-bit values) - = help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values) + = help: use `{0:x}` to have the register formatted as `ax` (for 2-byte values) + = help: or use `{0:r}` to keep the default formatting of `rax` (for 8-byte values) = note: `#[warn(asm_sub_register)]` on by default warning: formatting may not be suitable for sub-register argument @@ -54,8 +54,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{0} {0:x}", in(reg) 0i16); | ^^^ ---- for this argument | - = help: use `{0:x}` to have the register formatted as `ax` (for 16-bit values) - = help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values) + = help: use `{0:x}` to have the register formatted as `ax` (for 2-byte values) + = help: or use `{0:r}` to keep the default formatting of `rax` (for 8-byte values) warning: formatting may not be suitable for sub-register argument --> $DIR/type-check-3.rs:36:15 @@ -63,8 +63,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{}", in(reg) 0i32); | ^^ ---- for this argument | - = help: use `{0:e}` to have the register formatted as `eax` (for 32-bit values) - = help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values) + = help: use `{0:e}` to have the register formatted as `eax` (for 4-byte values) + = help: or use `{0:r}` to keep the default formatting of `rax` (for 8-byte values) warning: formatting may not be suitable for sub-register argument --> $DIR/type-check-3.rs:39:15 @@ -72,8 +72,8 @@ warning: formatting may not be suitable for sub-register argument LL | asm!("{}", in(ymm_reg) 0i64); | ^^ ---- for this argument | - = help: use `{0:x}` to have the register formatted as `xmm0` (for 128-bit values) - = help: or use `{0:y}` to keep the default formatting of `ymm0` (for 256-bit values) + = help: use `{0:x}` to have the register formatted as `xmm0` (for 16-byte values) + = help: or use `{0:y}` to keep the default formatting of `ymm0` (for 32-byte values) error: type `i8` cannot be used with this register class --> $DIR/type-check-3.rs:50:28 diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr new file mode 100644 index 0000000000000..f19cb17a04a29 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr @@ -0,0 +1,53 @@ +error[E0658]: register class `preg` can only be used as a clobber in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:45:23 + | +LL | asm!("/* {0} */", in(preg) p); + | ^^^^^^^^^^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: type `svint32_t` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:33:32 + | +LL | asm!("/* {0} */", in(vreg) x); + | ^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: type `svint32_t` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:36:38 + | +LL | asm!("/* {0} */", in(vreg_low16) x); + | ^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: type `svint32_t` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:39:23 + | +LL | asm!("", in("z0") x); + | ^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: type `svbool_t` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:45:32 + | +LL | asm!("/* {0} */", in(preg) p); + | ^ + | + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr similarity index 90% rename from tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr rename to tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr index fb54438ef589e..0f829dd65cb47 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr @@ -1,5 +1,5 @@ error[E0658]: register class `vreg` can only be used as a clobber in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:21:41 + --> $DIR/feature-gate-asm_experimental_reg.rs:60:41 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: register class `vreg` can only be used as a clobber in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:21:54 + --> $DIR/feature-gate-asm_experimental_reg.rs:60:54 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `i8x16` cannot be used with this register class in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:21:51 + --> $DIR/feature-gate-asm_experimental_reg.rs:60:51 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^ @@ -29,7 +29,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `i8x16` cannot be used with this register class in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:21:63 + --> $DIR/feature-gate-asm_experimental_reg.rs:60:63 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^ diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs index 0d2c4fe2b67c3..c91036366a028 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs @@ -1,6 +1,9 @@ //@ add-minicore -//@ compile-flags: --target loongarch64-unknown-none -//@ needs-llvm-components: loongarch +//@ revisions: aarch64 loongarch +//@ [aarch64] compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+sve +//@ [aarch64] needs-llvm-components: aarch64 +//@ [loongarch] compile-flags: --target loongarch64-unknown-none +//@ [loongarch] needs-llvm-components: loongarch //@ ignore-backends: gcc #![feature(no_core, lang_items, rustc_attrs, repr_simd)] @@ -11,17 +14,53 @@ extern crate minicore; use minicore::*; +#[cfg(aarch64)] +#[rustc_scalable_vector(4)] +pub struct svint32_t(i32); + +#[cfg(aarch64)] +impl Copy for svint32_t {} + +#[cfg(aarch64)] +#[rustc_scalable_vector(16)] +pub struct svbool_t(bool); + +#[cfg(aarch64)] +impl Copy for svbool_t {} + +#[cfg(aarch64)] +unsafe fn vector(x: svint32_t) { + asm!("/* {0} */", in(vreg) x); + //[aarch64]~^ ERROR type `svint32_t` cannot be used with this register class in stable + + asm!("/* {0} */", in(vreg_low16) x); + //[aarch64]~^ ERROR type `svint32_t` cannot be used with this register class in stable + + asm!("", in("z0") x); + //[aarch64]~^ ERROR type `svint32_t` cannot be used with this register class in stable +} + +#[cfg(aarch64)] +unsafe fn predicate(p: svbool_t) { + asm!("/* {0} */", in(preg) p); + //[aarch64]~^ ERROR register class `preg` can only be used as a clobber in stable + //[aarch64]~| ERROR type `svbool_t` cannot be used with this register class in stable +} + +#[cfg(loongarch)] #[repr(simd)] pub struct i8x16([i8; 16]); +#[cfg(loongarch)] impl Copy for i8x16 {} +#[cfg(loongarch)] unsafe fn main(x: i8x16) -> i8x16 { let y; asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); - //~^ ERROR register class `vreg` can only be used as a clobber in stable - //~| ERROR register class `vreg` can only be used as a clobber in stable - //~| ERROR type `i8x16` cannot be used with this register class in stable - //~| ERROR type `i8x16` cannot be used with this register class in stable + //[loongarch]~^ ERROR register class `vreg` can only be used as a clobber in stable + //[loongarch]~| ERROR register class `vreg` can only be used as a clobber in stable + //[loongarch]~| ERROR type `i8x16` cannot be used with this register class in stable + //[loongarch]~| ERROR type `i8x16` cannot be used with this register class in stable y }