From 668a3f30afa4f574ff7e6819a398143fedb5583b Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Sat, 2 Nov 2024 10:53:26 +0100 Subject: [PATCH 01/11] Document possibility to set core features in example config.toml --- config.example.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config.example.toml b/config.example.toml index 9072a83551a7e..5e13db3c32745 100644 --- a/config.example.toml +++ b/config.example.toml @@ -772,6 +772,7 @@ #validate-mir-opts = 3 # Configure `std` features used during bootstrap. +# # Default features will be expanded in the following cases: # - If `rust.llvm-libunwind` or `target.llvm-libunwind` is enabled: # - "llvm-libunwind" will be added for in-tree LLVM builds. @@ -779,6 +780,9 @@ # - If `rust.backtrace` is enabled, "backtrace" will be added. # - If `rust.profiler` or `target.profiler` is enabled, "profiler" will be added. # - If building for a zkvm target, "compiler-builtins-mem" will be added. +# +# Since libstd also builds libcore and liballoc as dependencies and all their features are mirrored +# as libstd features, this option can also be used to configure features such as optimize_for_size. #std-features = ["panic_unwind"] # ============================================================================= From ed848a635849ed611b9d0b0a5e8dcd72d8dc700b Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Sat, 2 Nov 2024 19:03:29 +0300 Subject: [PATCH 02/11] ci(triagebot): make all license files trigger "A-meta" label Also add some other proper files to the trigger list of this label. --- triagebot.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 7f4def6a11ba4..7f1f7d807876d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -409,8 +409,14 @@ trigger_files = [ "triagebot.toml", "rustfmt.toml", "LICENSES", + "COPYRIGHT", + "LICENSE-APACHE", + "LICENSE-MIT", + "CODE_OF_CONDUCT.md", "README.md", "CONTRIBUTING.md", + "INSTALL.md", + "REUSE.toml", ".reuse", ".mailmap", ".git-blame-ignore-revs", From 770b15693a6a815b643ffe3aabdf2ed0ce8daa67 Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Sat, 2 Nov 2024 14:23:01 -0400 Subject: [PATCH 03/11] Add BorrowedBuf::into_filled{,_mut} methods to allow returning buffer with original lifetime --- library/core/src/io/borrowed_buf.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs index dbc60aa8154c6..4227e503ba7ba 100644 --- a/library/core/src/io/borrowed_buf.rs +++ b/library/core/src/io/borrowed_buf.rs @@ -108,6 +108,26 @@ impl<'data> BorrowedBuf<'data> { } } + /// Returns a shared reference to the filled portion of the buffer with its original lifetime. + #[inline] + pub fn into_filled(self) -> &'data [u8] { + // SAFETY: We only slice the filled part of the buffer, which is always valid + unsafe { + let buf = self.buf.get_unchecked(..self.filled); + MaybeUninit::slice_assume_init_ref(buf) + } + } + + /// Returns a mutable reference to the filled portion of the buffer with its original lifetime. + #[inline] + pub fn into_filled_mut(self) -> &'data mut [u8] { + // SAFETY: We only slice the filled part of the buffer, which is always valid + unsafe { + let buf = self.buf.get_unchecked_mut(..self.filled); + MaybeUninit::slice_assume_init_mut(buf) + } + } + /// Returns a cursor over the unfilled part of the buffer. #[inline] pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> { From c1285b4fe661798fcc618bdd55a83b0172142f18 Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Thu, 31 Oct 2024 21:51:27 +1100 Subject: [PATCH 04/11] Add a test to verify that libstd doesn't use protected symbols --- tests/run-make/libstd-no-protected/rmake.rs | 63 +++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 tests/run-make/libstd-no-protected/rmake.rs diff --git a/tests/run-make/libstd-no-protected/rmake.rs b/tests/run-make/libstd-no-protected/rmake.rs new file mode 100644 index 0000000000000..3bba59a8f4d55 --- /dev/null +++ b/tests/run-make/libstd-no-protected/rmake.rs @@ -0,0 +1,63 @@ +// If libstd was compiled to use protected symbols, then linking would fail if GNU ld < 2.40 were +// used. This might not be noticed, since usually we use LLD for linking, so we could end up +// distributing a version of libstd that would cause link errors for such users. + +//@ only-x86_64-unknown-linux-gnu + +use run_make_support::object::Endianness; +use run_make_support::object::read::archive::ArchiveFile; +use run_make_support::object::read::elf::{FileHeader as _, SectionHeader as _}; +use run_make_support::rfs::{read, read_dir}; +use run_make_support::{has_prefix, has_suffix, object, path, rustc, shallow_find_files, target}; + +type FileHeader = run_make_support::object::elf::FileHeader64; +type SymbolTable<'data> = run_make_support::object::read::elf::SymbolTable<'data, FileHeader>; + +fn main() { + // Find libstd-...rlib + let sysroot = rustc().print("sysroot").run().stdout_utf8(); + let sysroot = sysroot.trim(); + let target_sysroot = path(sysroot).join("lib/rustlib").join(target()).join("lib"); + let mut libs = shallow_find_files(&target_sysroot, |path| { + has_prefix(path, "libstd-") && has_suffix(path, ".rlib") + }); + assert_eq!(libs.len(), 1); + let libstd_path = libs.pop().unwrap(); + let archive_data = read(libstd_path); + + // Parse all the object files within the libstd archive, checking defined symbols. + let mut num_protected = 0; + let mut num_symbols = 0; + + let archive = ArchiveFile::parse(&*archive_data).unwrap(); + for member in archive.members() { + let member = member.unwrap(); + if member.name() == b"lib.rmeta" { + continue; + } + let data = member.data(&*archive_data).unwrap(); + + let header = FileHeader::parse(data).unwrap(); + let endian = header.endian().unwrap(); + let sections = header.sections(endian, data).unwrap(); + + for (section_index, section) in sections.enumerate() { + if section.sh_type(endian) == object::elf::SHT_SYMTAB { + let symbols = + SymbolTable::parse(endian, data, §ions, section_index, section).unwrap(); + for symbol in symbols.symbols() { + if symbol.st_visibility() == object::elf::STV_PROTECTED { + num_protected += 1; + } + num_symbols += 1; + } + } + } + } + + // If there were no symbols at all, then something is wrong with the test. + assert_ne!(num_symbols, 0); + + // The purpose of this test - check that no symbols have protected visibility. + assert_eq!(num_protected, 0); +} From 5e4b33f2b8f70e5145ce0dce911cfc5b3289aabc Mon Sep 17 00:00:00 2001 From: wangjingcun Date: Sat, 9 Nov 2024 18:39:30 +0800 Subject: [PATCH 05/11] Fix broken url Signed-off-by: wangjingcun --- src/etc/lldb_providers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index bace228454ebb..a42ce111ebcc2 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -32,7 +32,7 @@ # You can find more information and examples here: # 1. https://lldb.llvm.org/varformats.html # 2. https://lldb.llvm.org/use/python-reference.html -# 3. https://lldb.llvm.org/python_reference/lldb.formatters.cpp.libcxx-pysrc.html +# 3. https://github.com/llvm/llvm-project/blob/llvmorg-8.0.1/lldb/www/python_reference/lldb.formatters.cpp-pysrc.html # 4. https://github.com/llvm-mirror/lldb/tree/master/examples/summaries/cocoa #################################################################################################### From 2c8f6de1babfd5cce9badd8ff85c0652377edd75 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 22 Nov 2024 04:18:14 +0900 Subject: [PATCH 06/11] Support input/output in vector registers of s390x inline assembly --- compiler/rustc_codegen_gcc/src/asm.rs | 8 +- compiler/rustc_codegen_llvm/src/asm.rs | 6 +- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/asm/s390x.rs | 5 +- tests/assembly/asm/s390x-types.rs | 198 ++++++++++- tests/auxiliary/minicore.rs | 1 + tests/ui/asm/s390x/bad-reg.rs | 56 ++- tests/ui/asm/s390x/bad-reg.s390x.stderr | 192 +++++----- .../ui/asm/s390x/bad-reg.s390x_vector.stderr | 328 ++++++++++++++++++ 9 files changed, 677 insertions(+), 118 deletions(-) create mode 100644 tests/ui/asm/s390x/bad-reg.s390x_vector.stderr diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 6b067b35e7127..279b4d1d20c85 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -683,9 +683,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::S390x( - S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg, - ) => { + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => { unreachable!("clobber-only") } InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r", @@ -766,7 +765,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr, ) => cx.type_i32(), InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i64(), 2), + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => { unreachable!("clobber-only") } InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index bb74dfe148703..2568c5ea5b594 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -678,7 +678,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> S390x(S390xInlineAsmRegClass::reg) => "r", S390x(S390xInlineAsmRegClass::reg_addr) => "a", S390x(S390xInlineAsmRegClass::freg) => "f", - S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { + S390x(S390xInlineAsmRegClass::vreg) => "v", + S390x(S390xInlineAsmRegClass::areg) => { unreachable!("clobber-only") } Sparc(SparcInlineAsmRegClass::reg) => "r", @@ -844,7 +845,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(), S390x(S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr) => cx.type_i32(), S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), - S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { + S390x(S390xInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i64(), 2), + S390x(S390xInlineAsmRegClass::areg) => { unreachable!("clobber-only") } Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a2d9859645ff6..b0086928231b6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2137,6 +2137,7 @@ symbols! { vec_pop, vec_with_capacity, vecdeque_iter, + vector, version, vfp2, vis, diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index 9b31190a72ba4..426417e5bace8 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -42,7 +42,10 @@ impl S390xInlineAsmRegClass { match self { Self::reg | Self::reg_addr => types! { _: I8, I16, I32, I64; }, Self::freg => types! { _: F32, F64; }, - Self::vreg => &[], + Self::vreg => types! { + vector: I32, F32, I64, F64, I128, F128, + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); + }, Self::areg => &[], } } diff --git a/tests/assembly/asm/s390x-types.rs b/tests/assembly/asm/s390x-types.rs index b1522198a087a..2103b38f9d7bc 100644 --- a/tests/assembly/asm/s390x-types.rs +++ b/tests/assembly/asm/s390x-types.rs @@ -1,10 +1,12 @@ -//@ revisions: s390x +//@ revisions: s390x s390x_vector //@ assembly-output: emit-asm //@[s390x] compile-flags: --target s390x-unknown-linux-gnu //@[s390x] needs-llvm-components: systemz +//@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector +//@[s390x_vector] needs-llvm-components: systemz //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, f128)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] @@ -27,16 +29,39 @@ trait Sized {} #[lang = "copy"] trait Copy {} +impl Copy for [T; N] {} + type ptr = *const i32; +#[repr(simd)] +pub struct i8x16([i8; 16]); +#[repr(simd)] +pub struct i16x8([i16; 8]); +#[repr(simd)] +pub struct i32x4([i32; 4]); +#[repr(simd)] +pub struct i64x2([i64; 2]); +#[repr(simd)] +pub struct f32x4([f32; 4]); +#[repr(simd)] +pub struct f64x2([f64; 2]); + impl Copy for i8 {} impl Copy for u8 {} impl Copy for i16 {} impl Copy for i32 {} impl Copy for i64 {} +impl Copy for i128 {} impl Copy for f32 {} impl Copy for f64 {} +impl Copy for f128 {} impl Copy for ptr {} +impl Copy for i8x16 {} +impl Copy for i16x8 {} +impl Copy for i32x4 {} +impl Copy for i64x2 {} +impl Copy for f32x4 {} +impl Copy for f64x2 {} extern "C" { fn extern_func(); @@ -65,7 +90,6 @@ macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { // CHECK: #APP // CHECK: brasl %r14, extern_func // CHECK: #NO_APP -#[cfg(s390x)] #[no_mangle] pub unsafe fn sym_fn_32() { asm!("brasl %r14, {}", sym extern_func); @@ -146,6 +170,90 @@ check!(reg_f64, f64, freg, "ldr"); // CHECK: #NO_APP check!(reg_ptr, ptr, reg, "lgr"); +// s390x_vector-LABEL: vreg_i8x16: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_i8x16, i8x16, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_i16x8: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_i16x8, i16x8, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_i32x4: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_i32x4, i32x4, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_i64x2: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_i64x2, i64x2, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_f32x4: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_f32x4, f32x4, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_f64x2: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_f64x2, f64x2, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_i32: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_i32, i32, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_i64: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_i64, i64, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_i128: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_i128, i128, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_f32: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_f32, f32, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_f64: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_f64, f64, vreg, "vlr"); + +// s390x_vector-LABEL: vreg_f128: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_f128, f128, vreg, "vlr"); + // CHECK-LABEL: r0_i8: // CHECK: #APP // CHECK: lr %r0, %r0 @@ -181,3 +289,87 @@ check_reg!(f0_f32, f32, "f0", "ler"); // CHECK: ldr %f0, %f0 // CHECK: #NO_APP check_reg!(f0_f64, f64, "f0", "ldr"); + +// s390x_vector-LABEL: v0_i8x16: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_i8x16, i8x16, "v0", "vlr"); + +// s390x_vector-LABEL: v0_i16x8: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_i16x8, i16x8, "v0", "vlr"); + +// s390x_vector-LABEL: v0_i32x4: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_i32x4, i32x4, "v0", "vlr"); + +// s390x_vector-LABEL: v0_i64x2: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_i64x2, i64x2, "v0", "vlr"); + +// s390x_vector-LABEL: v0_f32x4: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_f32x4, f32x4, "v0", "vlr"); + +// s390x_vector-LABEL: v0_f64x2: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_f64x2, f64x2, "v0", "vlr"); + +// s390x_vector-LABEL: v0_i32: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_i32, i32, "v0", "vlr"); + +// s390x_vector-LABEL: v0_i64: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_i64, i64, "v0", "vlr"); + +// s390x_vector-LABEL: v0_i128: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_i128, i128, "v0", "vlr"); + +// s390x_vector-LABEL: v0_f32: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_f32, f32, "v0", "vlr"); + +// s390x_vector-LABEL: v0_f64: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_f64, f64, "v0", "vlr"); + +// s390x_vector-LABEL: v0_f128: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_f128, f128, "v0", "vlr"); diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index 1e9f2ee59b48f..c4317752920f0 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -45,6 +45,7 @@ impl_marker_trait!( impl<'a, T: ?Sized> Copy for &'a T {} impl Copy for *const T {} impl Copy for *mut T {} +impl Copy for [T; N] {} #[lang = "phantom_data"] pub struct PhantomData; diff --git a/tests/ui/asm/s390x/bad-reg.rs b/tests/ui/asm/s390x/bad-reg.rs index 6de43fdfe5eb0..28877b822af68 100644 --- a/tests/ui/asm/s390x/bad-reg.rs +++ b/tests/ui/asm/s390x/bad-reg.rs @@ -1,19 +1,28 @@ //@ add-core-stubs //@ needs-asm-support -//@ revisions: s390x +//@ revisions: s390x s390x_vector //@[s390x] compile-flags: --target s390x-unknown-linux-gnu //@[s390x] needs-llvm-components: systemz +//@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector +//@[s390x_vector] needs-llvm-components: systemz #![crate_type = "rlib"] -#![feature(no_core, rustc_attrs)] -#![feature(asm_experimental_arch)] +#![feature(no_core, rustc_attrs, repr_simd)] #![no_core] +#![allow(non_camel_case_types)] extern crate minicore; use minicore::*; +#[repr(simd)] +pub struct i64x2([i64; 2]); + +impl Copy for i64x2 {} + fn f() { let mut x = 0; + let mut b = 0u8; + let mut v = i64x2([0; 2]); unsafe { // Unsupported registers asm!("", out("r11") _); @@ -57,6 +66,32 @@ fn f() { asm!("", out("a1") _); //~^ ERROR invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm + // vreg + asm!("", out("v0") _); // always ok + asm!("", in("v0") v); // requires vector + //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + asm!("", out("v0") v); // requires vector + //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + asm!("", in("v0") x); // requires vector + //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + asm!("", out("v0") x); // requires vector + //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + asm!("", in("v0") b); + //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + //[s390x_vector]~^^ ERROR type `u8` cannot be used with this register class + asm!("", out("v0") b); + //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + //[s390x_vector]~^^ ERROR type `u8` cannot be used with this register class + asm!("/* {} */", in(vreg) v); // requires vector + //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + asm!("/* {} */", in(vreg) x); // requires vector + //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + asm!("/* {} */", in(vreg) b); + //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + //[s390x_vector]~^^ ERROR type `u8` cannot be used with this register class + asm!("/* {} */", out(vreg) _); // requires vector + //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + // Clobber-only registers // areg asm!("", out("a2") _); // ok @@ -72,21 +107,6 @@ fn f() { asm!("/* {} */", out(areg) _); //~^ ERROR can only be used as a clobber - // vreg - asm!("", out("v0") _); // ok - // FIXME: will be supported in https://github.com/rust-lang/rust/pull/131664 - asm!("", in("v0") x); - //~^ ERROR can only be used as a clobber - //~| ERROR type `i32` cannot be used with this register class - asm!("", out("v0") x); - //~^ ERROR can only be used as a clobber - //~| ERROR type `i32` cannot be used with this register class - asm!("/* {} */", in(vreg) x); - //~^ ERROR can only be used as a clobber - //~| ERROR type `i32` cannot be used with this register class - asm!("/* {} */", out(vreg) _); - //~^ ERROR can only be used as a clobber - // Overlapping registers // vreg/freg asm!("", out("v0") _, out("f0") _); diff --git a/tests/ui/asm/s390x/bad-reg.s390x.stderr b/tests/ui/asm/s390x/bad-reg.s390x.stderr index 460d7c15de114..20c26096f8b5b 100644 --- a/tests/ui/asm/s390x/bad-reg.s390x.stderr +++ b/tests/ui/asm/s390x/bad-reg.s390x.stderr @@ -1,173 +1,149 @@ error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:19:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", out("r11") _); | ^^^^^^^^^^^^ error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:21:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("r15") _); | ^^^^^^^^^^^^ error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:23:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", out("c0") _); | ^^^^^^^^^^^ error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:25:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", out("c1") _); | ^^^^^^^^^^^ error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:27:18 + --> $DIR/bad-reg.rs:36:18 | LL | asm!("", out("c2") _); | ^^^^^^^^^^^ error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:29:18 + --> $DIR/bad-reg.rs:38:18 | LL | asm!("", out("c3") _); | ^^^^^^^^^^^ error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:31:18 + --> $DIR/bad-reg.rs:40:18 | LL | asm!("", out("c4") _); | ^^^^^^^^^^^ error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:33:18 + --> $DIR/bad-reg.rs:42:18 | LL | asm!("", out("c5") _); | ^^^^^^^^^^^ error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:35:18 + --> $DIR/bad-reg.rs:44:18 | LL | asm!("", out("c6") _); | ^^^^^^^^^^^ error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:37:18 + --> $DIR/bad-reg.rs:46:18 | LL | asm!("", out("c7") _); | ^^^^^^^^^^^ error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:39:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", out("c8") _); | ^^^^^^^^^^^ error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:41:18 + --> $DIR/bad-reg.rs:50:18 | LL | asm!("", out("c9") _); | ^^^^^^^^^^^ error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:43:18 + --> $DIR/bad-reg.rs:52:18 | LL | asm!("", out("c10") _); | ^^^^^^^^^^^^ error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:45:18 + --> $DIR/bad-reg.rs:54:18 | LL | asm!("", out("c11") _); | ^^^^^^^^^^^^ error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:47:18 + --> $DIR/bad-reg.rs:56:18 | LL | asm!("", out("c12") _); | ^^^^^^^^^^^^ error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:49:18 + --> $DIR/bad-reg.rs:58:18 | LL | asm!("", out("c13") _); | ^^^^^^^^^^^^ error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:51:18 + --> $DIR/bad-reg.rs:60:18 | LL | asm!("", out("c14") _); | ^^^^^^^^^^^^ error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:53:18 + --> $DIR/bad-reg.rs:62:18 | LL | asm!("", out("c15") _); | ^^^^^^^^^^^^ error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:55:18 + --> $DIR/bad-reg.rs:64:18 | LL | asm!("", out("a0") _); | ^^^^^^^^^^^ error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:57:18 + --> $DIR/bad-reg.rs:66:18 | LL | asm!("", out("a1") _); | ^^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:63:18 + --> $DIR/bad-reg.rs:98:18 | LL | asm!("", in("a2") x); | ^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:101:18 | LL | asm!("", out("a2") x); | ^^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:69:26 + --> $DIR/bad-reg.rs:104:26 | LL | asm!("/* {} */", in(areg) x); | ^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:72:26 + --> $DIR/bad-reg.rs:107:26 | LL | asm!("/* {} */", out(areg) _); | ^^^^^^^^^^^ -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:78:18 - | -LL | asm!("", in("v0") x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:81:18 - | -LL | asm!("", out("v0") x); - | ^^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:84:26 - | -LL | asm!("/* {} */", in(vreg) x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:87:26 - | -LL | asm!("/* {} */", out(vreg) _); - | ^^^^^^^^^^^ - error: register `f0` conflicts with register `v0` - --> $DIR/bad-reg.rs:92:31 + --> $DIR/bad-reg.rs:112:31 | LL | asm!("", out("v0") _, out("f0") _); | ----------- ^^^^^^^^^^^ register `f0` @@ -175,7 +151,7 @@ LL | asm!("", out("v0") _, out("f0") _); | register `v0` error: register `f1` conflicts with register `v1` - --> $DIR/bad-reg.rs:94:31 + --> $DIR/bad-reg.rs:114:31 | LL | asm!("", out("v1") _, out("f1") _); | ----------- ^^^^^^^^^^^ register `f1` @@ -183,7 +159,7 @@ LL | asm!("", out("v1") _, out("f1") _); | register `v1` error: register `f2` conflicts with register `v2` - --> $DIR/bad-reg.rs:96:31 + --> $DIR/bad-reg.rs:116:31 | LL | asm!("", out("v2") _, out("f2") _); | ----------- ^^^^^^^^^^^ register `f2` @@ -191,7 +167,7 @@ LL | asm!("", out("v2") _, out("f2") _); | register `v2` error: register `f3` conflicts with register `v3` - --> $DIR/bad-reg.rs:98:31 + --> $DIR/bad-reg.rs:118:31 | LL | asm!("", out("v3") _, out("f3") _); | ----------- ^^^^^^^^^^^ register `f3` @@ -199,7 +175,7 @@ LL | asm!("", out("v3") _, out("f3") _); | register `v3` error: register `f4` conflicts with register `v4` - --> $DIR/bad-reg.rs:100:31 + --> $DIR/bad-reg.rs:120:31 | LL | asm!("", out("v4") _, out("f4") _); | ----------- ^^^^^^^^^^^ register `f4` @@ -207,7 +183,7 @@ LL | asm!("", out("v4") _, out("f4") _); | register `v4` error: register `f5` conflicts with register `v5` - --> $DIR/bad-reg.rs:102:31 + --> $DIR/bad-reg.rs:122:31 | LL | asm!("", out("v5") _, out("f5") _); | ----------- ^^^^^^^^^^^ register `f5` @@ -215,7 +191,7 @@ LL | asm!("", out("v5") _, out("f5") _); | register `v5` error: register `f6` conflicts with register `v6` - --> $DIR/bad-reg.rs:104:31 + --> $DIR/bad-reg.rs:124:31 | LL | asm!("", out("v6") _, out("f6") _); | ----------- ^^^^^^^^^^^ register `f6` @@ -223,7 +199,7 @@ LL | asm!("", out("v6") _, out("f6") _); | register `v6` error: register `f7` conflicts with register `v7` - --> $DIR/bad-reg.rs:106:31 + --> $DIR/bad-reg.rs:126:31 | LL | asm!("", out("v7") _, out("f7") _); | ----------- ^^^^^^^^^^^ register `f7` @@ -231,7 +207,7 @@ LL | asm!("", out("v7") _, out("f7") _); | register `v7` error: register `f8` conflicts with register `v8` - --> $DIR/bad-reg.rs:108:31 + --> $DIR/bad-reg.rs:128:31 | LL | asm!("", out("v8") _, out("f8") _); | ----------- ^^^^^^^^^^^ register `f8` @@ -239,7 +215,7 @@ LL | asm!("", out("v8") _, out("f8") _); | register `v8` error: register `f9` conflicts with register `v9` - --> $DIR/bad-reg.rs:110:31 + --> $DIR/bad-reg.rs:130:31 | LL | asm!("", out("v9") _, out("f9") _); | ----------- ^^^^^^^^^^^ register `f9` @@ -247,7 +223,7 @@ LL | asm!("", out("v9") _, out("f9") _); | register `v9` error: register `f10` conflicts with register `v10` - --> $DIR/bad-reg.rs:112:32 + --> $DIR/bad-reg.rs:132:32 | LL | asm!("", out("v10") _, out("f10") _); | ------------ ^^^^^^^^^^^^ register `f10` @@ -255,7 +231,7 @@ LL | asm!("", out("v10") _, out("f10") _); | register `v10` error: register `f11` conflicts with register `v11` - --> $DIR/bad-reg.rs:114:32 + --> $DIR/bad-reg.rs:134:32 | LL | asm!("", out("v11") _, out("f11") _); | ------------ ^^^^^^^^^^^^ register `f11` @@ -263,7 +239,7 @@ LL | asm!("", out("v11") _, out("f11") _); | register `v11` error: register `f12` conflicts with register `v12` - --> $DIR/bad-reg.rs:116:32 + --> $DIR/bad-reg.rs:136:32 | LL | asm!("", out("v12") _, out("f12") _); | ------------ ^^^^^^^^^^^^ register `f12` @@ -271,7 +247,7 @@ LL | asm!("", out("v12") _, out("f12") _); | register `v12` error: register `f13` conflicts with register `v13` - --> $DIR/bad-reg.rs:118:32 + --> $DIR/bad-reg.rs:138:32 | LL | asm!("", out("v13") _, out("f13") _); | ------------ ^^^^^^^^^^^^ register `f13` @@ -279,7 +255,7 @@ LL | asm!("", out("v13") _, out("f13") _); | register `v13` error: register `f14` conflicts with register `v14` - --> $DIR/bad-reg.rs:120:32 + --> $DIR/bad-reg.rs:140:32 | LL | asm!("", out("v14") _, out("f14") _); | ------------ ^^^^^^^^^^^^ register `f14` @@ -287,7 +263,7 @@ LL | asm!("", out("v14") _, out("f14") _); | register `v14` error: register `f15` conflicts with register `v15` - --> $DIR/bad-reg.rs:122:32 + --> $DIR/bad-reg.rs:142:32 | LL | asm!("", out("v15") _, out("f15") _); | ------------ ^^^^^^^^^^^^ register `f15` @@ -295,58 +271,94 @@ LL | asm!("", out("v15") _, out("f15") _); | register `v15` error: invalid register `f16`: unknown register - --> $DIR/bad-reg.rs:125:32 + --> $DIR/bad-reg.rs:145:32 | LL | asm!("", out("v16") _, out("f16") _); | ^^^^^^^^^^^^ -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:63:27 +error: register class `vreg` requires the `vector` target feature + --> $DIR/bad-reg.rs:71:18 | -LL | asm!("", in("a2") x); - | ^ +LL | asm!("", in("v0") v); // requires vector + | ^^^^^^^^^^ + +error: register class `vreg` requires the `vector` target feature + --> $DIR/bad-reg.rs:73:18 | - = note: register class `areg` supports these types: +LL | asm!("", out("v0") v); // requires vector + | ^^^^^^^^^^^ -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:28 +error: register class `vreg` requires the `vector` target feature + --> $DIR/bad-reg.rs:75:18 | -LL | asm!("", out("a2") x); - | ^ +LL | asm!("", in("v0") x); // requires vector + | ^^^^^^^^^^ + +error: register class `vreg` requires the `vector` target feature + --> $DIR/bad-reg.rs:77:18 | - = note: register class `areg` supports these types: +LL | asm!("", out("v0") x); // requires vector + | ^^^^^^^^^^^ -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:35 +error: register class `vreg` requires the `vector` target feature + --> $DIR/bad-reg.rs:79:18 | -LL | asm!("/* {} */", in(areg) x); - | ^ +LL | asm!("", in("v0") b); + | ^^^^^^^^^^ + +error: register class `vreg` requires the `vector` target feature + --> $DIR/bad-reg.rs:82:18 | - = note: register class `areg` supports these types: +LL | asm!("", out("v0") b); + | ^^^^^^^^^^^ + +error: register class `vreg` requires the `vector` target feature + --> $DIR/bad-reg.rs:85:26 + | +LL | asm!("/* {} */", in(vreg) v); // requires vector + | ^^^^^^^^^^ + +error: register class `vreg` requires the `vector` target feature + --> $DIR/bad-reg.rs:87:26 + | +LL | asm!("/* {} */", in(vreg) x); // requires vector + | ^^^^^^^^^^ + +error: register class `vreg` requires the `vector` target feature + --> $DIR/bad-reg.rs:89:26 + | +LL | asm!("/* {} */", in(vreg) b); + | ^^^^^^^^^^ + +error: register class `vreg` requires the `vector` target feature + --> $DIR/bad-reg.rs:92:26 + | +LL | asm!("/* {} */", out(vreg) _); // requires vector + | ^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:78:27 + --> $DIR/bad-reg.rs:98:27 | -LL | asm!("", in("v0") x); +LL | asm!("", in("a2") x); | ^ | - = note: register class `vreg` supports these types: + = note: register class `areg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:81:28 + --> $DIR/bad-reg.rs:101:28 | -LL | asm!("", out("v0") x); +LL | asm!("", out("a2") x); | ^ | - = note: register class `vreg` supports these types: + = note: register class `areg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:84:35 + --> $DIR/bad-reg.rs:104:35 | -LL | asm!("/* {} */", in(vreg) x); +LL | asm!("/* {} */", in(areg) x); | ^ | - = note: register class `vreg` supports these types: + = note: register class `areg` supports these types: -error: aborting due to 51 previous errors +error: aborting due to 54 previous errors diff --git a/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr b/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr new file mode 100644 index 0000000000000..1ca18a5d84334 --- /dev/null +++ b/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr @@ -0,0 +1,328 @@ +error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:28:18 + | +LL | asm!("", out("r11") _); + | ^^^^^^^^^^^^ + +error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", out("r15") _); + | ^^^^^^^^^^^^ + +error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", out("c0") _); + | ^^^^^^^^^^^ + +error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("c1") _); + | ^^^^^^^^^^^ + +error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("c2") _); + | ^^^^^^^^^^^ + +error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("c3") _); + | ^^^^^^^^^^^ + +error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("c4") _); + | ^^^^^^^^^^^ + +error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("c5") _); + | ^^^^^^^^^^^ + +error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("c6") _); + | ^^^^^^^^^^^ + +error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("c7") _); + | ^^^^^^^^^^^ + +error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:48:18 + | +LL | asm!("", out("c8") _); + | ^^^^^^^^^^^ + +error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:50:18 + | +LL | asm!("", out("c9") _); + | ^^^^^^^^^^^ + +error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:52:18 + | +LL | asm!("", out("c10") _); + | ^^^^^^^^^^^^ + +error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:54:18 + | +LL | asm!("", out("c11") _); + | ^^^^^^^^^^^^ + +error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:56:18 + | +LL | asm!("", out("c12") _); + | ^^^^^^^^^^^^ + +error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:58:18 + | +LL | asm!("", out("c13") _); + | ^^^^^^^^^^^^ + +error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:60:18 + | +LL | asm!("", out("c14") _); + | ^^^^^^^^^^^^ + +error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:62:18 + | +LL | asm!("", out("c15") _); + | ^^^^^^^^^^^^ + +error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:64:18 + | +LL | asm!("", out("a0") _); + | ^^^^^^^^^^^ + +error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:66:18 + | +LL | asm!("", out("a1") _); + | ^^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:98:18 + | +LL | asm!("", in("a2") x); + | ^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:101:18 + | +LL | asm!("", out("a2") x); + | ^^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:104:26 + | +LL | asm!("/* {} */", in(areg) x); + | ^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:107:26 + | +LL | asm!("/* {} */", out(areg) _); + | ^^^^^^^^^^^ + +error: register `f0` conflicts with register `v0` + --> $DIR/bad-reg.rs:112:31 + | +LL | asm!("", out("v0") _, out("f0") _); + | ----------- ^^^^^^^^^^^ register `f0` + | | + | register `v0` + +error: register `f1` conflicts with register `v1` + --> $DIR/bad-reg.rs:114:31 + | +LL | asm!("", out("v1") _, out("f1") _); + | ----------- ^^^^^^^^^^^ register `f1` + | | + | register `v1` + +error: register `f2` conflicts with register `v2` + --> $DIR/bad-reg.rs:116:31 + | +LL | asm!("", out("v2") _, out("f2") _); + | ----------- ^^^^^^^^^^^ register `f2` + | | + | register `v2` + +error: register `f3` conflicts with register `v3` + --> $DIR/bad-reg.rs:118:31 + | +LL | asm!("", out("v3") _, out("f3") _); + | ----------- ^^^^^^^^^^^ register `f3` + | | + | register `v3` + +error: register `f4` conflicts with register `v4` + --> $DIR/bad-reg.rs:120:31 + | +LL | asm!("", out("v4") _, out("f4") _); + | ----------- ^^^^^^^^^^^ register `f4` + | | + | register `v4` + +error: register `f5` conflicts with register `v5` + --> $DIR/bad-reg.rs:122:31 + | +LL | asm!("", out("v5") _, out("f5") _); + | ----------- ^^^^^^^^^^^ register `f5` + | | + | register `v5` + +error: register `f6` conflicts with register `v6` + --> $DIR/bad-reg.rs:124:31 + | +LL | asm!("", out("v6") _, out("f6") _); + | ----------- ^^^^^^^^^^^ register `f6` + | | + | register `v6` + +error: register `f7` conflicts with register `v7` + --> $DIR/bad-reg.rs:126:31 + | +LL | asm!("", out("v7") _, out("f7") _); + | ----------- ^^^^^^^^^^^ register `f7` + | | + | register `v7` + +error: register `f8` conflicts with register `v8` + --> $DIR/bad-reg.rs:128:31 + | +LL | asm!("", out("v8") _, out("f8") _); + | ----------- ^^^^^^^^^^^ register `f8` + | | + | register `v8` + +error: register `f9` conflicts with register `v9` + --> $DIR/bad-reg.rs:130:31 + | +LL | asm!("", out("v9") _, out("f9") _); + | ----------- ^^^^^^^^^^^ register `f9` + | | + | register `v9` + +error: register `f10` conflicts with register `v10` + --> $DIR/bad-reg.rs:132:32 + | +LL | asm!("", out("v10") _, out("f10") _); + | ------------ ^^^^^^^^^^^^ register `f10` + | | + | register `v10` + +error: register `f11` conflicts with register `v11` + --> $DIR/bad-reg.rs:134:32 + | +LL | asm!("", out("v11") _, out("f11") _); + | ------------ ^^^^^^^^^^^^ register `f11` + | | + | register `v11` + +error: register `f12` conflicts with register `v12` + --> $DIR/bad-reg.rs:136:32 + | +LL | asm!("", out("v12") _, out("f12") _); + | ------------ ^^^^^^^^^^^^ register `f12` + | | + | register `v12` + +error: register `f13` conflicts with register `v13` + --> $DIR/bad-reg.rs:138:32 + | +LL | asm!("", out("v13") _, out("f13") _); + | ------------ ^^^^^^^^^^^^ register `f13` + | | + | register `v13` + +error: register `f14` conflicts with register `v14` + --> $DIR/bad-reg.rs:140:32 + | +LL | asm!("", out("v14") _, out("f14") _); + | ------------ ^^^^^^^^^^^^ register `f14` + | | + | register `v14` + +error: register `f15` conflicts with register `v15` + --> $DIR/bad-reg.rs:142:32 + | +LL | asm!("", out("v15") _, out("f15") _); + | ------------ ^^^^^^^^^^^^ register `f15` + | | + | register `v15` + +error: invalid register `f16`: unknown register + --> $DIR/bad-reg.rs:145:32 + | +LL | asm!("", out("v16") _, out("f16") _); + | ^^^^^^^^^^^^ + +error: type `u8` cannot be used with this register class + --> $DIR/bad-reg.rs:79:27 + | +LL | asm!("", in("v0") b); + | ^ + | + = note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 + +error: type `u8` cannot be used with this register class + --> $DIR/bad-reg.rs:82:28 + | +LL | asm!("", out("v0") b); + | ^ + | + = note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 + +error: type `u8` cannot be used with this register class + --> $DIR/bad-reg.rs:89:35 + | +LL | asm!("/* {} */", in(vreg) b); + | ^ + | + = note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:98:27 + | +LL | asm!("", in("a2") x); + | ^ + | + = note: register class `areg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:101:28 + | +LL | asm!("", out("a2") x); + | ^ + | + = note: register class `areg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:104:35 + | +LL | asm!("/* {} */", in(areg) x); + | ^ + | + = note: register class `areg` supports these types: + +error: aborting due to 47 previous errors + From c024d8ccdfb462f4e99b54e6c8456fbc4d745752 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 24 Nov 2024 21:42:22 +0900 Subject: [PATCH 07/11] Make s390x non-clobber-only vector register support unstable --- compiler/rustc_ast_lowering/messages.ftl | 2 + compiler/rustc_ast_lowering/src/asm.rs | 32 +- compiler/rustc_ast_lowering/src/errors.rs | 8 + .../rustc_codegen_cranelift/src/inline_asm.rs | 8 +- compiler/rustc_codegen_gcc/src/asm.rs | 2 +- compiler/rustc_codegen_llvm/src/asm.rs | 4 +- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_hir_analysis/messages.ftl | 3 + .../src/check/intrinsicck.rs | 38 +- compiler/rustc_hir_analysis/src/errors.rs | 8 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/asm/mod.rs | 13 +- compiler/rustc_target/src/asm/s390x.rs | 16 +- .../language-features/asm-experimental-reg.md | 40 ++ tests/assembly/asm/s390x-types.rs | 1 + tests/ui/asm/s390x/bad-reg.rs | 38 +- tests/ui/asm/s390x/bad-reg.s390x.stderr | 122 ++--- .../ui/asm/s390x/bad-reg.s390x_vector.stderr | 94 ++-- .../s390x/bad-reg.s390x_vector_stable.stderr | 489 ++++++++++++++++++ .../feature-gate-asm_experimental_reg.rs | 23 + .../feature-gate-asm_experimental_reg.stderr | 23 + 21 files changed, 822 insertions(+), 145 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/asm-experimental-reg.md create mode 100644 tests/ui/asm/s390x/bad-reg.s390x_vector_stable.stderr create mode 100644 tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs create mode 100644 tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index f704320c71d72..5095b454fa490 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -152,6 +152,8 @@ ast_lowering_register2 = register `{$reg2_name}` ast_lowering_register_class_only_clobber = register class `{$reg_class_name}` can only be used as a clobber, not as an input or output +ast_lowering_register_class_only_clobber_stable = + register class `{$reg_class_name}` can only be used as a clobber in stable ast_lowering_register_conflict = register `{$reg1_name}` conflicts with register `{$reg2_name}` diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 215e6d84d0f0a..3d75a63abda2e 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -17,7 +17,8 @@ use super::errors::{ InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst, InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass, InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister, - InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict, + InvalidRegisterClass, RegisterClassOnlyClobber, RegisterClassOnlyClobberStable, + RegisterConflict, }; use crate::{ AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode, @@ -61,6 +62,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .emit(); } } + let allow_experimental_reg = self.tcx.features().asm_experimental_reg(); if asm.options.contains(InlineAsmOptions::ATT_SYNTAX) && !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)) && !self.tcx.sess.opts.actually_rustdoc @@ -333,11 +335,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // means that we disallow passing a value in/out of the asm and // require that the operand name an explicit register, not a // register class. - if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() { - self.dcx().emit_err(RegisterClassOnlyClobber { - op_span: op_sp, - reg_class_name: reg_class.name(), - }); + if reg_class.is_clobber_only(asm_arch.unwrap(), allow_experimental_reg) + && !op.is_clobber() + { + if allow_experimental_reg || reg_class.is_clobber_only(asm_arch.unwrap(), true) + { + // always clobber-only + self.dcx().emit_err(RegisterClassOnlyClobber { + op_span: op_sp, + reg_class_name: reg_class.name(), + }); + } else { + // clobber-only in stable + self.tcx + .sess + .create_feature_err( + RegisterClassOnlyClobberStable { + op_span: op_sp, + reg_class_name: reg_class.name(), + }, + sym::asm_experimental_reg, + ) + .emit(); + } continue; } diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index e6a3f939f2db1..447af57354fd6 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -279,6 +279,14 @@ pub(crate) struct RegisterClassOnlyClobber { pub reg_class_name: Symbol, } +#[derive(Diagnostic)] +#[diag(ast_lowering_register_class_only_clobber_stable)] +pub(crate) struct RegisterClassOnlyClobberStable { + #[primary_span] + pub op_span: Span, + pub reg_class_name: Symbol, +} + #[derive(Diagnostic)] #[diag(ast_lowering_register_conflict)] pub(crate) struct RegisterConflict<'a> { diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 0df1a30fc0a49..a2fb711b9e166 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -462,8 +462,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { let mut slots_output = vec![None; self.operands.len()]; let new_slot_fn = |slot_size: &mut Size, reg_class: InlineAsmRegClass| { - let reg_size = - reg_class.supported_types(self.arch).iter().map(|(ty, _)| ty.size()).max().unwrap(); + let reg_size = reg_class + .supported_types(self.arch, true) + .iter() + .map(|(ty, _)| ty.size()) + .max() + .unwrap(); let align = rustc_abi::Align::from_bytes(reg_size.bytes()).unwrap(); let offset = slot_size.align_to(align); *slot_size = offset + reg_size; diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 279b4d1d20c85..ab4fdb78bb094 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -186,7 +186,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // `clobber_abi` can add lots of clobbers that are not supported by the target, // such as AVX-512 registers, so we just ignore unsupported registers let is_target_supported = - reg.reg_class().supported_types(asm_arch).iter().any( + reg.reg_class().supported_types(asm_arch, true).iter().any( |&(_, feature)| { if let Some(feature) = feature { self.tcx diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 2568c5ea5b594..ee6c768b724e4 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -45,7 +45,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { match *op { InlineAsmOperandRef::Out { reg, late, place } => { let is_target_supported = |reg_class: InlineAsmRegClass| { - for &(_, feature) in reg_class.supported_types(asm_arch) { + for &(_, feature) in reg_class.supported_types(asm_arch, true) { if let Some(feature) = feature { if self .tcx @@ -85,7 +85,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } continue; } else if !is_target_supported(reg.reg_class()) - || reg.reg_class().is_clobber_only(asm_arch) + || reg.reg_class().is_clobber_only(asm_arch, true) { // We turn discarded outputs into clobber constraints // if the target feature needed by the register class is diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index e3dc73c14014f..3b93c29e5489e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -376,6 +376,8 @@ declare_features! ( (unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), + /// Enables experimental register support in inline assembly. + (unstable, asm_experimental_reg, "CURRENT_RUSTC_VERSION", Some(133416)), /// Allows using `label` operands in inline assembly. (unstable, asm_goto, "1.78.0", Some(119364)), /// Allows the `may_unwind` option in inline assembly. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 64a30e633cf9d..6cc1d9ed8f484 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -424,6 +424,9 @@ hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}` .note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}` +hir_analysis_register_type_unstable = + type `{$ty}` cannot be used with this register class in stable + hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}` hir_analysis_return_type_notation_equality_bound = diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index dfddf93a5c273..b96469f503c8b 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -7,12 +7,14 @@ use rustc_hir::{self as hir, LangItem}; use rustc_middle::bug; use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; use rustc_session::lint; -use rustc_span::Symbol; use rustc_span::def_id::LocalDefId; +use rustc_span::{Symbol, sym}; use rustc_target::asm::{ InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType, ModifierInfo, }; +use crate::errors::RegisterTypeUnstable; + pub struct InlineAsmCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, @@ -218,17 +220,29 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // Check the type against the list of types supported by the selected // register class. let asm_arch = self.tcx.sess.asm_arch.unwrap(); + let allow_experimental_reg = self.tcx.features().asm_experimental_reg(); let reg_class = reg.reg_class(); - let supported_tys = reg_class.supported_types(asm_arch); + let supported_tys = reg_class.supported_types(asm_arch, allow_experimental_reg); let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else { - let msg = format!("type `{ty}` cannot be used with this register class"); - let mut err = self.tcx.dcx().struct_span_err(expr.span, msg); - let supported_tys: Vec<_> = supported_tys.iter().map(|(t, _)| t.to_string()).collect(); - err.note(format!( - "register class `{}` supports these types: {}", - reg_class.name(), - supported_tys.join(", "), - )); + let mut err = if !allow_experimental_reg + && reg_class.supported_types(asm_arch, true).iter().any(|&(t, _)| t == asm_ty) + { + self.tcx.sess.create_feature_err( + RegisterTypeUnstable { span: expr.span, ty }, + sym::asm_experimental_reg, + ) + } else { + let msg = format!("type `{ty}` cannot be used with this register class"); + let mut err = self.tcx.dcx().struct_span_err(expr.span, msg); + let supported_tys: Vec<_> = + supported_tys.iter().map(|(t, _)| t.to_string()).collect(); + err.note(format!( + "register class `{}` supports these types: {}", + reg_class.name(), + supported_tys.join(", "), + )); + err + }; if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) { err.help(format!("consider using the `{}` register class instead", suggest.name())); } @@ -313,6 +327,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { self.tcx.dcx().delayed_bug("target architecture does not support asm"); return; }; + let allow_experimental_reg = self.tcx.features().asm_experimental_reg(); for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { // Validate register classes against currently enabled target // features. We check that at least one type is available for @@ -352,7 +367,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let InlineAsmRegClass::Err = reg_class { continue; } - for &(_, feature) in reg_class.supported_types(asm_arch) { + for &(_, feature) in reg_class.supported_types(asm_arch, allow_experimental_reg) + { match feature { Some(feature) => { if target_features.contains(&feature) { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 07d3273b09c77..897ee58baab7a 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1685,3 +1685,11 @@ pub(crate) struct CmseEntryGeneric { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_register_type_unstable)] +pub(crate) struct RegisterTypeUnstable<'a> { + #[primary_span] + pub span: Span, + pub ty: Ty<'a>, +} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b0086928231b6..a051ab626383b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -416,6 +416,7 @@ symbols! { asm, asm_const, asm_experimental_arch, + asm_experimental_reg, asm_goto, asm_sym, asm_unwind, diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 10778e9acf1fd..db8d23776e563 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -604,9 +604,13 @@ impl InlineAsmRegClass { /// Returns a list of supported types for this register class, each with an /// options target feature required to use this type. + /// + /// At the codegen stage, it is fine to always pass true for `allow_experimental_reg`, + /// since all the stability checking will have been done in prior stages. pub fn supported_types( self, arch: InlineAsmArch, + allow_experimental_reg: bool, ) -> &'static [(InlineAsmType, Option)] { match self { Self::X86(r) => r.supported_types(arch), @@ -618,7 +622,7 @@ impl InlineAsmRegClass { Self::Hexagon(r) => r.supported_types(arch), Self::LoongArch(r) => r.supported_types(arch), Self::Mips(r) => r.supported_types(arch), - Self::S390x(r) => r.supported_types(arch), + Self::S390x(r) => r.supported_types(arch, allow_experimental_reg), Self::Sparc(r) => r.supported_types(arch), Self::SpirV(r) => r.supported_types(arch), Self::Wasm(r) => r.supported_types(arch), @@ -696,8 +700,11 @@ impl InlineAsmRegClass { /// Returns whether registers in this class can only be used as clobbers /// and not as inputs/outputs. - pub fn is_clobber_only(self, arch: InlineAsmArch) -> bool { - self.supported_types(arch).is_empty() + /// + /// At the codegen stage, it is fine to always pass true for `allow_experimental_reg`, + /// since all the stability checking will have been done in prior stages. + pub fn is_clobber_only(self, arch: InlineAsmArch, allow_experimental_reg: bool) -> bool { + self.supported_types(arch, allow_experimental_reg).is_empty() } } diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index 426417e5bace8..410590b722b14 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -38,14 +38,22 @@ impl S390xInlineAsmRegClass { pub fn supported_types( self, _arch: InlineAsmArch, + allow_experimental_reg: bool, ) -> &'static [(InlineAsmType, Option)] { match self { Self::reg | Self::reg_addr => types! { _: I8, I16, I32, I64; }, Self::freg => types! { _: F32, F64; }, - Self::vreg => types! { - vector: I32, F32, I64, F64, I128, F128, - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); - }, + Self::vreg => { + if allow_experimental_reg { + // non-clobber-only vector register support is unstable. + types! { + vector: I32, F32, I64, F64, I128, F128, + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); + } + } else { + &[] + } + } Self::areg => &[], } } 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 new file mode 100644 index 0000000000000..a251573d276cb --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-experimental-reg.md @@ -0,0 +1,40 @@ +# `asm_experimental_arch` + +The tracking issue for this feature is: [#133416] + +[#133416]: https://github.com/rust-lang/rust/issues/133416 + +------------------------ + +This tracks support for additional registers in architectures where inline assembly is already stable. + +## Register classes + +| Architecture | Register class | Registers | LLVM constraint code | +| ------------ | -------------- | --------- | -------------------- | +| s390x | `vreg` | `v[0-31]` | `v` | + +> **Notes**: +> - s390x `vreg` is clobber-only in stable. + +## Register class supported types + +| Architecture | Register class | Target feature | Allowed types | +| ------------ | -------------- | -------------- | ------------- | +| s390x | `vreg` | `vector` | `i32`, `f32`, `i64`, `f64`, `i128`, `f128`, `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | + +## Register aliases + +| Architecture | Base register | Aliases | +| ------------ | ------------- | ------- | + +## Unsupported registers + +| Architecture | Unsupported register | Reason | +| ------------ | -------------------- | ------ | + +## Template modifiers + +| Architecture | Register class | Modifier | Example output | LLVM modifier | +| ------------ | -------------- | -------- | -------------- | ------------- | +| s390x | `vreg` | None | `%v0` | None | diff --git a/tests/assembly/asm/s390x-types.rs b/tests/assembly/asm/s390x-types.rs index 2103b38f9d7bc..3da22d6c77b62 100644 --- a/tests/assembly/asm/s390x-types.rs +++ b/tests/assembly/asm/s390x-types.rs @@ -7,6 +7,7 @@ //@ compile-flags: -Zmerge-functions=disabled #![feature(no_core, lang_items, rustc_attrs, repr_simd, f128)] +#![cfg_attr(s390x_vector, feature(asm_experimental_reg))] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] diff --git a/tests/ui/asm/s390x/bad-reg.rs b/tests/ui/asm/s390x/bad-reg.rs index 28877b822af68..144215b1a3d35 100644 --- a/tests/ui/asm/s390x/bad-reg.rs +++ b/tests/ui/asm/s390x/bad-reg.rs @@ -1,13 +1,16 @@ //@ add-core-stubs //@ needs-asm-support -//@ revisions: s390x s390x_vector +//@ revisions: s390x s390x_vector s390x_vector_stable //@[s390x] compile-flags: --target s390x-unknown-linux-gnu //@[s390x] needs-llvm-components: systemz //@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector //@[s390x_vector] needs-llvm-components: systemz +//@[s390x_vector_stable] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector +//@[s390x_vector_stable] needs-llvm-components: systemz #![crate_type = "rlib"] #![feature(no_core, rustc_attrs, repr_simd)] +#![cfg_attr(not(s390x_vector_stable), feature(asm_experimental_reg))] #![no_core] #![allow(non_camel_case_types)] @@ -68,29 +71,48 @@ fn f() { // vreg asm!("", out("v0") _); // always ok - asm!("", in("v0") v); // requires vector + asm!("", in("v0") v); // requires vector & asm_experimental_reg //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature - asm!("", out("v0") v); // requires vector + //[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658] + //[s390x_vector_stable]~| ERROR type `i64x2` cannot be used with this register class in stable [E0658] + asm!("", out("v0") v); // requires vector & asm_experimental_reg //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature - asm!("", in("v0") x); // requires vector + //[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658] + //[s390x_vector_stable]~| ERROR type `i64x2` cannot be used with this register class in stable [E0658] + asm!("", in("v0") x); // requires vector & asm_experimental_reg //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature - asm!("", out("v0") x); // requires vector + //[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658] + //[s390x_vector_stable]~| ERROR type `i32` cannot be used with this register class in stable [E0658] + asm!("", out("v0") x); // requires vector & asm_experimental_reg //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + //[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658] + //[s390x_vector_stable]~| ERROR type `i32` cannot be used with this register class in stable [E0658] asm!("", in("v0") b); //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature //[s390x_vector]~^^ ERROR type `u8` cannot be used with this register class + //[s390x_vector_stable]~^^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658] + //[s390x_vector_stable]~| ERROR type `u8` cannot be used with this register class asm!("", out("v0") b); //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature //[s390x_vector]~^^ ERROR type `u8` cannot be used with this register class - asm!("/* {} */", in(vreg) v); // requires vector + //[s390x_vector_stable]~^^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658] + //[s390x_vector_stable]~| ERROR type `u8` cannot be used with this register class + asm!("/* {} */", in(vreg) v); // requires vector & asm_experimental_reg //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature - asm!("/* {} */", in(vreg) x); // requires vector + //[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658] + //[s390x_vector_stable]~| ERROR type `i64x2` cannot be used with this register class in stable [E0658] + asm!("/* {} */", in(vreg) x); // requires vector & asm_experimental_reg //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + //[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658] + //[s390x_vector_stable]~| ERROR type `i32` cannot be used with this register class in stable [E0658] asm!("/* {} */", in(vreg) b); //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature //[s390x_vector]~^^ ERROR type `u8` cannot be used with this register class - asm!("/* {} */", out(vreg) _); // requires vector + //[s390x_vector_stable]~^^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658] + //[s390x_vector_stable]~| ERROR type `u8` cannot be used with this register class + asm!("/* {} */", out(vreg) _); // requires vector & asm_experimental_reg //[s390x]~^ ERROR register class `vreg` requires the `vector` target feature + //[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658] // Clobber-only registers // areg diff --git a/tests/ui/asm/s390x/bad-reg.s390x.stderr b/tests/ui/asm/s390x/bad-reg.s390x.stderr index 20c26096f8b5b..238419b376b7f 100644 --- a/tests/ui/asm/s390x/bad-reg.s390x.stderr +++ b/tests/ui/asm/s390x/bad-reg.s390x.stderr @@ -1,149 +1,149 @@ error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("r11") _); | ^^^^^^^^^^^^ error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("r15") _); | ^^^^^^^^^^^^ error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", out("c0") _); | ^^^^^^^^^^^ error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:37:18 | LL | asm!("", out("c1") _); | ^^^^^^^^^^^ error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:39:18 | LL | asm!("", out("c2") _); | ^^^^^^^^^^^ error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:41:18 | LL | asm!("", out("c3") _); | ^^^^^^^^^^^ error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", out("c4") _); | ^^^^^^^^^^^ error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", out("c5") _); | ^^^^^^^^^^^ error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:47:18 | LL | asm!("", out("c6") _); | ^^^^^^^^^^^ error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", out("c7") _); | ^^^^^^^^^^^ error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", out("c8") _); | ^^^^^^^^^^^ error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:50:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", out("c9") _); | ^^^^^^^^^^^ error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:52:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("c10") _); | ^^^^^^^^^^^^ error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:54:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", out("c11") _); | ^^^^^^^^^^^^ error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:56:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", out("c12") _); | ^^^^^^^^^^^^ error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:58:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("c13") _); | ^^^^^^^^^^^^ error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:60:18 + --> $DIR/bad-reg.rs:63:18 | LL | asm!("", out("c14") _); | ^^^^^^^^^^^^ error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:62:18 + --> $DIR/bad-reg.rs:65:18 | LL | asm!("", out("c15") _); | ^^^^^^^^^^^^ error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:64:18 + --> $DIR/bad-reg.rs:67:18 | LL | asm!("", out("a0") _); | ^^^^^^^^^^^ error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:69:18 | LL | asm!("", out("a1") _); | ^^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:98:18 + --> $DIR/bad-reg.rs:120:18 | LL | asm!("", in("a2") x); | ^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:101:18 + --> $DIR/bad-reg.rs:123:18 | LL | asm!("", out("a2") x); | ^^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:104:26 + --> $DIR/bad-reg.rs:126:26 | LL | asm!("/* {} */", in(areg) x); | ^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:107:26 + --> $DIR/bad-reg.rs:129:26 | LL | asm!("/* {} */", out(areg) _); | ^^^^^^^^^^^ error: register `f0` conflicts with register `v0` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:134:31 | LL | asm!("", out("v0") _, out("f0") _); | ----------- ^^^^^^^^^^^ register `f0` @@ -151,7 +151,7 @@ LL | asm!("", out("v0") _, out("f0") _); | register `v0` error: register `f1` conflicts with register `v1` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:136:31 | LL | asm!("", out("v1") _, out("f1") _); | ----------- ^^^^^^^^^^^ register `f1` @@ -159,7 +159,7 @@ LL | asm!("", out("v1") _, out("f1") _); | register `v1` error: register `f2` conflicts with register `v2` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:138:31 | LL | asm!("", out("v2") _, out("f2") _); | ----------- ^^^^^^^^^^^ register `f2` @@ -167,7 +167,7 @@ LL | asm!("", out("v2") _, out("f2") _); | register `v2` error: register `f3` conflicts with register `v3` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:140:31 | LL | asm!("", out("v3") _, out("f3") _); | ----------- ^^^^^^^^^^^ register `f3` @@ -175,7 +175,7 @@ LL | asm!("", out("v3") _, out("f3") _); | register `v3` error: register `f4` conflicts with register `v4` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:142:31 | LL | asm!("", out("v4") _, out("f4") _); | ----------- ^^^^^^^^^^^ register `f4` @@ -183,7 +183,7 @@ LL | asm!("", out("v4") _, out("f4") _); | register `v4` error: register `f5` conflicts with register `v5` - --> $DIR/bad-reg.rs:122:31 + --> $DIR/bad-reg.rs:144:31 | LL | asm!("", out("v5") _, out("f5") _); | ----------- ^^^^^^^^^^^ register `f5` @@ -191,7 +191,7 @@ LL | asm!("", out("v5") _, out("f5") _); | register `v5` error: register `f6` conflicts with register `v6` - --> $DIR/bad-reg.rs:124:31 + --> $DIR/bad-reg.rs:146:31 | LL | asm!("", out("v6") _, out("f6") _); | ----------- ^^^^^^^^^^^ register `f6` @@ -199,7 +199,7 @@ LL | asm!("", out("v6") _, out("f6") _); | register `v6` error: register `f7` conflicts with register `v7` - --> $DIR/bad-reg.rs:126:31 + --> $DIR/bad-reg.rs:148:31 | LL | asm!("", out("v7") _, out("f7") _); | ----------- ^^^^^^^^^^^ register `f7` @@ -207,7 +207,7 @@ LL | asm!("", out("v7") _, out("f7") _); | register `v7` error: register `f8` conflicts with register `v8` - --> $DIR/bad-reg.rs:128:31 + --> $DIR/bad-reg.rs:150:31 | LL | asm!("", out("v8") _, out("f8") _); | ----------- ^^^^^^^^^^^ register `f8` @@ -215,7 +215,7 @@ LL | asm!("", out("v8") _, out("f8") _); | register `v8` error: register `f9` conflicts with register `v9` - --> $DIR/bad-reg.rs:130:31 + --> $DIR/bad-reg.rs:152:31 | LL | asm!("", out("v9") _, out("f9") _); | ----------- ^^^^^^^^^^^ register `f9` @@ -223,7 +223,7 @@ LL | asm!("", out("v9") _, out("f9") _); | register `v9` error: register `f10` conflicts with register `v10` - --> $DIR/bad-reg.rs:132:32 + --> $DIR/bad-reg.rs:154:32 | LL | asm!("", out("v10") _, out("f10") _); | ------------ ^^^^^^^^^^^^ register `f10` @@ -231,7 +231,7 @@ LL | asm!("", out("v10") _, out("f10") _); | register `v10` error: register `f11` conflicts with register `v11` - --> $DIR/bad-reg.rs:134:32 + --> $DIR/bad-reg.rs:156:32 | LL | asm!("", out("v11") _, out("f11") _); | ------------ ^^^^^^^^^^^^ register `f11` @@ -239,7 +239,7 @@ LL | asm!("", out("v11") _, out("f11") _); | register `v11` error: register `f12` conflicts with register `v12` - --> $DIR/bad-reg.rs:136:32 + --> $DIR/bad-reg.rs:158:32 | LL | asm!("", out("v12") _, out("f12") _); | ------------ ^^^^^^^^^^^^ register `f12` @@ -247,7 +247,7 @@ LL | asm!("", out("v12") _, out("f12") _); | register `v12` error: register `f13` conflicts with register `v13` - --> $DIR/bad-reg.rs:138:32 + --> $DIR/bad-reg.rs:160:32 | LL | asm!("", out("v13") _, out("f13") _); | ------------ ^^^^^^^^^^^^ register `f13` @@ -255,7 +255,7 @@ LL | asm!("", out("v13") _, out("f13") _); | register `v13` error: register `f14` conflicts with register `v14` - --> $DIR/bad-reg.rs:140:32 + --> $DIR/bad-reg.rs:162:32 | LL | asm!("", out("v14") _, out("f14") _); | ------------ ^^^^^^^^^^^^ register `f14` @@ -263,7 +263,7 @@ LL | asm!("", out("v14") _, out("f14") _); | register `v14` error: register `f15` conflicts with register `v15` - --> $DIR/bad-reg.rs:142:32 + --> $DIR/bad-reg.rs:164:32 | LL | asm!("", out("v15") _, out("f15") _); | ------------ ^^^^^^^^^^^^ register `f15` @@ -271,73 +271,73 @@ LL | asm!("", out("v15") _, out("f15") _); | register `v15` error: invalid register `f16`: unknown register - --> $DIR/bad-reg.rs:145:32 + --> $DIR/bad-reg.rs:167:32 | LL | asm!("", out("v16") _, out("f16") _); | ^^^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:71:18 + --> $DIR/bad-reg.rs:74:18 | -LL | asm!("", in("v0") v); // requires vector +LL | asm!("", in("v0") v); // requires vector & asm_experimental_reg | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:73:18 + --> $DIR/bad-reg.rs:78:18 | -LL | asm!("", out("v0") v); // requires vector +LL | asm!("", out("v0") v); // requires vector & asm_experimental_reg | ^^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:75:18 + --> $DIR/bad-reg.rs:82:18 | -LL | asm!("", in("v0") x); // requires vector +LL | asm!("", in("v0") x); // requires vector & asm_experimental_reg | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:77:18 + --> $DIR/bad-reg.rs:86:18 | -LL | asm!("", out("v0") x); // requires vector +LL | asm!("", out("v0") x); // requires vector & asm_experimental_reg | ^^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:79:18 + --> $DIR/bad-reg.rs:90:18 | LL | asm!("", in("v0") b); | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:82:18 + --> $DIR/bad-reg.rs:95:18 | LL | asm!("", out("v0") b); | ^^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:85:26 + --> $DIR/bad-reg.rs:100:26 | -LL | asm!("/* {} */", in(vreg) v); // requires vector +LL | asm!("/* {} */", in(vreg) v); // requires vector & asm_experimental_reg | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:87:26 + --> $DIR/bad-reg.rs:104:26 | -LL | asm!("/* {} */", in(vreg) x); // requires vector +LL | asm!("/* {} */", in(vreg) x); // requires vector & asm_experimental_reg | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:89:26 + --> $DIR/bad-reg.rs:108:26 | LL | asm!("/* {} */", in(vreg) b); | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:92:26 + --> $DIR/bad-reg.rs:113:26 | -LL | asm!("/* {} */", out(vreg) _); // requires vector +LL | asm!("/* {} */", out(vreg) _); // requires vector & asm_experimental_reg | ^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:98:27 + --> $DIR/bad-reg.rs:120:27 | LL | asm!("", in("a2") x); | ^ @@ -345,7 +345,7 @@ LL | asm!("", in("a2") x); = note: register class `areg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:101:28 + --> $DIR/bad-reg.rs:123:28 | LL | asm!("", out("a2") x); | ^ @@ -353,7 +353,7 @@ LL | asm!("", out("a2") x); = note: register class `areg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:104:35 + --> $DIR/bad-reg.rs:126:35 | LL | asm!("/* {} */", in(areg) x); | ^ diff --git a/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr b/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr index 1ca18a5d84334..897f872ae72af 100644 --- a/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr +++ b/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr @@ -1,149 +1,149 @@ error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("r11") _); | ^^^^^^^^^^^^ error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("r15") _); | ^^^^^^^^^^^^ error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", out("c0") _); | ^^^^^^^^^^^ error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:37:18 | LL | asm!("", out("c1") _); | ^^^^^^^^^^^ error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:39:18 | LL | asm!("", out("c2") _); | ^^^^^^^^^^^ error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:41:18 | LL | asm!("", out("c3") _); | ^^^^^^^^^^^ error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", out("c4") _); | ^^^^^^^^^^^ error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", out("c5") _); | ^^^^^^^^^^^ error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:47:18 | LL | asm!("", out("c6") _); | ^^^^^^^^^^^ error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", out("c7") _); | ^^^^^^^^^^^ error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", out("c8") _); | ^^^^^^^^^^^ error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:50:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", out("c9") _); | ^^^^^^^^^^^ error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:52:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("c10") _); | ^^^^^^^^^^^^ error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:54:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", out("c11") _); | ^^^^^^^^^^^^ error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:56:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", out("c12") _); | ^^^^^^^^^^^^ error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:58:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("c13") _); | ^^^^^^^^^^^^ error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:60:18 + --> $DIR/bad-reg.rs:63:18 | LL | asm!("", out("c14") _); | ^^^^^^^^^^^^ error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:62:18 + --> $DIR/bad-reg.rs:65:18 | LL | asm!("", out("c15") _); | ^^^^^^^^^^^^ error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:64:18 + --> $DIR/bad-reg.rs:67:18 | LL | asm!("", out("a0") _); | ^^^^^^^^^^^ error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:69:18 | LL | asm!("", out("a1") _); | ^^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:98:18 + --> $DIR/bad-reg.rs:120:18 | LL | asm!("", in("a2") x); | ^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:101:18 + --> $DIR/bad-reg.rs:123:18 | LL | asm!("", out("a2") x); | ^^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:104:26 + --> $DIR/bad-reg.rs:126:26 | LL | asm!("/* {} */", in(areg) x); | ^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:107:26 + --> $DIR/bad-reg.rs:129:26 | LL | asm!("/* {} */", out(areg) _); | ^^^^^^^^^^^ error: register `f0` conflicts with register `v0` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:134:31 | LL | asm!("", out("v0") _, out("f0") _); | ----------- ^^^^^^^^^^^ register `f0` @@ -151,7 +151,7 @@ LL | asm!("", out("v0") _, out("f0") _); | register `v0` error: register `f1` conflicts with register `v1` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:136:31 | LL | asm!("", out("v1") _, out("f1") _); | ----------- ^^^^^^^^^^^ register `f1` @@ -159,7 +159,7 @@ LL | asm!("", out("v1") _, out("f1") _); | register `v1` error: register `f2` conflicts with register `v2` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:138:31 | LL | asm!("", out("v2") _, out("f2") _); | ----------- ^^^^^^^^^^^ register `f2` @@ -167,7 +167,7 @@ LL | asm!("", out("v2") _, out("f2") _); | register `v2` error: register `f3` conflicts with register `v3` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:140:31 | LL | asm!("", out("v3") _, out("f3") _); | ----------- ^^^^^^^^^^^ register `f3` @@ -175,7 +175,7 @@ LL | asm!("", out("v3") _, out("f3") _); | register `v3` error: register `f4` conflicts with register `v4` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:142:31 | LL | asm!("", out("v4") _, out("f4") _); | ----------- ^^^^^^^^^^^ register `f4` @@ -183,7 +183,7 @@ LL | asm!("", out("v4") _, out("f4") _); | register `v4` error: register `f5` conflicts with register `v5` - --> $DIR/bad-reg.rs:122:31 + --> $DIR/bad-reg.rs:144:31 | LL | asm!("", out("v5") _, out("f5") _); | ----------- ^^^^^^^^^^^ register `f5` @@ -191,7 +191,7 @@ LL | asm!("", out("v5") _, out("f5") _); | register `v5` error: register `f6` conflicts with register `v6` - --> $DIR/bad-reg.rs:124:31 + --> $DIR/bad-reg.rs:146:31 | LL | asm!("", out("v6") _, out("f6") _); | ----------- ^^^^^^^^^^^ register `f6` @@ -199,7 +199,7 @@ LL | asm!("", out("v6") _, out("f6") _); | register `v6` error: register `f7` conflicts with register `v7` - --> $DIR/bad-reg.rs:126:31 + --> $DIR/bad-reg.rs:148:31 | LL | asm!("", out("v7") _, out("f7") _); | ----------- ^^^^^^^^^^^ register `f7` @@ -207,7 +207,7 @@ LL | asm!("", out("v7") _, out("f7") _); | register `v7` error: register `f8` conflicts with register `v8` - --> $DIR/bad-reg.rs:128:31 + --> $DIR/bad-reg.rs:150:31 | LL | asm!("", out("v8") _, out("f8") _); | ----------- ^^^^^^^^^^^ register `f8` @@ -215,7 +215,7 @@ LL | asm!("", out("v8") _, out("f8") _); | register `v8` error: register `f9` conflicts with register `v9` - --> $DIR/bad-reg.rs:130:31 + --> $DIR/bad-reg.rs:152:31 | LL | asm!("", out("v9") _, out("f9") _); | ----------- ^^^^^^^^^^^ register `f9` @@ -223,7 +223,7 @@ LL | asm!("", out("v9") _, out("f9") _); | register `v9` error: register `f10` conflicts with register `v10` - --> $DIR/bad-reg.rs:132:32 + --> $DIR/bad-reg.rs:154:32 | LL | asm!("", out("v10") _, out("f10") _); | ------------ ^^^^^^^^^^^^ register `f10` @@ -231,7 +231,7 @@ LL | asm!("", out("v10") _, out("f10") _); | register `v10` error: register `f11` conflicts with register `v11` - --> $DIR/bad-reg.rs:134:32 + --> $DIR/bad-reg.rs:156:32 | LL | asm!("", out("v11") _, out("f11") _); | ------------ ^^^^^^^^^^^^ register `f11` @@ -239,7 +239,7 @@ LL | asm!("", out("v11") _, out("f11") _); | register `v11` error: register `f12` conflicts with register `v12` - --> $DIR/bad-reg.rs:136:32 + --> $DIR/bad-reg.rs:158:32 | LL | asm!("", out("v12") _, out("f12") _); | ------------ ^^^^^^^^^^^^ register `f12` @@ -247,7 +247,7 @@ LL | asm!("", out("v12") _, out("f12") _); | register `v12` error: register `f13` conflicts with register `v13` - --> $DIR/bad-reg.rs:138:32 + --> $DIR/bad-reg.rs:160:32 | LL | asm!("", out("v13") _, out("f13") _); | ------------ ^^^^^^^^^^^^ register `f13` @@ -255,7 +255,7 @@ LL | asm!("", out("v13") _, out("f13") _); | register `v13` error: register `f14` conflicts with register `v14` - --> $DIR/bad-reg.rs:140:32 + --> $DIR/bad-reg.rs:162:32 | LL | asm!("", out("v14") _, out("f14") _); | ------------ ^^^^^^^^^^^^ register `f14` @@ -263,7 +263,7 @@ LL | asm!("", out("v14") _, out("f14") _); | register `v14` error: register `f15` conflicts with register `v15` - --> $DIR/bad-reg.rs:142:32 + --> $DIR/bad-reg.rs:164:32 | LL | asm!("", out("v15") _, out("f15") _); | ------------ ^^^^^^^^^^^^ register `f15` @@ -271,13 +271,13 @@ LL | asm!("", out("v15") _, out("f15") _); | register `v15` error: invalid register `f16`: unknown register - --> $DIR/bad-reg.rs:145:32 + --> $DIR/bad-reg.rs:167:32 | LL | asm!("", out("v16") _, out("f16") _); | ^^^^^^^^^^^^ error: type `u8` cannot be used with this register class - --> $DIR/bad-reg.rs:79:27 + --> $DIR/bad-reg.rs:90:27 | LL | asm!("", in("v0") b); | ^ @@ -285,7 +285,7 @@ LL | asm!("", in("v0") b); = note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 error: type `u8` cannot be used with this register class - --> $DIR/bad-reg.rs:82:28 + --> $DIR/bad-reg.rs:95:28 | LL | asm!("", out("v0") b); | ^ @@ -293,7 +293,7 @@ LL | asm!("", out("v0") b); = note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 error: type `u8` cannot be used with this register class - --> $DIR/bad-reg.rs:89:35 + --> $DIR/bad-reg.rs:108:35 | LL | asm!("/* {} */", in(vreg) b); | ^ @@ -301,7 +301,7 @@ LL | asm!("/* {} */", in(vreg) b); = note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:98:27 + --> $DIR/bad-reg.rs:120:27 | LL | asm!("", in("a2") x); | ^ @@ -309,7 +309,7 @@ LL | asm!("", in("a2") x); = note: register class `areg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:101:28 + --> $DIR/bad-reg.rs:123:28 | LL | asm!("", out("a2") x); | ^ @@ -317,7 +317,7 @@ LL | asm!("", out("a2") x); = note: register class `areg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:104:35 + --> $DIR/bad-reg.rs:126:35 | LL | asm!("/* {} */", in(areg) x); | ^ diff --git a/tests/ui/asm/s390x/bad-reg.s390x_vector_stable.stderr b/tests/ui/asm/s390x/bad-reg.s390x_vector_stable.stderr new file mode 100644 index 0000000000000..e2b3eeef4e925 --- /dev/null +++ b/tests/ui/asm/s390x/bad-reg.s390x_vector_stable.stderr @@ -0,0 +1,489 @@ +error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:31:18 + | +LL | asm!("", out("r11") _); + | ^^^^^^^^^^^^ + +error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:33:18 + | +LL | asm!("", out("r15") _); + | ^^^^^^^^^^^^ + +error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:35:18 + | +LL | asm!("", out("c0") _); + | ^^^^^^^^^^^ + +error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:37:18 + | +LL | asm!("", out("c1") _); + | ^^^^^^^^^^^ + +error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:39:18 + | +LL | asm!("", out("c2") _); + | ^^^^^^^^^^^ + +error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:41:18 + | +LL | asm!("", out("c3") _); + | ^^^^^^^^^^^ + +error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:43:18 + | +LL | asm!("", out("c4") _); + | ^^^^^^^^^^^ + +error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:45:18 + | +LL | asm!("", out("c5") _); + | ^^^^^^^^^^^ + +error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:47:18 + | +LL | asm!("", out("c6") _); + | ^^^^^^^^^^^ + +error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:49:18 + | +LL | asm!("", out("c7") _); + | ^^^^^^^^^^^ + +error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:51:18 + | +LL | asm!("", out("c8") _); + | ^^^^^^^^^^^ + +error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:53:18 + | +LL | asm!("", out("c9") _); + | ^^^^^^^^^^^ + +error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:55:18 + | +LL | asm!("", out("c10") _); + | ^^^^^^^^^^^^ + +error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:57:18 + | +LL | asm!("", out("c11") _); + | ^^^^^^^^^^^^ + +error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:59:18 + | +LL | asm!("", out("c12") _); + | ^^^^^^^^^^^^ + +error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:61:18 + | +LL | asm!("", out("c13") _); + | ^^^^^^^^^^^^ + +error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:63:18 + | +LL | asm!("", out("c14") _); + | ^^^^^^^^^^^^ + +error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:65:18 + | +LL | asm!("", out("c15") _); + | ^^^^^^^^^^^^ + +error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:67:18 + | +LL | asm!("", out("a0") _); + | ^^^^^^^^^^^ + +error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:69:18 + | +LL | asm!("", out("a1") _); + | ^^^^^^^^^^^ + +error[E0658]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:74:18 + | +LL | asm!("", in("v0") v); // requires vector & asm_experimental_reg + | ^^^^^^^^^^ + | + = 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]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:78:18 + | +LL | asm!("", out("v0") v); // requires vector & asm_experimental_reg + | ^^^^^^^^^^^ + | + = 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]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:82:18 + | +LL | asm!("", in("v0") x); // requires vector & asm_experimental_reg + | ^^^^^^^^^^ + | + = 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]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:86:18 + | +LL | asm!("", out("v0") x); // requires vector & asm_experimental_reg + | ^^^^^^^^^^^ + | + = 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]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:90:18 + | +LL | asm!("", in("v0") b); + | ^^^^^^^^^^ + | + = 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]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:95:18 + | +LL | asm!("", out("v0") b); + | ^^^^^^^^^^^ + | + = 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]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:100:26 + | +LL | asm!("/* {} */", in(vreg) v); // requires vector & asm_experimental_reg + | ^^^^^^^^^^ + | + = 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]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:104:26 + | +LL | asm!("/* {} */", in(vreg) x); // requires vector & asm_experimental_reg + | ^^^^^^^^^^ + | + = 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]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:108:26 + | +LL | asm!("/* {} */", in(vreg) b); + | ^^^^^^^^^^ + | + = 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]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:113:26 + | +LL | asm!("/* {} */", out(vreg) _); // requires vector & asm_experimental_reg + | ^^^^^^^^^^^ + | + = 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: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:120:18 + | +LL | asm!("", in("a2") x); + | ^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:123:18 + | +LL | asm!("", out("a2") x); + | ^^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:126:26 + | +LL | asm!("/* {} */", in(areg) x); + | ^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:129:26 + | +LL | asm!("/* {} */", out(areg) _); + | ^^^^^^^^^^^ + +error: register `f0` conflicts with register `v0` + --> $DIR/bad-reg.rs:134:31 + | +LL | asm!("", out("v0") _, out("f0") _); + | ----------- ^^^^^^^^^^^ register `f0` + | | + | register `v0` + +error: register `f1` conflicts with register `v1` + --> $DIR/bad-reg.rs:136:31 + | +LL | asm!("", out("v1") _, out("f1") _); + | ----------- ^^^^^^^^^^^ register `f1` + | | + | register `v1` + +error: register `f2` conflicts with register `v2` + --> $DIR/bad-reg.rs:138:31 + | +LL | asm!("", out("v2") _, out("f2") _); + | ----------- ^^^^^^^^^^^ register `f2` + | | + | register `v2` + +error: register `f3` conflicts with register `v3` + --> $DIR/bad-reg.rs:140:31 + | +LL | asm!("", out("v3") _, out("f3") _); + | ----------- ^^^^^^^^^^^ register `f3` + | | + | register `v3` + +error: register `f4` conflicts with register `v4` + --> $DIR/bad-reg.rs:142:31 + | +LL | asm!("", out("v4") _, out("f4") _); + | ----------- ^^^^^^^^^^^ register `f4` + | | + | register `v4` + +error: register `f5` conflicts with register `v5` + --> $DIR/bad-reg.rs:144:31 + | +LL | asm!("", out("v5") _, out("f5") _); + | ----------- ^^^^^^^^^^^ register `f5` + | | + | register `v5` + +error: register `f6` conflicts with register `v6` + --> $DIR/bad-reg.rs:146:31 + | +LL | asm!("", out("v6") _, out("f6") _); + | ----------- ^^^^^^^^^^^ register `f6` + | | + | register `v6` + +error: register `f7` conflicts with register `v7` + --> $DIR/bad-reg.rs:148:31 + | +LL | asm!("", out("v7") _, out("f7") _); + | ----------- ^^^^^^^^^^^ register `f7` + | | + | register `v7` + +error: register `f8` conflicts with register `v8` + --> $DIR/bad-reg.rs:150:31 + | +LL | asm!("", out("v8") _, out("f8") _); + | ----------- ^^^^^^^^^^^ register `f8` + | | + | register `v8` + +error: register `f9` conflicts with register `v9` + --> $DIR/bad-reg.rs:152:31 + | +LL | asm!("", out("v9") _, out("f9") _); + | ----------- ^^^^^^^^^^^ register `f9` + | | + | register `v9` + +error: register `f10` conflicts with register `v10` + --> $DIR/bad-reg.rs:154:32 + | +LL | asm!("", out("v10") _, out("f10") _); + | ------------ ^^^^^^^^^^^^ register `f10` + | | + | register `v10` + +error: register `f11` conflicts with register `v11` + --> $DIR/bad-reg.rs:156:32 + | +LL | asm!("", out("v11") _, out("f11") _); + | ------------ ^^^^^^^^^^^^ register `f11` + | | + | register `v11` + +error: register `f12` conflicts with register `v12` + --> $DIR/bad-reg.rs:158:32 + | +LL | asm!("", out("v12") _, out("f12") _); + | ------------ ^^^^^^^^^^^^ register `f12` + | | + | register `v12` + +error: register `f13` conflicts with register `v13` + --> $DIR/bad-reg.rs:160:32 + | +LL | asm!("", out("v13") _, out("f13") _); + | ------------ ^^^^^^^^^^^^ register `f13` + | | + | register `v13` + +error: register `f14` conflicts with register `v14` + --> $DIR/bad-reg.rs:162:32 + | +LL | asm!("", out("v14") _, out("f14") _); + | ------------ ^^^^^^^^^^^^ register `f14` + | | + | register `v14` + +error: register `f15` conflicts with register `v15` + --> $DIR/bad-reg.rs:164:32 + | +LL | asm!("", out("v15") _, out("f15") _); + | ------------ ^^^^^^^^^^^^ register `f15` + | | + | register `v15` + +error: invalid register `f16`: unknown register + --> $DIR/bad-reg.rs:167:32 + | +LL | asm!("", out("v16") _, out("f16") _); + | ^^^^^^^^^^^^ + +error[E0658]: type `i64x2` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:74:27 + | +LL | asm!("", in("v0") v); // requires vector & asm_experimental_reg + | ^ + | + = 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 `i64x2` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:78:28 + | +LL | asm!("", out("v0") v); // requires vector & asm_experimental_reg + | ^ + | + = 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 `i32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:82:27 + | +LL | asm!("", in("v0") x); // requires vector & asm_experimental_reg + | ^ + | + = 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 `i32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:86:28 + | +LL | asm!("", out("v0") x); // requires vector & asm_experimental_reg + | ^ + | + = 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: type `u8` cannot be used with this register class + --> $DIR/bad-reg.rs:90:27 + | +LL | asm!("", in("v0") b); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `u8` cannot be used with this register class + --> $DIR/bad-reg.rs:95:28 + | +LL | asm!("", out("v0") b); + | ^ + | + = note: register class `vreg` supports these types: + +error[E0658]: type `i64x2` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:100:35 + | +LL | asm!("/* {} */", in(vreg) v); // requires vector & asm_experimental_reg + | ^ + | + = 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 `i32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:104:35 + | +LL | asm!("/* {} */", in(vreg) x); // requires vector & asm_experimental_reg + | ^ + | + = 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: type `u8` cannot be used with this register class + --> $DIR/bad-reg.rs:108:35 + | +LL | asm!("/* {} */", in(vreg) b); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:120:27 + | +LL | asm!("", in("a2") x); + | ^ + | + = note: register class `areg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:123:28 + | +LL | asm!("", out("a2") x); + | ^ + | + = note: register class `areg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:126:35 + | +LL | asm!("/* {} */", in(areg) x); + | ^ + | + = note: register class `areg` supports these types: + +error: aborting due to 63 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs new file mode 100644 index 0000000000000..7aec7455b2e6a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs @@ -0,0 +1,23 @@ +//@ needs-asm-support +//@ compile-flags: --target s390x-unknown-linux-gnu +//@ needs-llvm-components: systemz + +#![feature(no_core, lang_items, rustc_attrs)] +#![crate_type = "rlib"] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +unsafe fn main() { + asm!("", in("v0") 0); + //~^ ERROR register class `vreg` can only be used as a clobber in stable + //~| ERROR type `i32` cannot be used with this register class +} diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr new file mode 100644 index 0000000000000..0791ce4543ca6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.stderr @@ -0,0 +1,23 @@ +error[E0658]: register class `vreg` can only be used as a clobber in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:20:14 + | +LL | asm!("", in("v0") 0); + | ^^^^^^^^^^ + | + = 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 `i32` cannot be used with this register class in stable + --> $DIR/feature-gate-asm_experimental_reg.rs:20:23 + | +LL | asm!("", in("v0") 0); + | ^ + | + = 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 2 previous errors + +For more information about this error, try `rustc --explain E0658`. From b8df869ebb9219b98ca798aacb16c9be3f84496b Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 11 Oct 2024 00:23:32 +0100 Subject: [PATCH 08/11] Fix asm goto with outputs When outputs are used together with labels, they are considered to be written for all destinations, not only when falling through. --- compiler/rustc_codegen_llvm/src/asm.rs | 35 ++++++++++----------- tests/codegen/asm/goto.rs | 24 ++++++++------- tests/ui/asm/x86_64/goto.rs | 42 +++++++++++++++++++++----- tests/ui/asm/x86_64/goto.stderr | 4 +-- 4 files changed, 68 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index bb74dfe148703..2455d13df8df7 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -342,24 +342,25 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs }); - // Switch to the 'normal' basic block if we did an `invoke` instead of a `call` - if let Some(dest) = dest { - self.switch_to_block(dest); - } + // Write results to outputs. We need to do this for all possible control flow. + for block in Some(dest).into_iter().chain(labels.iter().copied().map(Some)) { + if let Some(block) = block { + self.switch_to_block(block); + } - // Write results to outputs - for (idx, op) in operands.iter().enumerate() { - if let InlineAsmOperandRef::Out { reg, place: Some(place), .. } - | InlineAsmOperandRef::InOut { reg, out_place: Some(place), .. } = *op - { - let value = if output_types.len() == 1 { - result - } else { - self.extract_value(result, op_idx[&idx] as u64) - }; - let value = - llvm_fixup_output(self, value, reg.reg_class(), &place.layout, instance); - OperandValue::Immediate(value).store(self, place); + for (idx, op) in operands.iter().enumerate() { + if let InlineAsmOperandRef::Out { reg, place: Some(place), .. } + | InlineAsmOperandRef::InOut { reg, out_place: Some(place), .. } = *op + { + let value = if output_types.len() == 1 { + result + } else { + self.extract_value(result, op_idx[&idx] as u64) + }; + let value = + llvm_fixup_output(self, value, reg.reg_class(), &place.layout, instance); + OperandValue::Immediate(value).store(self, place); + } } } } diff --git a/tests/codegen/asm/goto.rs b/tests/codegen/asm/goto.rs index e522d0da5b405..0e69c4d58407d 100644 --- a/tests/codegen/asm/goto.rs +++ b/tests/codegen/asm/goto.rs @@ -6,17 +6,6 @@ use std::arch::asm; -#[no_mangle] -pub extern "C" fn panicky() {} - -struct Foo; - -impl Drop for Foo { - fn drop(&mut self) { - println!(); - } -} - // CHECK-LABEL: @asm_goto #[no_mangle] pub unsafe fn asm_goto() { @@ -38,6 +27,19 @@ pub unsafe fn asm_goto_with_outputs() -> u64 { out } +// CHECK-LABEL: @asm_goto_with_outputs_use_in_label +#[no_mangle] +pub unsafe fn asm_goto_with_outputs_use_in_label() -> u64 { + let out: u64; + // CHECK: [[RES:%[0-9]+]] = callbr i64 asm sideeffect alignstack inteldialect " + // CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]] + asm!("{} /* {} */", out(reg) out, label { return out; }); + // CHECK: [[JUMPBB]]: + // CHECK-NEXT: [[RET:%.+]] = phi i64 [ 1, %[[FALLTHROUGHBB]] ], [ [[RES]], %start ] + // CHECK-NEXT: ret i64 [[RET]] + 1 +} + // CHECK-LABEL: @asm_goto_noreturn #[no_mangle] pub unsafe fn asm_goto_noreturn() -> u64 { diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs index 6c14bb57ac6e2..ab22317c45831 100644 --- a/tests/ui/asm/x86_64/goto.rs +++ b/tests/ui/asm/x86_64/goto.rs @@ -31,10 +31,6 @@ fn goto_jump() { } } -// asm goto with outputs cause miscompilation in LLVM. UB can be triggered -// when outputs are used inside the label block when optimisation is enabled. -// See: https://github.com/llvm/llvm-project/issues/74483 -/* fn goto_out_fallthrough() { unsafe { let mut out: usize; @@ -68,7 +64,38 @@ fn goto_out_jump() { assert!(value); } } -*/ + +// asm goto with outputs cause miscompilation in LLVM when multiple outputs are present. +// The code sample below is adapted from https://github.com/llvm/llvm-project/issues/74483 +// and does not work with `-C opt-level=0` +#[expect(unused)] +fn goto_multi_out() { + #[inline(never)] + #[allow(unused)] + fn goto_multi_out(a: usize, b: usize) -> usize { + let mut x: usize; + let mut y: usize; + let mut z: usize; + unsafe { + core::arch::asm!( + "mov {x}, {a}", + "test {a}, {a}", + "jnz {label1}", + "/* {y} {z} {b} {label2} */", + x = out(reg) x, + y = out(reg) y, + z = out(reg) z, + a = in(reg) a, + b = in(reg) b, + label1 = label { return x }, + label2 = label { return 1 }, + ); + 0 + } + } + + assert_eq!(goto_multi_out(11, 22), 11); +} fn goto_noreturn() { unsafe { @@ -102,8 +129,9 @@ fn goto_noreturn_diverge() { fn main() { goto_fallthough(); goto_jump(); - // goto_out_fallthrough(); - // goto_out_jump(); + goto_out_fallthrough(); + goto_out_jump(); + // goto_multi_out(); goto_noreturn(); goto_noreturn_diverge(); } diff --git a/tests/ui/asm/x86_64/goto.stderr b/tests/ui/asm/x86_64/goto.stderr index 27e227d71a5f5..216b4d252ec76 100644 --- a/tests/ui/asm/x86_64/goto.stderr +++ b/tests/ui/asm/x86_64/goto.stderr @@ -1,5 +1,5 @@ warning: unreachable statement - --> $DIR/goto.rs:97:9 + --> $DIR/goto.rs:124:9 | LL | / asm!( LL | | "jmp {}", @@ -13,7 +13,7 @@ LL | unreachable!(); | ^^^^^^^^^^^^^^ unreachable statement | note: the lint level is defined here - --> $DIR/goto.rs:87:8 + --> $DIR/goto.rs:114:8 | LL | #[warn(unreachable_code)] | ^^^^^^^^^^^^^^^^ From 73f8309300bce03e62c8a49e8a06b884175b5f88 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 11 Oct 2024 00:26:21 +0100 Subject: [PATCH 09/11] Support use of asm goto with outputs and `options(noreturn)` When labels are present, the `noreturn` option really means that asm block won't fallthrough -- if labels are present, then outputs can still be meaningfully used. --- compiler/rustc_builtin_macros/src/asm.rs | 5 ++++- compiler/rustc_codegen_llvm/src/asm.rs | 9 ++++++++- tests/codegen/asm/goto.rs | 12 +++++++++++- tests/ui/asm/x86_64/goto.rs | 20 ++++++++++++++++++++ tests/ui/asm/x86_64/goto.stderr | 4 ++-- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 9ae48024f445b..14ac3cd74e884 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -300,7 +300,10 @@ pub fn parse_asm_args<'a>( if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output { dcx.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() }); } - if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() { + if args.options.contains(ast::InlineAsmOptions::NORETURN) + && !outputs_sp.is_empty() + && labels_sp.is_empty() + { let err = dcx.create_err(errors::AsmNoReturn { outputs_sp }); // Bail out now since this is likely to confuse MIR return Err(err); diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 2455d13df8df7..07473190d6f74 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -343,7 +343,14 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs }); // Write results to outputs. We need to do this for all possible control flow. - for block in Some(dest).into_iter().chain(labels.iter().copied().map(Some)) { + // + // Note that `dest` maybe populated with unreachable_block when asm goto with outputs + // is used (because we need to codegen callbr which always needs a destination), so + // here we use the NORETURN option to determine if `dest` should be used. + for block in (if options.contains(InlineAsmOptions::NORETURN) { None } else { Some(dest) }) + .into_iter() + .chain(labels.iter().copied().map(Some)) + { if let Some(block) = block { self.switch_to_block(block); } diff --git a/tests/codegen/asm/goto.rs b/tests/codegen/asm/goto.rs index 0e69c4d58407d..3193d3aa145d3 100644 --- a/tests/codegen/asm/goto.rs +++ b/tests/codegen/asm/goto.rs @@ -43,11 +43,21 @@ pub unsafe fn asm_goto_with_outputs_use_in_label() -> u64 { // CHECK-LABEL: @asm_goto_noreturn #[no_mangle] pub unsafe fn asm_goto_noreturn() -> u64 { - let out: u64; // CHECK: callbr void asm sideeffect alignstack inteldialect " // CHECK-NEXT: to label %unreachable [label %[[JUMPBB:[a-b0-9]+]]] asm!("jmp {}", label { return 1; }, options(noreturn)); // CHECK: [[JUMPBB]]: // CHECK-NEXT: ret i64 1 +} + +// CHECK-LABEL: @asm_goto_noreturn_with_outputs +#[no_mangle] +pub unsafe fn asm_goto_noreturn_with_outputs() -> u64 { + let out: u64; + // CHECK: [[RES:%[0-9]+]] = callbr i64 asm sideeffect alignstack inteldialect " + // CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]] + asm!("mov {}, 1", "jmp {}", out(reg) out, label { return out; }); + // CHECK: [[JUMPBB]]: + // CHECK-NEXT: ret i64 [[RES]] out } diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs index ab22317c45831..d23018a05f540 100644 --- a/tests/ui/asm/x86_64/goto.rs +++ b/tests/ui/asm/x86_64/goto.rs @@ -65,6 +65,25 @@ fn goto_out_jump() { } } +fn goto_out_jump_noreturn() { + unsafe { + let mut value = false; + let mut out: usize; + asm!( + "lea {}, [{} + 1]", + "jmp {}", + out(reg) out, + in(reg) 0x12345678usize, + label { + value = true; + assert_eq!(out, 0x12345679); + }, + options(noreturn) + ); + assert!(value); + } +} + // asm goto with outputs cause miscompilation in LLVM when multiple outputs are present. // The code sample below is adapted from https://github.com/llvm/llvm-project/issues/74483 // and does not work with `-C opt-level=0` @@ -131,6 +150,7 @@ fn main() { goto_jump(); goto_out_fallthrough(); goto_out_jump(); + goto_out_jump_noreturn(); // goto_multi_out(); goto_noreturn(); goto_noreturn_diverge(); diff --git a/tests/ui/asm/x86_64/goto.stderr b/tests/ui/asm/x86_64/goto.stderr index 216b4d252ec76..8f89e2b129081 100644 --- a/tests/ui/asm/x86_64/goto.stderr +++ b/tests/ui/asm/x86_64/goto.stderr @@ -1,5 +1,5 @@ warning: unreachable statement - --> $DIR/goto.rs:124:9 + --> $DIR/goto.rs:143:9 | LL | / asm!( LL | | "jmp {}", @@ -13,7 +13,7 @@ LL | unreachable!(); | ^^^^^^^^^^^^^^ unreachable statement | note: the lint level is defined here - --> $DIR/goto.rs:114:8 + --> $DIR/goto.rs:133:8 | LL | #[warn(unreachable_code)] | ^^^^^^^^^^^^^^^^ From 0178ba2c2547c3677b5624d684a392dccae12abc Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 11 Oct 2024 00:27:16 +0100 Subject: [PATCH 10/11] Make asm_goto_with_outputs a separate feature gate --- compiler/rustc_ast_lowering/messages.ftl | 2 + compiler/rustc_ast_lowering/src/asm.rs | 44 +++++++++++++++---- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + tests/codegen/asm/goto.rs | 2 +- tests/ui/asm/x86_64/goto.rs | 2 +- .../feature-gate-asm_goto_with_outputs.rs | 13 ++++++ .../feature-gate-asm_goto_with_outputs.stderr | 13 ++++++ 8 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs create mode 100644 tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index f704320c71d72..93e1e25384ef9 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -181,6 +181,8 @@ ast_lowering_underscore_expr_lhs_assign = .label = `_` not allowed here ast_lowering_unstable_inline_assembly = inline assembly is not stable yet on this architecture +ast_lowering_unstable_inline_assembly_label_operand_with_outputs = + using both label and output operands for inline assembly is unstable ast_lowering_unstable_inline_assembly_label_operands = label operands for inline assembly are unstable ast_lowering_unstable_may_unwind = the `may_unwind` option is unstable diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 215e6d84d0f0a..520274278a1e6 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -239,15 +239,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } InlineAsmOperand::Label { block } => { - if !self.tcx.features().asm_goto() { - feature_err( - sess, - sym::asm_goto, - *op_sp, - fluent::ast_lowering_unstable_inline_assembly_label_operands, - ) - .emit(); - } hir::InlineAsmOperand::Label { block: self.lower_block(block, false) } } }; @@ -466,6 +457,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } + // Feature gate checking for asm goto. + if let Some((_, op_sp)) = + operands.iter().find(|(op, _)| matches!(op, hir::InlineAsmOperand::Label { .. })) + { + if !self.tcx.features().asm_goto() { + feature_err( + sess, + sym::asm_goto, + *op_sp, + fluent::ast_lowering_unstable_inline_assembly_label_operands, + ) + .emit(); + } + + // In addition, check if an output operand is used. + // This is gated behind an additional feature. + let output_operand_used = operands.iter().any(|(op, _)| { + matches!( + op, + hir::InlineAsmOperand::Out { expr: Some(_), .. } + | hir::InlineAsmOperand::InOut { .. } + | hir::InlineAsmOperand::SplitInOut { out_expr: Some(_), .. } + ) + }); + if output_operand_used && !self.tcx.features().asm_goto_with_outputs() { + feature_err( + sess, + sym::asm_goto_with_outputs, + *op_sp, + fluent::ast_lowering_unstable_inline_assembly_label_operand_with_outputs, + ) + .emit(); + } + } + let operands = self.arena.alloc_from_iter(operands); let template = self.arena.alloc_from_iter(asm.template.iter().cloned()); let template_strs = self.arena.alloc_from_iter( diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index cf0f2a7e48c93..6a23139761523 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -378,6 +378,8 @@ declare_features! ( (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Allows using `label` operands in inline assembly. (unstable, asm_goto, "1.78.0", Some(119364)), + /// Allows using `label` operands in inline assembly together with output operands. + (unstable, asm_goto_with_outputs, "CURRENT_RUSTC_VERSION", Some(119364)), /// Allows the `may_unwind` option in inline assembly. (unstable, asm_unwind, "1.58.0", Some(93334)), /// Allows users to enforce equality of associated constants `TraitImpl`. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3d0ec2afa2b73..0e4d937d6fdc2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -417,6 +417,7 @@ symbols! { asm_const, asm_experimental_arch, asm_goto, + asm_goto_with_outputs, asm_sym, asm_unwind, assert, diff --git a/tests/codegen/asm/goto.rs b/tests/codegen/asm/goto.rs index 3193d3aa145d3..c40a43fbe1bd3 100644 --- a/tests/codegen/asm/goto.rs +++ b/tests/codegen/asm/goto.rs @@ -2,7 +2,7 @@ //@ only-x86_64 #![crate_type = "rlib"] -#![feature(asm_goto)] +#![feature(asm_goto, asm_goto_with_outputs)] use std::arch::asm; diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs index d23018a05f540..50e7441509ac2 100644 --- a/tests/ui/asm/x86_64/goto.rs +++ b/tests/ui/asm/x86_64/goto.rs @@ -3,7 +3,7 @@ //@ needs-asm-support #![deny(unreachable_code)] -#![feature(asm_goto)] +#![feature(asm_goto, asm_goto_with_outputs)] use std::arch::asm; diff --git a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs new file mode 100644 index 0000000000000..294827f78d263 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs @@ -0,0 +1,13 @@ +//@ only-x86_64 + +#![feature(asm_goto)] + +use std::arch::asm; + +fn main() { + let mut _out: u64; + unsafe { + asm!("mov {}, 1", "jmp {}", out(reg) _out, label {}); + //~^ ERROR using both label and output operands for inline assembly is unstable + } +} diff --git a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr new file mode 100644 index 0000000000000..ff7a7d5760a7f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr @@ -0,0 +1,13 @@ +error[E0658]: using both label and output operands for inline assembly is unstable + --> $DIR/feature-gate-asm_goto_with_outputs.rs:10:52 + | +LL | asm!("mov {}, 1", "jmp {}", out(reg) _out, label {}); + | ^^^^^^^^ + | + = note: see issue #119364 for more information + = help: add `#![feature(asm_goto_with_outputs)]` 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 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 8542175b6fb30b1ad1321d1a8691971834bfe6db Mon Sep 17 00:00:00 2001 From: m Date: Sun, 24 Nov 2024 16:38:29 -0800 Subject: [PATCH 11/11] fix `Allocator` method names in `alloc` free function docs --- library/alloc/src/alloc.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 98402a4620158..04b7315e650a2 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -61,7 +61,7 @@ pub use std::alloc::Global; /// of the allocator registered with the `#[global_allocator]` attribute /// if there is one, or the `std` crate’s default. /// -/// This function is expected to be deprecated in favor of the `alloc` method +/// This function is expected to be deprecated in favor of the `allocate` method /// of the [`Global`] type when it and the [`Allocator`] trait become stable. /// /// # Safety @@ -106,7 +106,7 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { /// of the allocator registered with the `#[global_allocator]` attribute /// if there is one, or the `std` crate’s default. /// -/// This function is expected to be deprecated in favor of the `dealloc` method +/// This function is expected to be deprecated in favor of the `deallocate` method /// of the [`Global`] type when it and the [`Allocator`] trait become stable. /// /// # Safety @@ -125,7 +125,7 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { /// of the allocator registered with the `#[global_allocator]` attribute /// if there is one, or the `std` crate’s default. /// -/// This function is expected to be deprecated in favor of the `realloc` method +/// This function is expected to be deprecated in favor of the `grow` and `shrink` methods /// of the [`Global`] type when it and the [`Allocator`] trait become stable. /// /// # Safety @@ -145,7 +145,7 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 /// of the allocator registered with the `#[global_allocator]` attribute /// if there is one, or the `std` crate’s default. /// -/// This function is expected to be deprecated in favor of the `alloc_zeroed` method +/// This function is expected to be deprecated in favor of the `allocate_zeroed` method /// of the [`Global`] type when it and the [`Allocator`] trait become stable. /// /// # Safety