diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 17e2e028b16fa..a14881c502cf3 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -698,8 +698,12 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v", - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { + InlineAsmRegClass::PowerPC( + PowerPCInlineAsmRegClass::cr + | PowerPCInlineAsmRegClass::ctr + | PowerPCInlineAsmRegClass::lr + | PowerPCInlineAsmRegClass::xer, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", @@ -777,8 +781,12 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => { cx.type_vector(cx.type_i32(), 4) } - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { + InlineAsmRegClass::PowerPC( + PowerPCInlineAsmRegClass::cr + | PowerPCInlineAsmRegClass::ctr + | PowerPCInlineAsmRegClass::lr + | PowerPCInlineAsmRegClass::xer, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index b79176e909818..cc09fa5b69bac 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -340,8 +340,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { attrs.push(llvm::AttributeKind::WillReturn.create_attr(self.cx.llcx)); } else if options.contains(InlineAsmOptions::NOMEM) { attrs.push(llvm::MemoryEffects::InaccessibleMemOnly.create_attr(self.cx.llcx)); - } else { - // LLVM doesn't have an attribute to represent ReadOnly + SideEffect + } else if options.contains(InlineAsmOptions::READONLY) { + attrs.push(llvm::MemoryEffects::ReadOnlyNotPure.create_attr(self.cx.llcx)); } attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs }); @@ -662,7 +662,12 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", PowerPC(PowerPCInlineAsmRegClass::freg) => "f", PowerPC(PowerPCInlineAsmRegClass::vreg) => "v", - PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => { + PowerPC( + PowerPCInlineAsmRegClass::cr + | PowerPCInlineAsmRegClass::ctr + | PowerPCInlineAsmRegClass::lr + | PowerPCInlineAsmRegClass::xer, + ) => { unreachable!("clobber-only") } RiscV(RiscVInlineAsmRegClass::reg) => "r", @@ -830,7 +835,12 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), PowerPC(PowerPCInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i32(), 4), - PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => { + PowerPC( + PowerPCInlineAsmRegClass::cr + | PowerPCInlineAsmRegClass::ctr + | PowerPCInlineAsmRegClass::lr + | PowerPCInlineAsmRegClass::xer, + ) => { unreachable!("clobber-only") } RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index c4881f0aafc80..1950b8288d149 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -204,6 +204,9 @@ pub(crate) fn target_machine_factory( optlvl: config::OptLevel, target_features: &[String], ) -> TargetMachineFactoryFn { + // Self-profile timer for creating a _factory_. + let _prof_timer = sess.prof.generic_activity("target_machine_factory"); + let reloc_model = to_llvm_relocation_model(sess.relocation_model()); let (opt_level, _) = to_llvm_opt_settings(optlvl); @@ -259,6 +262,9 @@ pub(crate) fn target_machine_factory( .into_string() .unwrap_or_default(); let command_line_args = quote_command_line_args(&sess.expanded_args); + // Self-profile counter for the number of bytes produced by command-line quoting. + // Values are summed, so the summary result is cumulative across all TM factories. + sess.prof.artifact_size("quoted_command_line_args", "-", command_line_args.len() as u64); let debuginfo_compression = sess.opts.debuginfo_compression.to_string(); match sess.opts.debuginfo_compression { @@ -281,7 +287,11 @@ pub(crate) fn target_machine_factory( let use_wasm_eh = wants_wasm_eh(sess); + let prof = SelfProfilerRef::clone(&sess.prof); Arc::new(move |config: TargetMachineFactoryConfig| { + // Self-profile timer for invoking a factory to create a target machine. + let _prof_timer = prof.generic_activity("target_machine_factory_inner"); + let path_to_cstring_helper = |path: Option| -> CString { let path = path.unwrap_or_default(); let path = path_mapping diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 9a86e4373d8f4..fd972f371df49 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -710,6 +710,7 @@ pub(crate) enum MemoryEffects { None, ReadOnly, InaccessibleMemOnly, + ReadOnlyNotPure, } /// LLVMOpcode diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 64151962321fd..414274f24fb50 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -553,6 +553,7 @@ enum class LLVMRustMemoryEffects { None, ReadOnly, InaccessibleMemOnly, + ReadOnlyNotPure, }; extern "C" LLVMAttributeRef @@ -568,6 +569,10 @@ LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C, case LLVMRustMemoryEffects::InaccessibleMemOnly: return wrap(Attribute::getWithMemoryEffects( *unwrap(C), MemoryEffects::inaccessibleMemOnly())); + case LLVMRustMemoryEffects::ReadOnlyNotPure: + return wrap(Attribute::getWithMemoryEffects( + *unwrap(C), + MemoryEffects::readOnly() | MemoryEffects::inaccessibleMemOnly())); default: report_fatal_error("bad MemoryEffects."); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4fef65f46b1fd..a6ae58f87dcc8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -794,6 +794,7 @@ symbols! { ctlz, ctlz_nonzero, ctpop, + ctr, cttz, cttz_nonzero, custom_attribute, @@ -1333,6 +1334,7 @@ symbols! { loongarch_target_feature, loop_break_value, loop_match, + lr, lt, m68k_target_feature, macro_at_most_once_rep, diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index e06f881e4b1c7..0601613567ead 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -1260,11 +1260,12 @@ impl InlineAsmClobberAbi { v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, - // cr0-cr1, cr5-cr7, xer + // cr0-cr1, cr5-cr7, ctr, lr, xer cr0, cr1, cr5, cr6, cr7, + ctr, + lr, xer, - // lr and ctr are reserved } }, InlineAsmClobberAbi::S390x => clobbered_regs! { diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index f3934afa6d94f..2348a0fd202e1 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -13,6 +13,8 @@ def_reg_class! { freg, vreg, cr, + ctr, + lr, xer, } } @@ -56,7 +58,7 @@ impl PowerPCInlineAsmRegClass { altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4); vsx: F32, F64, VecI64(2), VecF64(2); }, - Self::cr | Self::xer => &[], + Self::cr | Self::ctr | Self::lr | Self::xer => &[], } } } @@ -195,6 +197,8 @@ def_regs! { cr5: cr = ["cr5"], cr6: cr = ["cr6"], cr7: cr = ["cr7"], + ctr: ctr = ["ctr"], + lr: lr = ["lr"], xer: xer = ["xer"], #error = ["r1", "1", "sp"] => "the stack pointer cannot be used as an operand for inline asm", @@ -206,10 +210,6 @@ def_regs! { "r30 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["r31", "31", "fp"] => "the frame pointer cannot be used as an operand for inline asm", - #error = ["lr"] => - "the link register cannot be used as an operand for inline asm", - #error = ["ctr"] => - "the counter register cannot be used as an operand for inline asm", #error = ["vrsave"] => "the vrsave register cannot be used as an operand for inline asm", } @@ -247,6 +247,8 @@ impl PowerPCInlineAsmReg { (v24, "24"), (v25, "25"), (v26, "26"), (v27, "27"), (v28, "28"), (v29, "29"), (v30, "30"), (v31, "31"); (cr, "cr"); (cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7"); + (ctr, "ctr"); + (lr, "lr"); (xer, "xer"); } } diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs index d42e097b0fd8b..38c3c7dfaa1bb 100644 --- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs @@ -5,8 +5,6 @@ pub(crate) fn target() -> Target { base.cpu = "mips64r2".into(); base.features = "+mips64r2,+xgot".into(); base.max_atomic_width = Some(64); - // FIXME(compiler-team#422): musl targets should be dynamically linked by default. - base.crt_static_default = true; Target { // LLVM doesn't recognize "muslabi64" yet. llvm_target: "mips64el-unknown-linux-musl".into(), diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index b233e1740b7b7..2b8103c8b7786 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -117,10 +117,11 @@ impl InternalNode { /// initialized and valid edge. This function does not set up /// such an edge. unsafe fn new(alloc: A) -> Box { + let mut node = Box::::new_uninit_in(alloc); unsafe { - let mut node = Box::::new_uninit_in(alloc); - // We only need to initialize the data; the edges are MaybeUninit. + // SAFETY: argument points to the `node.data` `LeafNode` LeafNode::init(&raw mut (*node.as_mut_ptr()).data); + // SAFETY: `node.data` was just initialized and `node.edges` is MaybeUninit. node.assume_init() } } diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs index 178af2c0e3b46..d77fafed2039b 100644 --- a/library/core/src/ascii/ascii_char.rs +++ b/library/core/src/ascii/ascii_char.rs @@ -515,7 +515,7 @@ impl AsciiChar { #[track_caller] pub const unsafe fn digit_unchecked(d: u8) -> Self { assert_unsafe_precondition!( - check_language_ub, + check_library_ub, "`ascii::Char::digit_unchecked` input cannot exceed 9.", (d: u8 = d) => d < 10 ); diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 64a3dd3e8bc54..0d80c40fb2363 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1460,8 +1460,8 @@ macro_rules! int_impl { #[inline] pub const unsafe fn unchecked_exact_shl(self, rhs: u32) -> $SelfT { assert_unsafe_precondition!( - check_language_ub, - concat!(stringify!($SelfT), "::unchecked_exact_shl cannot shift out non-zero bits"), + check_library_ub, + concat!(stringify!($SelfT), "::unchecked_exact_shl cannot shift out bits that would change the value of the first bit"), ( zeros: u32 = self.leading_zeros(), ones: u32 = self.leading_ones(), @@ -1638,7 +1638,7 @@ macro_rules! int_impl { #[inline] pub const unsafe fn unchecked_exact_shr(self, rhs: u32) -> $SelfT { assert_unsafe_precondition!( - check_language_ub, + check_library_ub, concat!(stringify!($SelfT), "::unchecked_exact_shr cannot shift out non-zero bits"), ( zeros: u32 = self.trailing_zeros(), diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index bf72ec8319704..d68c7be9865b1 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1865,7 +1865,7 @@ macro_rules! uint_impl { #[inline] pub const unsafe fn unchecked_exact_shl(self, rhs: u32) -> $SelfT { assert_unsafe_precondition!( - check_language_ub, + check_library_ub, concat!(stringify!($SelfT), "::exact_shl_unchecked cannot shift out non-zero bits"), ( zeros: u32 = self.leading_zeros(), @@ -2037,7 +2037,7 @@ macro_rules! uint_impl { #[inline] pub const unsafe fn unchecked_exact_shr(self, rhs: u32) -> $SelfT { assert_unsafe_precondition!( - check_language_ub, + check_library_ub, concat!(stringify!($SelfT), "::exact_shr_unchecked cannot shift out non-zero bits"), ( zeros: u32 = self.trailing_zeros(), diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index a8147d745f3ab..d4c466201edf5 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -233,7 +233,7 @@ unsafe impl const SliceIndex<[T]> for usize { #[track_caller] unsafe fn get_unchecked(self, slice: *const [T]) -> *const T { assert_unsafe_precondition!( - check_language_ub, + check_language_ub, // okay because of the `assume` below "slice::get_unchecked requires that the index is within the slice", (this: usize = self, len: usize = slice.len()) => this < len ); diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index b809294cfcee7..514ff93c9820e 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -21,8 +21,9 @@ use crate::intrinsics::{self, const_eval_select}; /// slow down const-eval/Miri and we'll get the panic message instead of the interpreter's nice /// diagnostic, but our ability to detect UB is unchanged. /// But if `check_language_ub` is used when the check is actually for library UB, the check is -/// omitted in const-eval/Miri and thus if we eventually execute language UB which relies on the -/// library UB, the backtrace Miri reports may be far removed from original cause. +/// omitted in const-eval/Miri and thus UB might occur undetected. Even if we eventually execute +/// language UB which relies on the library UB, the backtrace Miri reports may be far removed from +/// original cause. /// /// These checks are behind a condition which is evaluated at codegen time, not expansion time like /// [`debug_assert`]. This means that a standard library built with optimizations and debug diff --git a/library/std_detect/src/detect/os/darwin/aarch64.rs b/library/std_detect/src/detect/os/darwin/aarch64.rs index f5409361d93b9..8c9fd9647b8a2 100644 --- a/library/std_detect/src/detect/os/darwin/aarch64.rs +++ b/library/std_detect/src/detect/os/darwin/aarch64.rs @@ -37,24 +37,25 @@ pub(crate) fn detect_features() -> cache::Initializer { // Armv8.0 features not using the standard identifiers let fp = _sysctlbyname(c"hw.optional.floatingpoint"); let asimd = _sysctlbyname(c"hw.optional.AdvSIMD"); - let crc = _sysctlbyname(c"hw.optional.armv8_crc32"); + let crc_old = _sysctlbyname(c"hw.optional.armv8_crc32"); // Armv8 and Armv9 features using the standard identifiers let aes = _sysctlbyname(c"hw.optional.arm.FEAT_AES"); let bf16 = _sysctlbyname(c"hw.optional.arm.FEAT_BF16"); let bti = _sysctlbyname(c"hw.optional.arm.FEAT_BTI"); + let crc = _sysctlbyname(c"hw.optional.arm.FEAT_CRC32"); let cssc = _sysctlbyname(c"hw.optional.arm.FEAT_CSSC"); let dit = _sysctlbyname(c"hw.optional.arm.FEAT_DIT"); + let dotprod = _sysctlbyname(c"hw.optional.arm.FEAT_DotProd"); let dpb = _sysctlbyname(c"hw.optional.arm.FEAT_DPB"); let dpb2 = _sysctlbyname(c"hw.optional.arm.FEAT_DPB2"); - let dotprod = _sysctlbyname(c"hw.optional.arm.FEAT_DotProd"); let ecv = _sysctlbyname(c"hw.optional.arm.FEAT_ECV"); let fcma = _sysctlbyname(c"hw.optional.arm.FEAT_FCMA"); let fhm = _sysctlbyname(c"hw.optional.arm.FEAT_FHM"); - let fp16 = _sysctlbyname(c"hw.optional.arm.FEAT_FP16"); - let frintts = _sysctlbyname(c"hw.optional.arm.FEAT_FRINTTS"); let flagm = _sysctlbyname(c"hw.optional.arm.FEAT_FlagM"); let flagm2 = _sysctlbyname(c"hw.optional.arm.FEAT_FlagM2"); + let fp16 = _sysctlbyname(c"hw.optional.arm.FEAT_FP16"); + let frintts = _sysctlbyname(c"hw.optional.arm.FEAT_FRINTTS"); let hbc = _sysctlbyname(c"hw.optional.arm.FEAT_HBC"); let i8mm = _sysctlbyname(c"hw.optional.arm.FEAT_I8MM"); let jsconv = _sysctlbyname(c"hw.optional.arm.FEAT_JSCVT"); @@ -62,6 +63,8 @@ pub(crate) fn detect_features() -> cache::Initializer { let rcpc2 = _sysctlbyname(c"hw.optional.arm.FEAT_LRCPC2"); let lse = _sysctlbyname(c"hw.optional.arm.FEAT_LSE"); let lse2 = _sysctlbyname(c"hw.optional.arm.FEAT_LSE2"); + let mte = _sysctlbyname(c"hw.optional.arm.FEAT_MTE"); + let mte2 = _sysctlbyname(c"hw.optional.arm.FEAT_MTE2"); let pauth = _sysctlbyname(c"hw.optional.arm.FEAT_PAuth"); let pmull = _sysctlbyname(c"hw.optional.arm.FEAT_PMULL"); let rdm = _sysctlbyname(c"hw.optional.arm.FEAT_RDM"); @@ -72,6 +75,7 @@ pub(crate) fn detect_features() -> cache::Initializer { let sha512 = _sysctlbyname(c"hw.optional.arm.FEAT_SHA512"); let sme = _sysctlbyname(c"hw.optional.arm.FEAT_SME"); let sme2 = _sysctlbyname(c"hw.optional.arm.FEAT_SME2"); + let sme2p1 = _sysctlbyname(c"hw.optional.arm.FEAT_SME2p1"); let sme_f64f64 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_F64F64"); let sme_i16i64 = _sysctlbyname(c"hw.optional.arm.FEAT_SME_I16I64"); let ssbs = _sysctlbyname(c"hw.optional.arm.FEAT_SSBS"); @@ -87,6 +91,12 @@ pub(crate) fn detect_features() -> cache::Initializer { let ebf16 = _sysctlbyname(c"hw.optional.arm.FEAT_EBF16"); let fpac = _sysctlbyname(c"hw.optional.arm.FEAT_FPAC"); let fpaccombine = _sysctlbyname(c"hw.optional.arm.FEAT_FPACCOMBINE"); + let mte_async = _sysctlbyname(c"hw.optional.arm.FEAT_MTE_ASYNC"); + let mte_canonical_tags = _sysctlbyname(c"hw.optional.arm.FEAT_MTE_CANONICAL_TAGS"); + let mte_no_address_tags = _sysctlbyname(c"hw.optional.arm.FEAT_MTE_NO_ADDRESS_TAGS"); + let mte_store_only = _sysctlbyname(c"hw.optional.arm.FEAT_MTE_STORE_ONLY"); + let mte3 = _sysctlbyname(c"hw.optional.arm.FEAT_MTE3"); + let mte4 = _sysctlbyname(c"hw.optional.arm.FEAT_MTE4"); let pacimp = _sysctlbyname(c"hw.optional.arm.FEAT_PACIMP"); let pauth2 = _sysctlbyname(c"hw.optional.arm.FEAT_PAuth2"); let rpres = _sysctlbyname(c"hw.optional.arm.FEAT_RPRES"); @@ -111,7 +121,7 @@ pub(crate) fn detect_features() -> cache::Initializer { enable_feature(Feature::asimd, asimd); enable_feature(Feature::bf16, bf16); enable_feature(Feature::bti, bti); - enable_feature(Feature::crc, crc); + enable_feature(Feature::crc, crc_old || crc); enable_feature(Feature::cssc, cssc); enable_feature(Feature::dit, dit); enable_feature(Feature::dotprod, dotprod); @@ -130,6 +140,7 @@ pub(crate) fn detect_features() -> cache::Initializer { enable_feature(Feature::jsconv, jsconv); enable_feature(Feature::lse, lse); enable_feature(Feature::lse2, lse2); + enable_feature(Feature::mte, mte && mte2); enable_feature(Feature::paca, pauth); enable_feature(Feature::pacg, pauth); enable_feature(Feature::pmull, aes && pmull); @@ -141,6 +152,7 @@ pub(crate) fn detect_features() -> cache::Initializer { enable_feature(Feature::sha3, sha512 && sha3 && asimd); enable_feature(Feature::sme, sme); enable_feature(Feature::sme2, sme2); + enable_feature(Feature::sme2p1, sme2p1); enable_feature(Feature::sme_f64f64, sme_f64f64); enable_feature(Feature::sme_i16i64, sme_i16i64); enable_feature(Feature::ssbs, ssbs); diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index d9566c9f55c5c..9434868dc08e6 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -36,6 +36,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `freg` | `f[0-31]` | `f` | | PowerPC | `vreg` | `v[0-31]` | `v` | | PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers | +| PowerPC | `ctr` | `ctr` | Only clobbers | +| PowerPC | `lr` | `lr` | Only clobbers | | PowerPC | `xer` | `xer` | Only clobbers | | wasm32 | `local` | None\* | `r` | | BPF | `reg` | `r[0-10]` | `r` | @@ -78,6 +80,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `vreg` | `altivec` | `i8x16`, `i16x8`, `i32x4`, `f32x4` | | PowerPC | `vreg` | `vsx` | `f32`, `f64`, `i64x2`, `f64x2` | | PowerPC | `cr` | N/A | Only clobbers | +| PowerPC | `ctr` | N/A | Only clobbers | +| PowerPC | `lr` | N/A | Only clobbers | | PowerPC | `xer` | N/A | Only clobbers | | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | | BPF | `reg` | None | `i8` `i16` `i32` `i64` | @@ -150,8 +154,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | MIPS | `$ra` | Return address cannot be used as inputs or outputs. | | Hexagon | `lr` | This is the link register which cannot be used as an input or output. | | PowerPC | `r2`, `r13` | These are system reserved registers. | -| PowerPC | `lr` | The link register cannot be used as an input or output. | -| PowerPC | `ctr` | The counter register cannot be used as an input or output. | | PowerPC | `vrsave` | The vrsave register cannot be used as an input or output. | | AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | |MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. | diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index e204e1788baa8..8feca1367fc9e 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -3,16 +3,16 @@ // FIXME: Once the portability lint RFC is implemented (see tracking issue #41619), // switch to use those structures instead. -use std::fmt::{self, Write}; -use std::{mem, ops}; +use std::{fmt, mem, ops}; +use itertools::Either; use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit}; use rustc_data_structures::fx::FxHashSet; use rustc_session::parse::ParseSess; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; -use crate::display::Joined as _; +use crate::display::{Joined as _, MaybeDisplay, Wrapped}; use crate::html::escape::Escape; #[cfg(test)] @@ -376,27 +376,20 @@ impl Format { Format::LongPlain => false, } } + + fn escape(self, s: &str) -> impl fmt::Display { + if self.is_html() { Either::Left(Escape(s)) } else { Either::Right(s) } + } } /// Pretty-print wrapper for a `Cfg`. Also indicates what form of rendering should be used. struct Display<'a>(&'a Cfg, Format); -fn write_with_opt_paren( - fmt: &mut fmt::Formatter<'_>, - has_paren: bool, - obj: T, -) -> fmt::Result { - if has_paren { - fmt.write_char('(')?; - } - obj.fmt(fmt)?; - if has_paren { - fmt.write_char(')')?; +impl Display<'_> { + fn code_wrappers(&self) -> Wrapped<&'static str> { + if self.1.is_html() { Wrapped::with("", "") } else { Wrapped::with("`", "`") } } - Ok(()) -} -impl Display<'_> { fn display_sub_cfgs( &self, fmt: &mut fmt::Formatter<'_>, @@ -427,20 +420,17 @@ impl Display<'_> { sub_cfgs .iter() .map(|sub_cfg| { - fmt::from_fn(move |fmt| { - if let Cfg::Cfg(_, Some(feat)) = sub_cfg - && short_longhand - { - if self.1.is_html() { - write!(fmt, "{feat}")?; - } else { - write!(fmt, "`{feat}`")?; - } - } else { - write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; - } - Ok(()) - }) + if let Cfg::Cfg(_, Some(feat)) = sub_cfg + && short_longhand + { + Either::Left(self.code_wrappers().wrap(feat)) + } else { + Either::Right( + Wrapped::with_parens() + .when(!sub_cfg.is_all()) + .wrap(Display(sub_cfg, self.1)), + ) + } }) .joined(separator, f) }) @@ -461,9 +451,9 @@ impl fmt::Display for Display<'_> { sub_cfgs .iter() .map(|sub_cfg| { - fmt::from_fn(|fmt| { - write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1)) - }) + Wrapped::with_parens() + .when(!sub_cfg.is_all()) + .wrap(Display(sub_cfg, self.1)) }) .joined(separator, fmt) } @@ -568,21 +558,13 @@ impl fmt::Display for Display<'_> { }; if !human_readable.is_empty() { fmt.write_str(human_readable) - } else if let Some(v) = value { - if self.1.is_html() { - write!( - fmt, - r#"{}="{}""#, - Escape(name.as_str()), - Escape(v.as_str()) - ) - } else { - write!(fmt, r#"`{name}="{v}"`"#) - } - } else if self.1.is_html() { - write!(fmt, "{}", Escape(name.as_str())) } else { - write!(fmt, "`{name}`") + let value = value + .map(|v| fmt::from_fn(move |f| write!(f, "={}", self.1.escape(v.as_str())))) + .maybe_display(); + self.code_wrappers() + .wrap(format_args!("{}{value}", self.1.escape(name.as_str()))) + .fmt(fmt) } } } diff --git a/src/librustdoc/display.rs b/src/librustdoc/display.rs index db868c5c9a8f3..d62ea4c368804 100644 --- a/src/librustdoc/display.rs +++ b/src/librustdoc/display.rs @@ -1,6 +1,6 @@ //! Various utilities for working with [`fmt::Display`] implementations. -use std::fmt::{self, Display, Formatter}; +use std::fmt::{self, Display, Formatter, FormattingOptions}; pub(crate) trait Joined: IntoIterator { /// Takes an iterator over elements that implement [`Display`], and format them into `f`, separated by `sep`. @@ -45,3 +45,87 @@ impl MaybeDisplay for Option { }) } } + +#[derive(Clone, Copy)] +pub(crate) struct Wrapped { + prefix: T, + suffix: T, +} + +pub(crate) enum AngleBracket { + Open, + Close, +} + +impl Display for AngleBracket { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str(match (self, f.alternate()) { + (Self::Open, true) => "<", + (Self::Open, false) => "<", + (Self::Close, true) => ">", + (Self::Close, false) => ">", + }) + } +} + +impl Wrapped { + pub(crate) fn with_angle_brackets() -> Self { + Self { prefix: AngleBracket::Open, suffix: AngleBracket::Close } + } +} + +impl Wrapped { + pub(crate) fn with_parens() -> Self { + Self { prefix: '(', suffix: ')' } + } + + pub(crate) fn with_square_brackets() -> Self { + Self { prefix: '[', suffix: ']' } + } +} + +impl Wrapped { + pub(crate) fn with(prefix: T, suffix: T) -> Self { + Self { prefix, suffix } + } + + pub(crate) fn when(self, if_: bool) -> Wrapped { + Wrapped { + prefix: if_.then_some(self.prefix).maybe_display(), + suffix: if_.then_some(self.suffix).maybe_display(), + } + } + + pub(crate) fn wrap_fn( + self, + content: impl Fn(&mut Formatter<'_>) -> fmt::Result, + ) -> impl Display { + fmt::from_fn(move |f| { + self.prefix.fmt(f)?; + content(f)?; + self.suffix.fmt(f) + }) + } + + pub(crate) fn wrap(self, content: C) -> impl Display { + self.wrap_fn(move |f| content.fmt(f)) + } +} + +#[derive(Clone, Copy)] +pub(crate) struct WithOpts { + opts: FormattingOptions, +} + +impl WithOpts { + pub(crate) fn from(f: &Formatter<'_>) -> Self { + Self { opts: f.options() } + } + + pub(crate) fn display(self, t: impl Display) -> impl Display { + fmt::from_fn(move |f| { + let mut f = f.with_options(self.opts); + t.fmt(&mut f) + }) + } +} diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 8c75f301841f3..ecaff4cdf43af 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -30,7 +30,7 @@ use super::url_parts_builder::UrlPartsBuilder; use crate::clean::types::ExternalLocation; use crate::clean::utils::find_nearest_parent_module; use crate::clean::{self, ExternalCrate, PrimitiveType}; -use crate::display::{Joined as _, MaybeDisplay as _}; +use crate::display::{Joined as _, MaybeDisplay as _, WithOpts, Wrapped}; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::escape::{Escape, EscapeBodyText}; @@ -105,20 +105,16 @@ impl clean::GenericParamDef { impl clean::Generics { pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display { - fmt::from_fn(move |f| { - let mut real_params = self.params.iter().filter(|p| !p.is_synthetic_param()).peekable(); - if real_params.peek().is_none() { - return Ok(()); - } - - let real_params = - fmt::from_fn(|f| real_params.clone().map(|g| g.print(cx)).joined(", ", f)); - if f.alternate() { - write!(f, "<{real_params:#}>") - } else { - write!(f, "<{real_params}>") - } - }) + let mut real_params = self.params.iter().filter(|p| !p.is_synthetic_param()).peekable(); + if real_params.peek().is_none() { + None + } else { + Some( + Wrapped::with_angle_brackets() + .wrap_fn(move |f| real_params.clone().map(|g| g.print(cx)).joined(", ", f)), + ) + } + .maybe_display() } } @@ -151,11 +147,8 @@ fn print_where_predicate(predicate: &clean::WherePredicate, cx: &Context<'_>) -> Ok(()) } clean::WherePredicate::EqPredicate { lhs, rhs } => { - if f.alternate() { - write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx)) - } else { - write!(f, "{} == {}", lhs.print(cx), rhs.print(cx)) - } + let opts = WithOpts::from(f); + write!(f, "{} == {}", opts.display(lhs.print(cx)), opts.display(rhs.print(cx))) } } }) @@ -279,13 +272,10 @@ impl clean::GenericBound { ty.print(cx).fmt(f) } clean::GenericBound::Use(args) => { - if f.alternate() { - f.write_str("use<")?; - } else { - f.write_str("use<")?; - } - args.iter().map(|arg| arg.name()).joined(", ", f)?; - if f.alternate() { f.write_str(">") } else { f.write_str(">") } + f.write_str("use")?; + Wrapped::with_angle_brackets() + .wrap_fn(|f| args.iter().map(|arg| arg.name()).joined(", ", f)) + .fmt(f) } }) } @@ -297,40 +287,29 @@ impl clean::GenericArgs { match self { clean::GenericArgs::AngleBracketed { args, constraints } => { if !args.is_empty() || !constraints.is_empty() { - if f.alternate() { - f.write_str("<")?; - } else { - f.write_str("<")?; - } - - [Either::Left(args), Either::Right(constraints)] - .into_iter() - .flat_map(Either::factor_into_iter) - .map(|either| { - either.map_either( - |arg| arg.print(cx), - |constraint| constraint.print(cx), - ) + Wrapped::with_angle_brackets() + .wrap_fn(|f| { + [Either::Left(args), Either::Right(constraints)] + .into_iter() + .flat_map(Either::factor_into_iter) + .map(|either| { + either.map_either( + |arg| arg.print(cx), + |constraint| constraint.print(cx), + ) + }) + .joined(", ", f) }) - .joined(", ", f)?; - - if f.alternate() { - f.write_str(">")?; - } else { - f.write_str(">")?; - } + .fmt(f)?; } } clean::GenericArgs::Parenthesized { inputs, output } => { - f.write_str("(")?; - inputs.iter().map(|ty| ty.print(cx)).joined(", ", f)?; - f.write_str(")")?; + Wrapped::with_parens() + .wrap_fn(|f| inputs.iter().map(|ty| ty.print(cx)).joined(", ", f)) + .fmt(f)?; if let Some(ref ty) = *output { - if f.alternate() { - write!(f, " -> {:#}", ty.print(cx))?; - } else { - write!(f, " -> {}", ty.print(cx))?; - } + f.write_str(if f.alternate() { " -> " } else { " -> " })?; + ty.print(cx).fmt(f)?; } } clean::GenericArgs::ReturnTypeNotation => { @@ -834,9 +813,10 @@ fn print_higher_ranked_params_with_space( fmt::from_fn(move |f| { if !params.is_empty() { f.write_str(keyword)?; - f.write_str(if f.alternate() { "<" } else { "<" })?; - params.iter().map(|lt| lt.print(cx)).joined(", ", f)?; - f.write_str(if f.alternate() { "> " } else { "> " })?; + Wrapped::with_angle_brackets() + .wrap_fn(|f| params.iter().map(|lt| lt.print(cx)).joined(", ", f)) + .fmt(f)?; + f.write_char(' ')?; } Ok(()) }) @@ -923,26 +903,23 @@ fn fmt_type( f, PrimitiveType::Tuple, format_args!( - "({})", - fmt::from_fn(|f| generic_names.iter().joined(", ", f)) + "{}", + Wrapped::with_parens() + .wrap_fn(|f| generic_names.iter().joined(", ", f)) ), cx, ) } else { - f.write_str("(")?; - many.iter().map(|item| item.print(cx)).joined(", ", f)?; - f.write_str(")") + Wrapped::with_parens() + .wrap_fn(|f| many.iter().map(|item| item.print(cx)).joined(", ", f)) + .fmt(f) } } }, clean::Slice(box clean::Generic(name)) => { primitive_link(f, PrimitiveType::Slice, format_args!("[{name}]"), cx) } - clean::Slice(t) => { - write!(f, "[")?; - t.print(cx).fmt(f)?; - write!(f, "]") - } + clean::Slice(t) => Wrapped::with_square_brackets().wrap(t.print(cx)).fmt(f), clean::Type::Pat(t, pat) => { fmt::Display::fmt(&t.print(cx), f)?; write!(f, " is {pat}") @@ -953,40 +930,27 @@ fn fmt_type( format_args!("[{name}; {n}]", n = Escape(n)), cx, ), - clean::Array(t, n) => { - write!(f, "[")?; - t.print(cx).fmt(f)?; - if f.alternate() { - write!(f, "; {n}")?; - } else { - write!(f, "; ")?; - primitive_link(f, PrimitiveType::Array, format_args!("{n}", n = Escape(n)), cx)?; - } - write!(f, "]") - } - clean::RawPointer(m, t) => { - let m = match m { - hir::Mutability::Mut => "mut", - hir::Mutability::Not => "const", - }; - - if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() { - let ty = t.print(cx); + clean::Array(t, n) => Wrapped::with_square_brackets() + .wrap(fmt::from_fn(|f| { + t.print(cx).fmt(f)?; + f.write_str("; ")?; if f.alternate() { - primitive_link( - f, - clean::PrimitiveType::RawPointer, - format_args!("*{m} {ty:#}"), - cx, - ) + f.write_str(n) } else { - primitive_link( - f, - clean::PrimitiveType::RawPointer, - format_args!("*{m} {ty}"), - cx, - ) + primitive_link(f, PrimitiveType::Array, format_args!("{n}", n = Escape(n)), cx) } + })) + .fmt(f), + clean::RawPointer(m, t) => { + let m = m.ptr_str(); + + if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() { + primitive_link( + f, + clean::PrimitiveType::RawPointer, + format_args!("*{m} {ty}", ty = WithOpts::from(f).display(t.print(cx))), + cx, + ) } else { primitive_link(f, clean::PrimitiveType::RawPointer, format_args!("*{m} "), cx)?; t.print(cx).fmt(f) @@ -1020,14 +984,10 @@ fn fmt_type( clean::ImplTrait(ref bounds) if bounds.len() > 1 => true, _ => false, }; - if needs_parens { - f.write_str("(")?; - } - fmt_type(ty, f, use_absolute, cx)?; - if needs_parens { - f.write_str(")")?; - } - Ok(()) + Wrapped::with_parens() + .when(needs_parens) + .wrap_fn(|f| fmt_type(ty, f, use_absolute, cx)) + .fmt(f) } clean::ImplTrait(bounds) => { f.write_str("impl ")?; @@ -1057,23 +1017,21 @@ impl clean::QPathData { // FIXME(inherent_associated_types): Once we support non-ADT self-types (#106719), // we need to surround them with angle brackets in some cases (e.g. `::P`). - if f.alternate() { - if let Some(trait_) = trait_ - && should_fully_qualify - { - write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))? - } else { - write!(f, "{:#}::", self_type.print(cx))? - } + if let Some(trait_) = trait_ + && should_fully_qualify + { + let opts = WithOpts::from(f); + Wrapped::with_angle_brackets() + .wrap(format_args!( + "{} as {}", + opts.display(self_type.print(cx)), + opts.display(trait_.print(cx)) + )) + .fmt(f)? } else { - if let Some(trait_) = trait_ - && should_fully_qualify - { - write!(f, "<{} as {}>::", self_type.print(cx), trait_.print(cx))? - } else { - write!(f, "{}::", self_type.print(cx))? - } - }; + self_type.print(cx).fmt(f)?; + } + f.write_str("::")?; // It's pretty unsightly to look at `::C` in output, and // we've got hyperlinking on our side, so try to avoid longer // notation as much as possible by making `C` a hyperlink to trait @@ -1132,7 +1090,7 @@ impl clean::Impl { if let Some(ref ty) = self.trait_ { if self.is_negative_trait_impl() { - write!(f, "!")?; + f.write_char('!')?; } if self.kind.is_fake_variadic() && let Some(generics) = ty.generics() @@ -1140,18 +1098,17 @@ impl clean::Impl { { let last = ty.last(); if f.alternate() { - write!(f, "{last}<")?; - self.print_type(inner_type, f, use_absolute, cx)?; - write!(f, ">")?; + write!(f, "{last}")?; } else { - write!(f, "{}<", print_anchor(ty.def_id(), last, cx))?; - self.print_type(inner_type, f, use_absolute, cx)?; - write!(f, ">")?; - } + write!(f, "{}", print_anchor(ty.def_id(), last, cx))?; + }; + Wrapped::with_angle_brackets() + .wrap_fn(|f| self.print_type(inner_type, f, use_absolute, cx)) + .fmt(f)?; } else { ty.print(cx).fmt(f)?; } - write!(f, " for ")?; + f.write_str(" for ")?; } if let Some(ty) = self.kind.as_blanket_ty() { @@ -1218,18 +1175,10 @@ impl clean::Impl { && let Ok(ty) = generics.exactly_one() && self.kind.is_fake_variadic() { - let wrapper = print_anchor(path.def_id(), path.last(), cx); - if f.alternate() { - write!(f, "{wrapper:#}<")?; - } else { - write!(f, "{wrapper}<")?; - } - self.print_type(ty, f, use_absolute, cx)?; - if f.alternate() { - write!(f, ">")?; - } else { - write!(f, ">")?; - } + print_anchor(path.def_id(), path.last(), cx).fmt(f)?; + Wrapped::with_angle_brackets() + .wrap_fn(|f| self.print_type(ty, f, use_absolute, cx)) + .fmt(f)?; } else { fmt_type(type_, f, use_absolute, cx)?; } @@ -1311,23 +1260,13 @@ impl clean::FnDecl { pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display { fmt::from_fn(move |f| { let ellipsis = if self.c_variadic { ", ..." } else { "" }; - if f.alternate() { - write!( - f, - "({params:#}{ellipsis}){arrow:#}", - params = print_params(&self.inputs, cx), - ellipsis = ellipsis, - arrow = self.print_output(cx) - ) - } else { - write!( - f, - "({params}{ellipsis}){arrow}", - params = print_params(&self.inputs, cx), - ellipsis = ellipsis, - arrow = self.print_output(cx) - ) - } + Wrapped::with_parens() + .wrap_fn(|f| { + print_params(&self.inputs, cx).fmt(f)?; + f.write_str(ellipsis) + }) + .fmt(f)?; + self.print_output(cx).fmt(f) }) } @@ -1346,8 +1285,7 @@ impl clean::FnDecl { fmt::from_fn(move |f| { // First, generate the text form of the declaration, with no line wrapping, and count the bytes. let mut counter = WriteCounter(0); - write!(&mut counter, "{:#}", fmt::from_fn(|f| { self.inner_full_print(None, f, cx) })) - .unwrap(); + write!(&mut counter, "{:#}", fmt::from_fn(|f| { self.inner_full_print(None, f, cx) }))?; // If the text form was over 80 characters wide, we will line-wrap our output. let line_wrapping_indent = if header_len + counter.0 > 80 { Some(indent) } else { None }; @@ -1365,53 +1303,56 @@ impl clean::FnDecl { f: &mut fmt::Formatter<'_>, cx: &Context<'_>, ) -> fmt::Result { - f.write_char('(')?; + Wrapped::with_parens() + .wrap_fn(|f| { + if !self.inputs.is_empty() { + let line_wrapping_indent = line_wrapping_indent.map(|n| Indent(n + 4)); - if !self.inputs.is_empty() { - let line_wrapping_indent = line_wrapping_indent.map(|n| Indent(n + 4)); - - if let Some(indent) = line_wrapping_indent { - write!(f, "\n{indent}")?; - } + if let Some(indent) = line_wrapping_indent { + write!(f, "\n{indent}")?; + } - let sep = fmt::from_fn(|f| { - if let Some(indent) = line_wrapping_indent { - write!(f, ",\n{indent}") - } else { - f.write_str(", ") - } - }); + let sep = fmt::from_fn(|f| { + if let Some(indent) = line_wrapping_indent { + write!(f, ",\n{indent}") + } else { + f.write_str(", ") + } + }); - self.inputs.iter().map(|param| param.print(cx)).joined(sep, f)?; + self.inputs.iter().map(|param| param.print(cx)).joined(sep, f)?; - if line_wrapping_indent.is_some() { - writeln!(f, ",")? - } + if line_wrapping_indent.is_some() { + writeln!(f, ",")? + } - if self.c_variadic { - match line_wrapping_indent { - None => write!(f, ", ...")?, - Some(indent) => writeln!(f, "{indent}...")?, - }; - } - } + if self.c_variadic { + match line_wrapping_indent { + None => write!(f, ", ...")?, + Some(indent) => writeln!(f, "{indent}...")?, + }; + } + } - if let Some(n) = line_wrapping_indent { - write!(f, "{}", Indent(n))? - } + if let Some(n) = line_wrapping_indent { + write!(f, "{}", Indent(n))? + } - f.write_char(')')?; + Ok(()) + }) + .fmt(f)?; self.print_output(cx).fmt(f) } fn print_output(&self, cx: &Context<'_>) -> impl Display { - fmt::from_fn(move |f| match &self.output { - clean::Tuple(tys) if tys.is_empty() => Ok(()), - ty if f.alternate() => { - write!(f, " -> {:#}", ty.print(cx)) + fmt::from_fn(move |f| { + if self.output.is_unit() { + return Ok(()); } - ty => write!(f, " -> {}", ty.print(cx)), + + f.write_str(if f.alternate() { " -> " } else { " -> " })?; + self.output.print(cx).fmt(f) }) } } @@ -1422,10 +1363,13 @@ pub(crate) fn visibility_print_with_space(item: &clean::Item, cx: &Context<'_>) f.write_str("#[doc(hidden)] ")?; } - match item.visibility(cx.tcx()) { - None => {} - Some(ty::Visibility::Public) => f.write_str("pub ")?, - Some(ty::Visibility::Restricted(vis_did)) => { + let Some(vis) = item.visibility(cx.tcx()) else { + return Ok(()); + }; + + match vis { + ty::Visibility::Public => f.write_str("pub ")?, + ty::Visibility::Restricted(vis_did) => { // FIXME(camelid): This may not work correctly if `item_did` is a module. // However, rustdoc currently never displays a module's // visibility, so it shouldn't matter. diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 9871066b9eb51..0ff1c09068936 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -10,6 +10,7 @@ #![feature(box_patterns)] #![feature(debug_closure_helpers)] #![feature(file_buffered)] +#![feature(formatting_options)] #![feature(if_let_guard)] #![feature(iter_advance_by)] #![feature(iter_intersperse)] diff --git a/tests/codegen-llvm/asm/powerpc-clobbers.rs b/tests/codegen-llvm/asm/powerpc-clobbers.rs index f7fc7eea5d506..10d7ae4dba40b 100644 --- a/tests/codegen-llvm/asm/powerpc-clobbers.rs +++ b/tests/codegen-llvm/asm/powerpc-clobbers.rs @@ -58,10 +58,10 @@ pub unsafe fn v0_clobber() { // Output format depends on the availability of altivec. // CHECK-LABEL: @clobber_abi -// powerpc: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() -// powerpc64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() -// powerpc64le: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() -// aix64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() +// powerpc: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{ctr},~{lr},~{xer}"() +// powerpc64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{ctr},~{lr},~{xer}"() +// powerpc64le: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{ctr},~{lr},~{xer}"() +// aix64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{ctr},~{lr},~{xer}"() #[no_mangle] pub unsafe fn clobber_abi() { asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); diff --git a/tests/codegen-llvm/asm/readonly-not-pure.rs b/tests/codegen-llvm/asm/readonly-not-pure.rs new file mode 100644 index 0000000000000..a3c0e276c7f5e --- /dev/null +++ b/tests/codegen-llvm/asm/readonly-not-pure.rs @@ -0,0 +1,48 @@ +//@ add-core-stubs +//@ compile-flags: -Copt-level=3 --target x86_64-unknown-linux-gnu +//@ needs-llvm-components: x86 + +#![crate_type = "rlib"] +#![feature(no_core)] +#![no_core] + +// Test that when an inline assembly block specifies `readonly` but not `pure`, a detailed +// `MemoryEffects` is provided to LLVM: this assembly block is not allowed to perform writes, +// but it may have side-effects. + +extern crate minicore; +use minicore::*; + +pub static mut VAR: i32 = 0; + +// CHECK-LABEL: @no_options +// CHECK: call i32 asm +#[no_mangle] +pub unsafe fn no_options() -> i32 { + VAR = 1; + let _ignored: i32; + asm!("mov {0}, 1", out(reg) _ignored); + VAR +} + +// CHECK-LABEL: @readonly_pure +// CHECK-NOT: call i32 asm +#[no_mangle] +pub unsafe fn readonly_pure() -> i32 { + VAR = 1; + let _ignored: i32; + asm!("mov {0}, 1", out(reg) _ignored, options(pure, readonly)); + VAR +} + +// CHECK-LABEL: @readonly_not_pure +// CHECK: call i32 asm {{.*}} #[[ATTR:[0-9]+]] +#[no_mangle] +pub unsafe fn readonly_not_pure() -> i32 { + VAR = 1; + let _ignored: i32; + asm!("mov {0}, 1", out(reg) _ignored, options(readonly)); + VAR +} + +// CHECK: attributes #[[ATTR]] = { nounwind memory(read, inaccessiblemem: readwrite) } diff --git a/tests/codegen-llvm/issues/cows-dont-have-branches-117763.rs b/tests/codegen-llvm/issues/cows-dont-have-branches-117763.rs new file mode 100644 index 0000000000000..b97729fa14657 --- /dev/null +++ b/tests/codegen-llvm/issues/cows-dont-have-branches-117763.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Copt-level=3 +//@ needs-deterministic-layouts + +// Currently Vec and &[T] have layouts that start with (pointer, len) +// which makes the conversion branchless. +// A nice-to-have property, not guaranteed. +#![crate_type = "cdylib"] + +// CHECK-LABEL: @branchless_cow_slices +#[no_mangle] +pub fn branchless_cow_slices<'a>(cow: &'a std::borrow::Cow<'a, [u8]>) -> &'a [u8] { + // CHECK-NOT: br + // CHECK-NOT: select + // CHECK-NOT: icmp + // CHECK: ret { ptr, {{i32|i64}} } + &*cow +} diff --git a/tests/run-make/musl-default-linking/rmake.rs b/tests/run-make/musl-default-linking/rmake.rs index 1b30c538b5e30..e9d09e359c686 100644 --- a/tests/run-make/musl-default-linking/rmake.rs +++ b/tests/run-make/musl-default-linking/rmake.rs @@ -4,7 +4,7 @@ use run_make_support::{rustc, serde_json}; // Per https://github.com/rust-lang/compiler-team/issues/422, // we should be trying to move these targets to dynamically link // musl libc by default. -//@ needs-llvm-components: aarch64 arm mips powerpc x86 +//@ needs-llvm-components: aarch64 arm powerpc x86 static LEGACY_STATIC_LINKING_TARGETS: &[&'static str] = &[ "aarch64-unknown-linux-musl", "arm-unknown-linux-musleabi", @@ -14,7 +14,6 @@ static LEGACY_STATIC_LINKING_TARGETS: &[&'static str] = &[ "armv7-unknown-linux-musleabihf", "i586-unknown-linux-musl", "i686-unknown-linux-musl", - "mips64el-unknown-linux-muslabi64", "powerpc64le-unknown-linux-musl", "x86_64-unknown-linux-musl", ]; diff --git a/tests/ui/asm/powerpc/bad-reg.aix64.stderr b/tests/ui/asm/powerpc/bad-reg.aix64.stderr index 124013f89afa9..82faba8d167fa 100644 --- a/tests/ui/asm/powerpc/bad-reg.aix64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.aix64.stderr @@ -28,74 +28,110 @@ error: invalid register `fp`: the frame pointer cannot be used as an operand for LL | asm!("", out("fp") _); | ^^^^^^^^^^^ -error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 - | -LL | asm!("", out("lr") _); - | ^^^^^^^^^^^ - -error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:50:18 - | -LL | asm!("", out("ctr") _); - | ^^^^^^^^^^^^ - error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:52:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:100:18 + --> $DIR/bad-reg.rs:96:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:103:18 + --> $DIR/bad-reg.rs:99:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:106:26 + --> $DIR/bad-reg.rs:102:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:109:26 + --> $DIR/bad-reg.rs:105:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:109:18 + | +LL | asm!("", in("ctr") x); + | ^^^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:112:18 + | +LL | asm!("", out("ctr") x); + | ^^^^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:115:26 + | +LL | asm!("/* {} */", in(ctr) x); + | ^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:118:26 + | +LL | asm!("/* {} */", out(ctr) _); + | ^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:122:18 + | +LL | asm!("", in("lr") x); + | ^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:125:18 + | +LL | asm!("", out("lr") x); + | ^^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:128:26 + | +LL | asm!("/* {} */", in(lr) x); + | ^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:131:26 + | +LL | asm!("/* {} */", out(lr) _); + | ^^^^^^^^^ + error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:113:18 + --> $DIR/bad-reg.rs:135:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:116:18 + --> $DIR/bad-reg.rs:138:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:119:26 + --> $DIR/bad-reg.rs:141:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:122:26 + --> $DIR/bad-reg.rs:144:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:126:31 + --> $DIR/bad-reg.rs:148:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -103,7 +139,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:128:31 + --> $DIR/bad-reg.rs:150:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -111,7 +147,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:130:31 + --> $DIR/bad-reg.rs:152:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -119,7 +155,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:132:31 + --> $DIR/bad-reg.rs:154:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -127,7 +163,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:134:31 + --> $DIR/bad-reg.rs:156:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -135,7 +171,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:136:31 + --> $DIR/bad-reg.rs:158:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -143,7 +179,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:138:31 + --> $DIR/bad-reg.rs:160:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -151,7 +187,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:140:31 + --> $DIR/bad-reg.rs:162:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -165,7 +201,7 @@ LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:67:27 + --> $DIR/bad-reg.rs:63:27 | LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -173,7 +209,7 @@ LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:70:28 + --> $DIR/bad-reg.rs:66:28 | LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -181,7 +217,7 @@ LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:78:35 + --> $DIR/bad-reg.rs:74:35 | LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^ @@ -189,7 +225,7 @@ LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is avai = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:100:27 + --> $DIR/bad-reg.rs:96:27 | LL | asm!("", in("cr") x); | ^ @@ -197,7 +233,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:103:28 + --> $DIR/bad-reg.rs:99:28 | LL | asm!("", out("cr") x); | ^ @@ -205,7 +241,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:106:33 + --> $DIR/bad-reg.rs:102:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -213,7 +249,55 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:113:28 + --> $DIR/bad-reg.rs:109:28 + | +LL | asm!("", in("ctr") x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:112:29 + | +LL | asm!("", out("ctr") x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:115:34 + | +LL | asm!("/* {} */", in(ctr) x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:122:27 + | +LL | asm!("", in("lr") x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:125:28 + | +LL | asm!("", out("lr") x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:128:33 + | +LL | asm!("/* {} */", in(lr) x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:135:28 | LL | asm!("", in("xer") x); | ^ @@ -221,7 +305,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:116:29 + --> $DIR/bad-reg.rs:138:29 | LL | asm!("", out("xer") x); | ^ @@ -229,12 +313,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:119:34 + --> $DIR/bad-reg.rs:141:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: aborting due to 34 previous errors +error: aborting due to 46 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr index b11c946f80da5..fac70ea77cb3a 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr @@ -28,74 +28,110 @@ error: invalid register `fp`: the frame pointer cannot be used as an operand for LL | asm!("", out("fp") _); | ^^^^^^^^^^^ -error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 - | -LL | asm!("", out("lr") _); - | ^^^^^^^^^^^ - -error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:50:18 - | -LL | asm!("", out("ctr") _); - | ^^^^^^^^^^^^ - error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:52:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:100:18 + --> $DIR/bad-reg.rs:96:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:103:18 + --> $DIR/bad-reg.rs:99:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:106:26 + --> $DIR/bad-reg.rs:102:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:109:26 + --> $DIR/bad-reg.rs:105:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:109:18 + | +LL | asm!("", in("ctr") x); + | ^^^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:112:18 + | +LL | asm!("", out("ctr") x); + | ^^^^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:115:26 + | +LL | asm!("/* {} */", in(ctr) x); + | ^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:118:26 + | +LL | asm!("/* {} */", out(ctr) _); + | ^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:122:18 + | +LL | asm!("", in("lr") x); + | ^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:125:18 + | +LL | asm!("", out("lr") x); + | ^^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:128:26 + | +LL | asm!("/* {} */", in(lr) x); + | ^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:131:26 + | +LL | asm!("/* {} */", out(lr) _); + | ^^^^^^^^^ + error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:113:18 + --> $DIR/bad-reg.rs:135:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:116:18 + --> $DIR/bad-reg.rs:138:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:119:26 + --> $DIR/bad-reg.rs:141:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:122:26 + --> $DIR/bad-reg.rs:144:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:126:31 + --> $DIR/bad-reg.rs:148:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -103,7 +139,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:128:31 + --> $DIR/bad-reg.rs:150:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -111,7 +147,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:130:31 + --> $DIR/bad-reg.rs:152:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -119,7 +155,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:132:31 + --> $DIR/bad-reg.rs:154:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -127,7 +163,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:134:31 + --> $DIR/bad-reg.rs:156:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -135,7 +171,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:136:31 + --> $DIR/bad-reg.rs:158:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -143,7 +179,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:138:31 + --> $DIR/bad-reg.rs:160:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -151,7 +187,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:140:31 + --> $DIR/bad-reg.rs:162:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -165,67 +201,67 @@ LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:57:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", in("v0") v32x4); // requires altivec | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:59:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("v0") v32x4); // requires altivec | ^^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:61:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", in("v0") v64x2); // requires vsx | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:64:18 + --> $DIR/bad-reg.rs:60:18 | LL | asm!("", out("v0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:67:18 + --> $DIR/bad-reg.rs:63:18 | LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:70:18 + --> $DIR/bad-reg.rs:66:18 | LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:73:26 + --> $DIR/bad-reg.rs:69:26 | LL | asm!("/* {} */", in(vreg) v32x4); // requires altivec | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:75:26 + --> $DIR/bad-reg.rs:71:26 | LL | asm!("/* {} */", in(vreg) v64x2); // requires vsx | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:78:26 + --> $DIR/bad-reg.rs:74:26 | LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:81:26 + --> $DIR/bad-reg.rs:77:26 | LL | asm!("/* {} */", out(vreg) _); // requires altivec | ^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:100:27 + --> $DIR/bad-reg.rs:96:27 | LL | asm!("", in("cr") x); | ^ @@ -233,7 +269,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:103:28 + --> $DIR/bad-reg.rs:99:28 | LL | asm!("", out("cr") x); | ^ @@ -241,7 +277,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:106:33 + --> $DIR/bad-reg.rs:102:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -249,7 +285,55 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:113:28 + --> $DIR/bad-reg.rs:109:28 + | +LL | asm!("", in("ctr") x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:112:29 + | +LL | asm!("", out("ctr") x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:115:34 + | +LL | asm!("/* {} */", in(ctr) x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:122:27 + | +LL | asm!("", in("lr") x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:125:28 + | +LL | asm!("", out("lr") x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:128:33 + | +LL | asm!("/* {} */", in(lr) x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:135:28 | LL | asm!("", in("xer") x); | ^ @@ -257,7 +341,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:116:29 + --> $DIR/bad-reg.rs:138:29 | LL | asm!("", out("xer") x); | ^ @@ -265,12 +349,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:119:34 + --> $DIR/bad-reg.rs:141:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: aborting due to 41 previous errors +error: aborting due to 53 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr index a93b2b018df0e..42a59448f425e 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr @@ -28,74 +28,110 @@ error: invalid register `fp`: the frame pointer cannot be used as an operand for LL | asm!("", out("fp") _); | ^^^^^^^^^^^ -error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 - | -LL | asm!("", out("lr") _); - | ^^^^^^^^^^^ - -error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:50:18 - | -LL | asm!("", out("ctr") _); - | ^^^^^^^^^^^^ - error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:52:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:100:18 + --> $DIR/bad-reg.rs:96:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:103:18 + --> $DIR/bad-reg.rs:99:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:106:26 + --> $DIR/bad-reg.rs:102:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:109:26 + --> $DIR/bad-reg.rs:105:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:109:18 + | +LL | asm!("", in("ctr") x); + | ^^^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:112:18 + | +LL | asm!("", out("ctr") x); + | ^^^^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:115:26 + | +LL | asm!("/* {} */", in(ctr) x); + | ^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:118:26 + | +LL | asm!("/* {} */", out(ctr) _); + | ^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:122:18 + | +LL | asm!("", in("lr") x); + | ^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:125:18 + | +LL | asm!("", out("lr") x); + | ^^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:128:26 + | +LL | asm!("/* {} */", in(lr) x); + | ^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:131:26 + | +LL | asm!("/* {} */", out(lr) _); + | ^^^^^^^^^ + error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:113:18 + --> $DIR/bad-reg.rs:135:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:116:18 + --> $DIR/bad-reg.rs:138:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:119:26 + --> $DIR/bad-reg.rs:141:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:122:26 + --> $DIR/bad-reg.rs:144:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:126:31 + --> $DIR/bad-reg.rs:148:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -103,7 +139,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:128:31 + --> $DIR/bad-reg.rs:150:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -111,7 +147,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:130:31 + --> $DIR/bad-reg.rs:152:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -119,7 +155,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:132:31 + --> $DIR/bad-reg.rs:154:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -127,7 +163,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:134:31 + --> $DIR/bad-reg.rs:156:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -135,7 +171,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:136:31 + --> $DIR/bad-reg.rs:158:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -143,7 +179,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:138:31 + --> $DIR/bad-reg.rs:160:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -151,7 +187,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:140:31 + --> $DIR/bad-reg.rs:162:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -165,7 +201,7 @@ LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: `vsx` target feature is not enabled - --> $DIR/bad-reg.rs:61:27 + --> $DIR/bad-reg.rs:57:27 | LL | asm!("", in("v0") v64x2); // requires vsx | ^^^^^ @@ -173,7 +209,7 @@ LL | asm!("", in("v0") v64x2); // requires vsx = note: this is required to use type `i64x2` with register class `vreg` error: `vsx` target feature is not enabled - --> $DIR/bad-reg.rs:64:28 + --> $DIR/bad-reg.rs:60:28 | LL | asm!("", out("v0") v64x2); // requires vsx | ^^^^^ @@ -181,7 +217,7 @@ LL | asm!("", out("v0") v64x2); // requires vsx = note: this is required to use type `i64x2` with register class `vreg` error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:67:27 + --> $DIR/bad-reg.rs:63:27 | LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -189,7 +225,7 @@ LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:70:28 + --> $DIR/bad-reg.rs:66:28 | LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -197,7 +233,7 @@ LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: `vsx` target feature is not enabled - --> $DIR/bad-reg.rs:75:35 + --> $DIR/bad-reg.rs:71:35 | LL | asm!("/* {} */", in(vreg) v64x2); // requires vsx | ^^^^^ @@ -205,7 +241,7 @@ LL | asm!("/* {} */", in(vreg) v64x2); // requires vsx = note: this is required to use type `i64x2` with register class `vreg` error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:78:35 + --> $DIR/bad-reg.rs:74:35 | LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^ @@ -213,7 +249,7 @@ LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is avai = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:100:27 + --> $DIR/bad-reg.rs:96:27 | LL | asm!("", in("cr") x); | ^ @@ -221,7 +257,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:103:28 + --> $DIR/bad-reg.rs:99:28 | LL | asm!("", out("cr") x); | ^ @@ -229,7 +265,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:106:33 + --> $DIR/bad-reg.rs:102:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -237,7 +273,55 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:113:28 + --> $DIR/bad-reg.rs:109:28 + | +LL | asm!("", in("ctr") x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:112:29 + | +LL | asm!("", out("ctr") x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:115:34 + | +LL | asm!("/* {} */", in(ctr) x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:122:27 + | +LL | asm!("", in("lr") x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:125:28 + | +LL | asm!("", out("lr") x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:128:33 + | +LL | asm!("/* {} */", in(lr) x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:135:28 | LL | asm!("", in("xer") x); | ^ @@ -245,7 +329,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:116:29 + --> $DIR/bad-reg.rs:138:29 | LL | asm!("", out("xer") x); | ^ @@ -253,12 +337,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:119:34 + --> $DIR/bad-reg.rs:141:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: aborting due to 37 previous errors +error: aborting due to 49 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr index 124013f89afa9..82faba8d167fa 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr @@ -28,74 +28,110 @@ error: invalid register `fp`: the frame pointer cannot be used as an operand for LL | asm!("", out("fp") _); | ^^^^^^^^^^^ -error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 - | -LL | asm!("", out("lr") _); - | ^^^^^^^^^^^ - -error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:50:18 - | -LL | asm!("", out("ctr") _); - | ^^^^^^^^^^^^ - error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:52:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:100:18 + --> $DIR/bad-reg.rs:96:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:103:18 + --> $DIR/bad-reg.rs:99:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:106:26 + --> $DIR/bad-reg.rs:102:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:109:26 + --> $DIR/bad-reg.rs:105:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:109:18 + | +LL | asm!("", in("ctr") x); + | ^^^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:112:18 + | +LL | asm!("", out("ctr") x); + | ^^^^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:115:26 + | +LL | asm!("/* {} */", in(ctr) x); + | ^^^^^^^^^ + +error: register class `ctr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:118:26 + | +LL | asm!("/* {} */", out(ctr) _); + | ^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:122:18 + | +LL | asm!("", in("lr") x); + | ^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:125:18 + | +LL | asm!("", out("lr") x); + | ^^^^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:128:26 + | +LL | asm!("/* {} */", in(lr) x); + | ^^^^^^^^ + +error: register class `lr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:131:26 + | +LL | asm!("/* {} */", out(lr) _); + | ^^^^^^^^^ + error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:113:18 + --> $DIR/bad-reg.rs:135:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:116:18 + --> $DIR/bad-reg.rs:138:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:119:26 + --> $DIR/bad-reg.rs:141:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:122:26 + --> $DIR/bad-reg.rs:144:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:126:31 + --> $DIR/bad-reg.rs:148:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -103,7 +139,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:128:31 + --> $DIR/bad-reg.rs:150:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -111,7 +147,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:130:31 + --> $DIR/bad-reg.rs:152:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -119,7 +155,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:132:31 + --> $DIR/bad-reg.rs:154:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -127,7 +163,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:134:31 + --> $DIR/bad-reg.rs:156:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -135,7 +171,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:136:31 + --> $DIR/bad-reg.rs:158:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -143,7 +179,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:138:31 + --> $DIR/bad-reg.rs:160:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -151,7 +187,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:140:31 + --> $DIR/bad-reg.rs:162:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -165,7 +201,7 @@ LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:67:27 + --> $DIR/bad-reg.rs:63:27 | LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -173,7 +209,7 @@ LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:70:28 + --> $DIR/bad-reg.rs:66:28 | LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -181,7 +217,7 @@ LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:78:35 + --> $DIR/bad-reg.rs:74:35 | LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^ @@ -189,7 +225,7 @@ LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is avai = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:100:27 + --> $DIR/bad-reg.rs:96:27 | LL | asm!("", in("cr") x); | ^ @@ -197,7 +233,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:103:28 + --> $DIR/bad-reg.rs:99:28 | LL | asm!("", out("cr") x); | ^ @@ -205,7 +241,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:106:33 + --> $DIR/bad-reg.rs:102:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -213,7 +249,55 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:113:28 + --> $DIR/bad-reg.rs:109:28 + | +LL | asm!("", in("ctr") x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:112:29 + | +LL | asm!("", out("ctr") x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:115:34 + | +LL | asm!("/* {} */", in(ctr) x); + | ^ + | + = note: register class `ctr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:122:27 + | +LL | asm!("", in("lr") x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:125:28 + | +LL | asm!("", out("lr") x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:128:33 + | +LL | asm!("/* {} */", in(lr) x); + | ^ + | + = note: register class `lr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:135:28 | LL | asm!("", in("xer") x); | ^ @@ -221,7 +305,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:116:29 + --> $DIR/bad-reg.rs:138:29 | LL | asm!("", out("xer") x); | ^ @@ -229,12 +313,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:119:34 + --> $DIR/bad-reg.rs:141:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: aborting due to 34 previous errors +error: aborting due to 46 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.rs b/tests/ui/asm/powerpc/bad-reg.rs index 5598f8379603d..21ea451934ed4 100644 --- a/tests/ui/asm/powerpc/bad-reg.rs +++ b/tests/ui/asm/powerpc/bad-reg.rs @@ -45,10 +45,6 @@ fn f() { //~^ ERROR invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm asm!("", out("fp") _); //~^ ERROR invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - asm!("", out("lr") _); - //~^ ERROR invalid register `lr`: the link register cannot be used as an operand for inline asm - asm!("", out("ctr") _); - //~^ ERROR invalid register `ctr`: the counter register cannot be used as an operand for inline asm asm!("", out("vrsave") _); //~^ ERROR invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm @@ -108,6 +104,32 @@ fn f() { //~| ERROR type `i32` cannot be used with this register class asm!("/* {} */", out(cr) _); //~^ ERROR can only be used as a clobber + // ctr + asm!("", out("ctr") _); // ok + asm!("", in("ctr") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("", out("ctr") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(ctr) x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(ctr) _); + //~^ ERROR can only be used as a clobber + // lr + asm!("", out("lr") _); // ok + asm!("", in("lr") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("", out("lr") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(lr) x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(lr) _); + //~^ ERROR can only be used as a clobber // xer asm!("", out("xer") _); // ok asm!("", in("xer") x);