diff --git a/Cargo.lock b/Cargo.lock index 6c14a9f26e175..873182dde9102 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3235,24 +3235,13 @@ dependencies = [ "ptr_meta", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - [[package]] name = "rand" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "rand_chacha 0.9.0", + "rand_chacha", "rand_core 0.9.3", ] @@ -3267,16 +3256,6 @@ dependencies = [ "rand_core 0.10.1", ] -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - [[package]] name = "rand_chacha" version = "0.9.0" @@ -3287,15 +3266,6 @@ dependencies = [ "rand_core 0.9.3", ] -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", -] - [[package]] name = "rand_core" version = "0.9.3" @@ -5550,7 +5520,7 @@ dependencies = [ "indicatif", "num", "rand 0.9.2", - "rand_chacha 0.9.0", + "rand_chacha", "rayon", ] @@ -5924,7 +5894,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", - "rand 0.8.5", "static_assertions", ] diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 53074e313f9ce..6fd7188f656c5 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -706,7 +706,9 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { unreachable!("clobber-only") } InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) + | InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::vreg) + | InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::xreg) => "f", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", @@ -815,6 +817,12 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl } InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::vreg) => { + cx.type_vector(cx.type_i32(), 4) + } + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::xreg) => { + cx.type_vector(cx.type_i32(), 8) + } InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), @@ -1013,7 +1021,22 @@ fn modifier_to_gcc( } } InlineAsmRegClass::Hexagon(_) => None, - InlineAsmRegClass::LoongArch(_) => None, + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => None, + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => modifier, + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::vreg) => { + if modifier.is_none() { + Some('w') + } else { + modifier + } + } + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::xreg) => { + if modifier.is_none() { + Some('u') + } else { + modifier + } + } InlineAsmRegClass::Mips(_) => None, InlineAsmRegClass::Nvptx(_) => None, InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vsreg) => { diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 2598c1b38ff88..8f192a5a73b63 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -709,7 +709,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> Hexagon(HexagonInlineAsmRegClass::vreg_pair) => "v", Hexagon(HexagonInlineAsmRegClass::qreg) => unreachable!("clobber-only"), LoongArch(LoongArchInlineAsmRegClass::reg) => "r", - LoongArch(LoongArchInlineAsmRegClass::freg) => "f", + LoongArch(LoongArchInlineAsmRegClass::freg) + | LoongArch(LoongArchInlineAsmRegClass::vreg) + | LoongArch(LoongArchInlineAsmRegClass::xreg) => "f", Mips(MipsInlineAsmRegClass::reg) => "r", Mips(MipsInlineAsmRegClass::freg) => "f", Nvptx(NvptxInlineAsmRegClass::reg16) => "h", @@ -814,7 +816,22 @@ fn modifier_to_llvm( } Amdgpu(_) => None, Hexagon(_) => None, - LoongArch(_) => None, + LoongArch(LoongArchInlineAsmRegClass::reg) => None, + LoongArch(LoongArchInlineAsmRegClass::freg) => modifier, + LoongArch(LoongArchInlineAsmRegClass::vreg) => { + if modifier.is_none() { + Some('w') + } else { + modifier + } + } + LoongArch(LoongArchInlineAsmRegClass::xreg) => { + if modifier.is_none() { + Some('u') + } else { + modifier + } + } Mips(_) => None, Nvptx(_) => None, PowerPC(PowerPCInlineAsmRegClass::vsreg) => { @@ -917,6 +934,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' Hexagon(HexagonInlineAsmRegClass::qreg) => unreachable!("clobber-only"), LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), + LoongArch(LoongArchInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i32(), 4), + LoongArch(LoongArchInlineAsmRegClass::xreg) => cx.type_vector(cx.type_i32(), 8), Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index b29e469348f81..2b0219f356c3c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1707,8 +1707,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .inherent_impls(adt_did) .iter() .filter_map(|&impl_| { - let (item, scope) = - self.probe_assoc_item_unchecked(name, assoc_tag, block, impl_)?; + let (item, scope) = self.probe_assoc_item_unchecked(name, assoc_tag, impl_)?; Some(InherentAssocCandidate { impl_, assoc_item: item.def_id, scope }) }) .collect(); @@ -1784,7 +1783,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span: Span, scope: DefId, ) -> Option { - let (item, scope) = self.probe_assoc_item_unchecked(ident, assoc_tag, block, scope)?; + let (item, scope) = self.probe_assoc_item_unchecked(ident, assoc_tag, scope)?; self.check_assoc_item(item.def_id, ident, scope, block, span); Some(item) } @@ -1797,12 +1796,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, ident: Ident, assoc_tag: ty::AssocTag, - block: HirId, scope: DefId, ) -> Option<(ty::AssocItem, /*scope*/ DefId)> { let tcx = self.tcx(); - let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, block); + let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, self.item_def_id()); // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()` // instead of calling `filter_by_name_and_kind` which would needlessly normalize the // `ident` again and again. @@ -3497,8 +3495,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } (FIRST_VARIANT, def.non_enum_variant()) }; - let block = tcx.local_def_id_to_hir_id(item_def_id); - let (ident, def_scope) = tcx.adjust_ident_and_get_scope(field, def.did(), block); + let (ident, def_scope) = + tcx.adjust_ident_and_get_scope(field, def.did(), item_def_id); if let Some((field_idx, field)) = variant .fields .iter_enumerated() diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 22c211b199474..0cd80a6a83c87 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2764,9 +2764,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Ty::new_error(self.tcx(), guar); } - let fn_body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id); let (ident, def_scope) = - self.tcx.adjust_ident_and_get_scope(field, base_def.did(), fn_body_hir_id); + self.tcx.adjust_ident_and_get_scope(field, base_def.did(), self.body_id); if let Some((idx, field)) = self.find_adt_field(*base_def, ident) { self.write_field_index(expr.hir_id, idx); @@ -3768,9 +3767,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match container.kind() { ty::Adt(container_def, args) if container_def.is_enum() => { - let block = self.tcx.local_def_id_to_hir_id(self.body_id); - let (ident, _def_scope) = - self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block); + let ident = self.tcx.adjust_ident(field, container_def.did()); if !self.tcx.features().offset_of_enum() { rustc_session::errors::feature_err( @@ -3806,7 +3803,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { break; }; let (subident, sub_def_scope) = - self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, block); + self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, self.body_id); let Some((subindex, field)) = variant .fields @@ -3854,9 +3851,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } ty::Adt(container_def, args) => { - let block = self.tcx.local_def_id_to_hir_id(self.body_id); - let (ident, def_scope) = - self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block); + let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope( + field, + container_def.did(), + self.body_id, + ); let fields = &container_def.non_enum_variant().fields; if let Some((index, field)) = fields diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index ce187aa1aff14..ce22ab937391e 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -810,9 +810,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn push_candidate(&mut self, candidate: Candidate<'tcx>, is_inherent: bool) { let is_accessible = if let Some(name) = self.method_name { let item = candidate.item; - let hir_id = self.tcx.local_def_id_to_hir_id(self.body_id); - let def_scope = - self.tcx.adjust_ident_and_get_scope(name, item.container_id(self.tcx), hir_id).1; + let container_id = item.container_id(self.tcx); + let def_scope = self.tcx.adjust_ident_and_get_scope(name, container_id, self.body_id).1; item.visibility(self.tcx).is_accessible_from(def_scope, self.tcx) } else { true diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 98b44f072075a..41079d431edf9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2137,18 +2137,17 @@ impl<'tcx> TyCtxt<'tcx> { ident } - // FIXME(vincenzopalazzo): move the HirId to a LocalDefId pub fn adjust_ident_and_get_scope( self, mut ident: Ident, scope: DefId, - block: hir::HirId, + item_id: LocalDefId, ) -> (Ident, DefId) { let scope = ident .span .normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) .and_then(|actual_expansion| actual_expansion.expn_data().parent_module) - .unwrap_or_else(|| self.parent_module(block).to_def_id()); + .unwrap_or_else(|| self.parent_module_from_def_id(item_id).to_def_id()); (ident, scope) } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 6f09e53f0a8e7..76af497c1d063 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -948,7 +948,8 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { // definition of the field let ident = Ident::new(sym::dummy, use_ctxt); - let (_, def_id) = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id); + let (_, def_id) = + self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id.owner.def_id); !field.vis.is_accessible_from(def_id, self.tcx) } diff --git a/compiler/rustc_sanitizers/Cargo.toml b/compiler/rustc_sanitizers/Cargo.toml index 9069d2c233db7..8eff14d0cfcfa 100644 --- a/compiler/rustc_sanitizers/Cargo.toml +++ b/compiler/rustc_sanitizers/Cargo.toml @@ -14,5 +14,5 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } tracing = "0.1" -twox-hash = "1.6.3" +twox-hash = { version = "1.6.3", default-features = false } # tidy-alphabetical-end diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4bada9712d2a9..71eae246ebaff 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1170,6 +1170,7 @@ symbols! { lang_items, large_assignments, last, + lasx, lateout, lazy_normalization_consts, lazy_type_alias, @@ -1227,6 +1228,7 @@ symbols! { loop_hints, loop_match, lr, + lsx, lt, m68k, m68k_target_feature, @@ -2374,6 +2376,7 @@ symbols! { xloop, xmm_reg, xop_target_feature, + xreg, xtensa, xtensa_target_feature, yeet_desugar_details, diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs index 51e7ee8daa439..4aa69dac2d7db 100644 --- a/compiler/rustc_target/src/asm/loongarch.rs +++ b/compiler/rustc_target/src/asm/loongarch.rs @@ -8,12 +8,19 @@ def_reg_class! { LoongArch LoongArchInlineAsmRegClass { reg, freg, + vreg, + xreg, } } impl LoongArchInlineAsmRegClass { pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { - &[] + match self { + Self::freg => &['w', 'u'], + Self::vreg => &['u'], + Self::xreg => &['w'], + _ => &[], + } } pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { @@ -35,6 +42,7 @@ impl LoongArchInlineAsmRegClass { pub fn supported_types( self, arch: InlineAsmArch, + allow_experimental_reg: bool, ) -> &'static [(InlineAsmType, Option)] { match (self, arch) { (Self::reg, InlineAsmArch::LoongArch64) => { @@ -42,6 +50,27 @@ impl LoongArchInlineAsmRegClass { } (Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F16, F32; }, (Self::freg, _) => types! { f: F16, F32; d: F64; }, + (Self::vreg, _) => { + if allow_experimental_reg { + types! { + lsx: F16, F32, F64, + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); + } + } else { + &[] + } + } + (Self::xreg, _) => { + if allow_experimental_reg { + types! { + lasx: F16, F32, F64, + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2), + VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF32(8), VecF64(4); + } + } else { + &[] + } + } _ => unreachable!("unsupported register class"), } } @@ -108,6 +137,70 @@ def_regs! { f29: freg = ["$f29","$fs5"], f30: freg = ["$f30","$fs6"], f31: freg = ["$f31","$fs7"], + vr0: vreg = ["$vr0"], + vr1: vreg = ["$vr1"], + vr2: vreg = ["$vr2"], + vr3: vreg = ["$vr3"], + vr4: vreg = ["$vr4"], + vr5: vreg = ["$vr5"], + vr6: vreg = ["$vr6"], + vr7: vreg = ["$vr7"], + vr8: vreg = ["$vr8"], + vr9: vreg = ["$vr9"], + vr10: vreg = ["$vr10"], + vr11: vreg = ["$vr11"], + vr12: vreg = ["$vr12"], + vr13: vreg = ["$vr13"], + vr14: vreg = ["$vr14"], + vr15: vreg = ["$vr15"], + vr16: vreg = ["$vr16"], + vr17: vreg = ["$vr17"], + vr18: vreg = ["$vr18"], + vr19: vreg = ["$vr19"], + vr20: vreg = ["$vr20"], + vr21: vreg = ["$vr21"], + vr22: vreg = ["$vr22"], + vr23: vreg = ["$vr23"], + vr24: vreg = ["$vr24"], + vr25: vreg = ["$vr25"], + vr26: vreg = ["$vr26"], + vr27: vreg = ["$vr27"], + vr28: vreg = ["$vr28"], + vr29: vreg = ["$vr29"], + vr30: vreg = ["$vr30"], + vr31: vreg = ["$vr31"], + xr0: xreg = ["$xr0"], + xr1: xreg = ["$xr1"], + xr2: xreg = ["$xr2"], + xr3: xreg = ["$xr3"], + xr4: xreg = ["$xr4"], + xr5: xreg = ["$xr5"], + xr6: xreg = ["$xr6"], + xr7: xreg = ["$xr7"], + xr8: xreg = ["$xr8"], + xr9: xreg = ["$xr9"], + xr10: xreg = ["$xr10"], + xr11: xreg = ["$xr11"], + xr12: xreg = ["$xr12"], + xr13: xreg = ["$xr13"], + xr14: xreg = ["$xr14"], + xr15: xreg = ["$xr15"], + xr16: xreg = ["$xr16"], + xr17: xreg = ["$xr17"], + xr18: xreg = ["$xr18"], + xr19: xreg = ["$xr19"], + xr20: xreg = ["$xr20"], + xr21: xreg = ["$xr21"], + xr22: xreg = ["$xr22"], + xr23: xreg = ["$xr23"], + xr24: xreg = ["$xr24"], + xr25: xreg = ["$xr25"], + xr26: xreg = ["$xr26"], + xr27: xreg = ["$xr27"], + xr28: xreg = ["$xr28"], + xr29: xreg = ["$xr29"], + xr30: xreg = ["$xr30"], + xr31: xreg = ["$xr31"], #error = ["$r0","$zero"] => "constant zero cannot be used as an operand for inline asm", #error = ["$r2","$tp"] => @@ -132,4 +225,60 @@ impl LoongArchInlineAsmReg { ) -> fmt::Result { out.write_str(self.name()) } + + pub fn overlapping_regs(self, mut cb: impl FnMut(LoongArchInlineAsmReg)) { + macro_rules! reg_conflicts { + ( + $( + $f:ident : $v:ident : $x:ident + ),*; + ) => { + match self { + $( + Self::$f | Self::$v | Self::$x => { + cb(Self::$f); + cb(Self::$v); + cb(Self::$x); + } + )* + r => cb(r), + } + }; + } + + reg_conflicts! { + f0 : vr0 : xr0, + f1 : vr1 : xr1, + f2 : vr2 : xr2, + f3 : vr3 : xr3, + f4 : vr4 : xr4, + f5 : vr5 : xr5, + f6 : vr6 : xr6, + f7 : vr7 : xr7, + f8 : vr8 : xr8, + f9 : vr9 : xr9, + f10 : vr10 : xr10, + f11 : vr11 : xr11, + f12 : vr12 : xr12, + f13 : vr13 : xr13, + f14 : vr14 : xr14, + f15 : vr15 : xr15, + f16 : vr16 : xr16, + f17 : vr17 : xr17, + f18 : vr18 : xr18, + f19 : vr19 : xr19, + f20 : vr20 : xr20, + f21 : vr21 : xr21, + f22 : vr22 : xr22, + f23 : vr23 : xr23, + f24 : vr24 : xr24, + f25 : vr25 : xr25, + f26 : vr26 : xr26, + f27 : vr27 : xr27, + f28 : vr28 : xr28, + f29 : vr29 : xr29, + f30 : vr30 : xr30, + f31 : vr31 : xr31; + } + } } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 1129c2eddf2d3..8d99035fd0db4 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -474,7 +474,7 @@ impl InlineAsmReg { Self::RiscV(_) => cb(self), Self::PowerPC(r) => r.overlapping_regs(|r| cb(Self::PowerPC(r))), Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), - Self::LoongArch(_) => cb(self), + Self::LoongArch(r) => r.overlapping_regs(|r| cb(Self::LoongArch(r))), Self::Mips(_) => cb(self), Self::S390x(r) => r.overlapping_regs(|r| cb(Self::S390x(r))), Self::Sparc(_) => cb(self), @@ -655,7 +655,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.supported_types(arch).into(), Self::PowerPC(r) => r.supported_types(arch).into(), Self::Hexagon(r) => r.supported_types(arch).into(), - Self::LoongArch(r) => r.supported_types(arch).into(), + Self::LoongArch(r) => r.supported_types(arch, allow_experimental_reg).into(), Self::Mips(r) => r.supported_types(arch).into(), Self::S390x(r) => r.supported_types(arch).into(), Self::Sparc(r) => r.supported_types(arch).into(), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 3fdb1d6defdf6..b0fda96078c54 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -334,7 +334,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return; } - let fn_body_hir_id = self.tcx.local_def_id_to_hir_id(typeck_results.hir_owner.def_id); let mut private_candidate: Option<(Ty<'tcx>, Ty<'tcx>, Span)> = None; for (deref_base_ty, _) in (self.autoderef_steps)(base_ty) { @@ -346,8 +345,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { continue; } - let (adjusted_ident, def_scope) = - self.tcx.adjust_ident_and_get_scope(field_ident, base_def.did(), fn_body_hir_id); + let (adjusted_ident, def_scope) = self.tcx.adjust_ident_and_get_scope( + field_ident, + base_def.did(), + typeck_results.hir_owner.def_id, + ); let Some((_, field_def)) = base_def.non_enum_variant().fields.iter_enumerated().find(|(_, field)| { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 3bd05eec07974..33fbcd8e32a6e 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -144,6 +144,7 @@ #![feature(legacy_receiver_trait)] #![feature(likely_unlikely)] #![feature(local_waker)] +#![feature(maybe_uninit_array_assume_init)] #![feature(maybe_uninit_uninit_array_transpose)] #![feature(panic_internals)] #![feature(pattern)] diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 97e4912596b94..b7fcecf11e059 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -445,6 +445,47 @@ impl DoubleEndedIterator for IntoIter { } } + #[inline] + fn next_chunk_back(&mut self) -> Result<[T; N], core::array::IntoIter> { + let mut raw_ary = [const { MaybeUninit::uninit() }; N]; + + let len = self.len(); + + if T::IS_ZST { + if len < N { + self.forget_remaining_elements(); + // Safety: ZSTs can be conjured ex nihilo, only the amount has to be correct + return Err(unsafe { array::IntoIter::new_unchecked(raw_ary, N - len..N) }); + } + + self.end = self.end.wrapping_byte_sub(N); + // Safety: ditto + return Ok(unsafe { MaybeUninit::array_assume_init(raw_ary) }); + } + + if len < N { + // Safety: `len` indicates that this many elements are available and we just checked that + // it fits into the array. + unsafe { + ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, len); + self.forget_remaining_elements(); + return Err(array::IntoIter::new_unchecked(raw_ary, 0..len)); + } + } + + // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize + // the array. + unsafe { + ptr::copy_nonoverlapping( + self.ptr.add(len - N).as_ptr(), + raw_ary.as_mut_ptr() as *mut T, + N, + ); + self.end = self.end.sub(N); + Ok(MaybeUninit::array_assume_init(raw_ary)) + } + } + #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { let step_size = self.len().min(n); diff --git a/library/alloctests/tests/vec.rs b/library/alloctests/tests/vec.rs index ccf9b8095b290..fc58e4364fe66 100644 --- a/library/alloctests/tests/vec.rs +++ b/library/alloctests/tests/vec.rs @@ -1027,6 +1027,15 @@ fn test_into_iter_next_chunk() { assert_eq!(iter.next_chunk::<4>().unwrap_err().as_slice(), &[]); // N is explicitly 4 } +#[test] +fn test_into_iter_next_chunk_back() { + let mut iter = b"lorem".to_vec().into_iter(); + + assert_eq!(iter.next_chunk_back().unwrap(), [b'e', b'm']); // N is inferred as 2 + assert_eq!(iter.next_chunk_back().unwrap(), [b'l', b'o', b'r']); // N is inferred as 3 + assert_eq!(iter.next_chunk_back::<4>().unwrap_err().as_slice(), &[]); // N is explicitly 4 +} + #[test] fn test_into_iter_clone() { fn iter_equal>(it: I, slice: &[i32]) { @@ -1131,6 +1140,14 @@ fn test_into_iter_zst() { let mut it = vec![C, C].into_iter(); it.next_chunk::<4>().unwrap_err(); drop(it); + + let mut it = vec![C, C].into_iter(); + it.next_chunk_back::<1>().unwrap(); + drop(it); + + let mut it = vec![C, C].into_iter(); + it.next_chunk_back::<4>().unwrap_err(); + drop(it); } #[test] diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 5784dbed03634..63a99349d7c9a 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -969,6 +969,54 @@ const impl Drop for Guard<'_, T> { } } +/// Panic guard for incremental initialization of arrays from the back. +/// +/// Elements of the array are populated starting from the end towards the beginning. +/// Disarm the guard with `mem::forget` once the array has been fully initialized. +/// +/// # Safety +/// +/// All write accesses to this structure are unsafe and must maintain a correct +/// count of `initialized` elements. +struct GuardBack<'a, T> { + /// The array to be initialized (will be filled from the end). + pub array_mut: &'a mut [MaybeUninit], + /// The number of items that have been initialized so far. + pub initialized: usize, +} + +impl GuardBack<'_, T> { + /// Adds an item to the array and updates the initialized item counter. + /// + /// # Safety + /// + /// No more than N elements must be initialized. + #[inline] + pub(crate) unsafe fn push_unchecked(&mut self, item: T) { + // SAFETY: If `initialized` was correct before and the caller does not + // invoke this method more than N times, then writes will be in-bounds + // and slots will not be initialized more than once. + unsafe { + let offset = self.initialized.unchecked_add(1); + let index = self.array_mut.len().unchecked_sub(offset); + self.array_mut.get_unchecked_mut(index).write(item); + self.initialized = offset; + } + } +} + +impl Drop for GuardBack<'_, T> { + #[inline] + fn drop(&mut self) { + debug_assert!(self.initialized <= self.array_mut.len()); + let len = self.array_mut.len(); + // SAFETY: this slice will contain only initialized objects. + unsafe { + self.array_mut.get_unchecked_mut(len - self.initialized..len).assume_init_drop(); + } + } +} + /// Pulls `N` items from `iter` and returns them as an array. If the iterator /// yields fewer than `N` items, `Err` is returned containing an iterator over /// the already yielded items. @@ -1076,3 +1124,109 @@ const fn iter_next_chunk_erased( mem::forget(guard); Ok(()) } + +/// Pulls `N` items from the back of `iter` and returns them as an array. +/// If the iterator yields fewer than `N` items, `Err` is returned containing +/// an iterator over the already yielded items. +/// +/// Since the iterator is passed as a mutable reference and this function calls +/// `next_back` at most `N` times, the iterator can still be used afterwards to +/// retrieve the remaining items. +/// +/// If `iter.next_back()` panics, all items already yielded by the iterator are +/// dropped. +/// +/// Used for [`DoubleEndedIterator::next_chunk_back`]. +#[inline] +pub(crate) fn iter_next_chunk_back( + iter: &mut impl DoubleEndedIterator, +) -> Result<[T; N], IntoIter> { + iter.spec_next_chunk_back() +} + +pub(crate) trait SpecNextChunkBack: + DoubleEndedIterator +{ + fn spec_next_chunk_back(&mut self) -> Result<[T; N], IntoIter>; +} + +impl, T, const N: usize> SpecNextChunkBack for I { + #[inline] + default fn spec_next_chunk_back(&mut self) -> Result<[T; N], IntoIter> { + let mut array = [const { MaybeUninit::uninit() }; N]; + let r = iter_next_chunk_back_erased(&mut array, self); + match r { + Ok(()) => { + // SAFETY: All elements of `array` were populated. + Ok(unsafe { MaybeUninit::array_assume_init(array) }) + } + Err(initialized) => { + // SAFETY: Only the last `initialized` elements were populated + Err(unsafe { IntoIter::new_unchecked(array, N - initialized..N) }) + } + } + } +} + +impl + TrustedLen, T, const N: usize> SpecNextChunkBack + for I +{ + fn spec_next_chunk_back(&mut self) -> Result<[T; N], IntoIter> { + let len = (*self).size_hint().0; + let mut array = [const { MaybeUninit::uninit() }; N]; + if len < N { + // SAFETY: `TrustedLen`, an unsafe trait, requires that i can get len items out of it. + unsafe { write_back(&mut array, self, len) }; + // SAFETY: Only the last `len` elements were populated + Err(unsafe { IntoIter::new_unchecked(array, N - len..N) }) + } else { + // SAFETY: `TrustedLen`, an unsafe trait, requires that i can get N items out of it. + unsafe { write_back(&mut array, self, N) }; + // SAFETY: All N items were populated + Ok(unsafe { MaybeUninit::array_assume_init(array) }) + } + } +} + +// SAFETY: `from` must have len items, and len items must be < N. +unsafe fn write_back( + to: &mut [MaybeUninit; N], + from: &mut impl DoubleEndedIterator, + len: usize, +) { + let mut guard = GuardBack { array_mut: to, initialized: 0 }; + while guard.initialized < len { + // SAFETY: caller has guaranteed, from has len items. + let item = unsafe { from.next_back().unwrap_unchecked() }; + // SAFETY: guard.initialized < len < N + unsafe { guard.push_unchecked(item) }; + } + crate::mem::forget(guard); +} + +/// Version of [`iter_next_chunk_back`] using a passed-in slice +/// in order to avoid needing to monomorphize for every array length. +/// +/// Unfortunately this loop has two exit conditions, the buffer filling up +/// or the iterator running out of items, making it tend to optimize poorly. +#[inline] +fn iter_next_chunk_back_erased( + buffer: &mut [MaybeUninit], + iter: &mut impl DoubleEndedIterator, +) -> Result<(), usize> { + // if `Iterator::next_back` panics, this guard will drop already initialized items + let mut guard = GuardBack { array_mut: buffer, initialized: 0 }; + while guard.initialized < guard.array_mut.len() { + let Some(item) = iter.next_back() else { + let initialized = guard.initialized; + mem::forget(guard); + return Err(initialized); + }; + + // SAFETY: The loop condition ensures we have space to push the item + unsafe { guard.push_unchecked(item) }; + } + + mem::forget(guard); + Ok(()) +} diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index ce80874a23897..a16732e1d8c74 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -1,3 +1,4 @@ +use crate::array; use crate::marker::Destruct; use crate::num::NonZero; use crate::ops::{ControlFlow, Try}; @@ -95,6 +96,53 @@ pub const trait DoubleEndedIterator: [const] Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn next_back(&mut self) -> Option; + /// Advances from the back of the iterator and returns an array containing the next + /// `N` values in sequence. + /// + /// If there are not enough elements to fill the array then `Err` is returned + /// containing an iterator over the remaining elements. + /// + /// Note: This is not equivalent to doing `iter.rev().next_chunk()` as this method + /// takes elements from the back of the iterator and preserves the order that the + /// elements were seen in the original iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_next_chunk)] + /// + /// let mut iter = "lorem".chars(); + /// + /// assert_eq!(iter.next_chunk_back().unwrap(), ['e', 'm']); // N is inferred as 2 + /// assert_eq!(iter.next_chunk_back().unwrap(), ['l', 'o', 'r']); // N is inferred as 3 + /// assert_eq!(iter.next_chunk_back::<4>().unwrap_err().as_slice(), &[]); // N is explicitly 4 + /// ``` + /// + /// Split a string and get the last three items in sequence. + /// + /// ``` + /// #![feature(iter_next_chunk)] + /// + /// let quote = "not all those who wander are lost"; + /// let [first, second, third] = quote.split_whitespace().next_chunk_back().unwrap(); + /// assert_eq!(first, "wander"); + /// assert_eq!(second, "are"); + /// assert_eq!(third, "lost"); + /// ``` + #[inline] + #[unstable(feature = "iter_next_chunk", issue = "98326")] + #[rustc_non_const_trait_method] + fn next_chunk_back( + &mut self, + ) -> Result<[Self::Item; N], array::IntoIter> + where + Self: Sized, + { + crate::array::iter_next_chunk_back(self) + } + /// Advances the iterator from the back by `n` elements. /// /// `advance_back_by` is the reverse version of [`advance_by`]. This method will diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index e41ede7498b06..66dde8377a37a 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1810,16 +1810,24 @@ pub const unsafe fn read(src: *const T) -> T { #[track_caller] #[rustc_diagnostic_item = "ptr_read_unaligned"] pub const unsafe fn read_unaligned(src: *const T) -> T { - let mut tmp = MaybeUninit::::uninit(); + // Always true thanks to the repr, but to demonstrate + const { + assert!(mem::offset_of!(Packed::, 0) == 0); + assert!(size_of::() == size_of::>()); + } + + let src = src.cast::>(); // SAFETY: the caller must guarantee that `src` is valid for reads. - // `src` cannot overlap `tmp` because `tmp` was just allocated on - // the stack as a separate allocation. + // Reading it as `Packed` instead of `T` reads those same bytes because + // it's the same size (thus zero offset), but with alignment 1 instead. // - // Also, since we just wrote a valid value into `tmp`, it is guaranteed - // to be properly initialized. + // Similarly, because it's the same bytes it's sound to transmute from the + // `Packed` to `T`. Transmute is a value-based (not a place-based) + // operation that doesn't care about alignment. unsafe { - copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, size_of::()); - tmp.assume_init() + let packed = read(src); + // Can't just destructure because that's not allowed in const fn + mem::transmute_neo(packed) } } @@ -2012,14 +2020,18 @@ pub const unsafe fn write(dst: *mut T, src: T) { #[rustc_diagnostic_item = "ptr_write_unaligned"] #[track_caller] pub const unsafe fn write_unaligned(dst: *mut T, src: T) { - // SAFETY: the caller must guarantee that `dst` is valid for writes. - // `dst` cannot overlap `src` because the caller has mutable access - // to `dst` while `src` is owned by this function. - unsafe { - copy_nonoverlapping((&raw const src) as *const u8, dst as *mut u8, size_of::()); - // We are calling the intrinsic directly to avoid function calls in the generated code. - intrinsics::forget(src); + // Always true thanks to the repr, but to demonstrate + const { + assert!(mem::offset_of!(Packed::, 0) == 0); + assert!(size_of::() == size_of::>()); } + + let dst = dst.cast::>(); + let src = Packed(src); + // SAFETY: the caller must guarantee that `dst` is valid for writes. + // Writing it as `Packed` instead of `T` writes those same bytes because + // it's the same size (thus zero offset), but with alignment 1 instead. + unsafe { write(dst, src) } } /// Performs a volatile read of the value from `src` without moving it. @@ -2809,3 +2821,6 @@ pub macro addr_of($place:expr) { pub macro addr_of_mut($place:expr) { &raw mut $place } + +#[repr(C, packed)] +struct Packed(T); diff --git a/library/coretests/tests/iter/adapters/filter.rs b/library/coretests/tests/iter/adapters/filter.rs index 167851e33336e..14cd3cbd58f10 100644 --- a/library/coretests/tests/iter/adapters/filter.rs +++ b/library/coretests/tests/iter/adapters/filter.rs @@ -63,3 +63,15 @@ fn test_next_chunk_does_not_leak() { assert_eq!(Rc::strong_count(w), 1); } } + +#[test] +fn test_next_chunk_back_does_not_leak() { + let drop_witness: [_; 5] = std::array::from_fn(|_| Rc::new(())); + + let v = (0..5).map(|i| drop_witness[i].clone()).collect::>(); + let _ = v.into_iter().filter(|_| false).next_chunk_back::<1>(); + + for ref w in drop_witness { + assert_eq!(Rc::strong_count(w), 1); + } +} diff --git a/library/coretests/tests/iter/traits/iterator.rs b/library/coretests/tests/iter/traits/iterator.rs index 386946461e9fe..0850b1e4edc26 100644 --- a/library/coretests/tests/iter/traits/iterator.rs +++ b/library/coretests/tests/iter/traits/iterator.rs @@ -619,6 +619,18 @@ fn test_next_chunk() { assert_eq!(it.next_chunk::<0>().unwrap(), []); } +#[test] +fn test_next_chunk_back() { + let mut it = 0..12; + assert_eq!(it.next_chunk_back().unwrap(), [8, 9, 10, 11]); + assert_eq!(it.next_chunk_back().unwrap(), []); + assert_eq!(it.next_chunk_back().unwrap(), [2, 3, 4, 5, 6, 7]); + assert_eq!(it.next_chunk_back::<4>().unwrap_err().as_slice(), &[0, 1]); + + let mut it = std::iter::once_with(|| panic!()); + assert_eq!(it.next_chunk_back::<0>().unwrap(), []); +} + #[test] fn test_next_chunk_untrusted() { struct Untrusted(I); @@ -636,6 +648,28 @@ fn test_next_chunk_untrusted() { assert_eq!(it.next_chunk::<4>().unwrap_err().as_slice(), &[10, 11]); } +#[test] +fn test_next_chunk_back_untrusted() { + struct Untrusted(I); + impl Iterator for Untrusted { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.0.next() + } + } + impl DoubleEndedIterator for Untrusted { + fn next_back(&mut self) -> Option { + self.0.next_back() + } + } + let mut it = Untrusted(0..12); + assert_eq!(it.next_chunk_back().unwrap(), [8, 9, 10, 11]); + assert_eq!(it.next_chunk_back().unwrap(), []); + assert_eq!(it.next_chunk_back().unwrap(), [2, 3, 4, 5, 6, 7]); + assert_eq!(it.next_chunk::<4>().unwrap_err().as_slice(), &[0, 1]); +} + #[test] fn test_collect_into_tuples() { let a = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)]; diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 3b3a5794ac4f1..dcec7b2a1077c 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -7,6 +7,8 @@ use crate::ffi::OsStr; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::path::Path; +#[cfg(doc)] +use crate::process::{ExitStatus, ExitStatusError}; use crate::sys::process::ChildPipe; use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::{io, process, sys}; @@ -272,35 +274,105 @@ impl CommandExt for process::Command { } } -/// Unix-specific extensions to [`process::ExitStatus`] and -/// [`ExitStatusError`](process::ExitStatusError). +/// Unix-specific extensions to [`ExitStatus`] and [`ExitStatusError`]. /// -/// On Unix, `ExitStatus` **does not necessarily represent an exit status**, as +/// On Unix, [`ExitStatus`] **does not necessarily represent an exit status**, as /// passed to the `_exit` system call or returned by -/// [`ExitStatus::code()`](crate::process::ExitStatus::code). It represents **any wait status** -/// as returned by one of the `wait` family of system +/// [`ExitStatus::code()`](ExitStatus::code). It represents **any wait status** +/// as returned by one of the [`wait`] family of system /// calls. /// -/// A Unix wait status (a Rust `ExitStatus`) can represent a Unix exit status, but can also +/// A Unix wait status (a Rust [`ExitStatus`]) can represent a Unix exit status, but can also /// represent other kinds of process event. +/// +/// [`wait`]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html #[stable(feature = "rust1", since = "1.0.0")] pub impl(self) trait ExitStatusExt { - /// Creates a new `ExitStatus` or `ExitStatusError` from the raw underlying integer status - /// value from `wait` + /// Creates a new [`ExitStatus`] or [`ExitStatusError`] from the raw underlying integer status + /// value from [`wait`]. /// /// The value should be a **wait status, not an exit status**. /// + /// # Example + /// + /// A signal-terminated [`wait`] status carries the signal number, which [`ExitStatus::signal`] + /// recovers using the platform's [`WTERMSIG`][`wait`] macro. Note that the bit layout of a + /// wait status is **not** specified by POSIX and is platform-specific. By convention on most + /// Unix platforms, the signal number occupies the low 7 bits with the exit-code byte left + /// zero, so a bare signal number between 1 and 126 is treated as a signal-terminated wait + /// status. The following example relies on that convention and is therefore not guaranteed to + /// hold on every target: + /// + /// ``` + /// # if cfg!(target_os = "fuchsia") { return; } + /// use std::os::unix::process::ExitStatusExt; + /// use std::process::ExitStatus; + /// + /// let signal = 15; // SIGTERM + /// assert!(signal > 0 && signal < 0x7f, "not a valid Unix termination signal: {signal}"); + /// + /// let status = ExitStatus::from_raw(signal); + /// assert!(!status.success()); + /// assert_eq!(status.code(), None); + /// assert_eq!(status.signal(), Some(15)); + /// ``` + /// + /// Generating an [`ExitStatus`] with a given exit code (0-255) is system-dependent. + /// The value returned by [`ExitStatus::code`] is specified to come from applying the + /// [`WEXITSTATUS`][`wait`] macro, but there is no POSIX-specified constructor and the bit + /// layout is left unspecified. By near-universal convention every Unix libc stores the + /// 8-bit exit code in bits 8..16, so a status built with `(code & 0xff) << 8` will usually + /// round-trip back to the original exit code: + /// + /// ``` + /// # if cfg!(target_os = "fuchsia") { return; } + /// use std::os::unix::process::ExitStatusExt; + /// use std::process::ExitStatus; + /// + /// let code = 41; + /// let status = ExitStatus::from_raw((code & 0xff) << 8); + /// assert_eq!(status.code(), Some(41)); + /// assert!(!status.success()); + /// ``` + /// /// # Panics /// - /// Panics on an attempt to make an `ExitStatusError` from a wait status of `0`. + /// - `ExitStatusError::from_raw` panics on an attempt to make an [`ExitStatusError`] from a + /// [`wait`] status of `0`. + /// - `ExitStatus::from_raw` always succeeds and never panics. /// - /// Making an `ExitStatus` always succeeds and never panics. + /// [`wait`]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html #[stable(feature = "exit_status_from", since = "1.12.0")] fn from_raw(raw: i32) -> Self; /// If the process was terminated by a signal, returns that signal. /// - /// In other words, if `WIFSIGNALED`, this returns `WTERMSIG`. + /// In other words, if [`WIFSIGNALED`][`wait`], this returns [`WTERMSIG`][`wait`]. For such a status, + /// [`ExitStatus::code`] returns `None`: + /// + /// ``` + /// # if cfg!(target_os = "fuchsia") { return; } + /// use std::os::unix::process::ExitStatusExt; + /// use std::process::ExitStatus; + /// + /// let sigterm = 15; + /// let status = ExitStatus::from_raw(sigterm); + /// assert_eq!(status.code(), None); + /// assert_eq!(status.signal(), Some(sigterm)); + /// ``` + /// + /// A process that receives a signal may catch and handle it, then exit normally with an + /// exit code. When that happens, `signal` returns `None`. + /// + /// Rust does not pass commands through a shell, such as `bash` and `sh`, but it + /// is possible to do so manually. When invoking a shell, the signal value indicates whether + /// the top-level shell itself received a terminating signal. If instead a command *within* + /// an invoked shell receives a terminating signal, many shells convert the signal number + /// into an exit code by adding 128. For example, a command run under `sh` that receives a + /// [`SIGTERM`] canonically causes the shell to report an exit code of `15 + 128`, i.e. `143`. + /// + /// [`SIGTERM`]: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/kill.html + /// [`wait`]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html #[stable(feature = "rust1", since = "1.0.0")] fn signal(&self) -> Option; @@ -310,21 +382,27 @@ pub impl(self) trait ExitStatusExt { /// If the process was stopped by a signal, returns that signal. /// - /// In other words, if `WIFSTOPPED`, this returns `WSTOPSIG`. This is only possible if the status came from - /// a `wait` system call which was passed `WUNTRACED`, and was then converted into an `ExitStatus`. + /// In other words, if [`WIFSTOPPED`][`wait`], this returns [`WSTOPSIG`][`wait`]. This is only possible if the status came from + /// a [`wait`] system call which was passed [`WUNTRACED`][`wait`], and was then converted into an [`ExitStatus`]. + /// + /// [`wait`]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html #[stable(feature = "unix_process_wait_more", since = "1.58.0")] fn stopped_signal(&self) -> Option; /// Whether the process was continued from a stopped status. /// - /// Ie, `WIFCONTINUED`. This is only possible if the status came from a `wait` system call - /// which was passed `WCONTINUED`, and was then converted into an `ExitStatus`. + /// I.e. [`WIFCONTINUED`][`wait`]. This is only possible if the status came from a [`wait`] system call + /// which was passed [`WCONTINUED`][`wait`], and was then converted into an [`ExitStatus`]. + /// + /// [`wait`]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html #[stable(feature = "unix_process_wait_more", since = "1.58.0")] fn continued(&self) -> bool; - /// Returns the underlying raw `wait` status. + /// Returns the underlying raw [`wait`] status. /// /// The returned integer is a **wait status, not an exit status**. + /// + /// [`wait`]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html #[stable(feature = "unix_process_wait_more", since = "1.58.0")] fn into_raw(self) -> i32; } diff --git a/library/std/src/sys/env/sgx.rs b/library/std/src/sys/env/sgx.rs index 094a7dfa90581..b45acfe7c1ba7 100644 --- a/library/std/src/sys/env/sgx.rs +++ b/library/std/src/sys/env/sgx.rs @@ -1,54 +1,35 @@ -#![allow(implicit_provenance_casts)] // FIXME: this module systematically confuses pointers and integers - pub use super::common::Env; use crate::collections::HashMap; use crate::ffi::{OsStr, OsString}; use crate::io; -use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; -use crate::sync::{Mutex, Once}; +use crate::sync::{Mutex, OnceLock}; + +type EnvStore = Mutex>; // Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests #[cfg_attr(test, linkage = "available_externally")] #[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os3ENVE")] -static ENV: Atomic = AtomicUsize::new(0); -// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests -#[cfg_attr(test, linkage = "available_externally")] -#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os8ENV_INITE")] -static ENV_INIT: Once = Once::new(); -type EnvStore = Mutex>; - -fn get_env_store() -> Option<&'static EnvStore> { - unsafe { (ENV.load(Ordering::Relaxed) as *const EnvStore).as_ref() } -} - -fn create_env_store() -> &'static EnvStore { - ENV_INIT.call_once(|| { - ENV.store(Box::into_raw(Box::new(EnvStore::default())) as _, Ordering::Relaxed) - }); - unsafe { &*(ENV.load(Ordering::Relaxed) as *const EnvStore) } -} +static ENV: OnceLock = OnceLock::new(); pub fn env() -> Env { - let clone_to_vec = |map: &HashMap| -> Vec<_> { - map.iter().map(|(k, v)| (k.clone(), v.clone())).collect() - }; - - let env = get_env_store().map(|env| clone_to_vec(&env.lock().unwrap())).unwrap_or_default(); + let env = ENV + .get() + .map(|env| env.lock().unwrap().iter().map(|(k, v)| (k.clone(), v.clone())).collect()) + .unwrap_or_default(); Env::new(env) } pub fn getenv(k: &OsStr) -> Option { - get_env_store().and_then(|s| s.lock().unwrap().get(k).cloned()) + ENV.get().and_then(|s| s.lock().unwrap().get(k).cloned()) } pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - let (k, v) = (k.to_owned(), v.to_owned()); - create_env_store().lock().unwrap().insert(k, v); + ENV.get_or_init(|| EnvStore::default()).lock().unwrap().insert(k.to_owned(), v.to_owned()); Ok(()) } pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { - if let Some(env) = get_env_store() { + if let Some(env) = ENV.get() { env.lock().unwrap().remove(k); } Ok(()) diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-reg.md b/src/doc/unstable-book/src/language-features/asm-experimental-reg.md index 5bbcb223b6026..095b541da6e46 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-reg.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-reg.md @@ -12,6 +12,8 @@ This tracks support for additional registers in architectures where inline assem | Architecture | Register class | Registers | LLVM constraint code | | ------------ | -------------- | --------- | -------------------- | +| LoongArch | `vreg` | `$vr[0-31]` | `f` | +| LoongArch | `xreg` | `$xr[0-31]` | `f` | ## Register class supported types @@ -20,11 +22,16 @@ This tracks support for additional registers in architectures where inline assem | x86 | `xmm_reg` | `sse` | `i128` | | x86 | `ymm_reg` | `avx` | `i128` | | x86 | `zmm_reg` | `avx512f` | `i128` | +| LoongArch | `vreg` | `lsx` | `f32`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | +| LoongArch | `xreg` | `lasx` | `f32`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`,
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` | ## Register aliases | Architecture | Base register | Aliases | | ------------ | ------------- | ------- | +| LoongArch | `$f[0-7]` | `$fa[0-7]`, `$vr[0-7]`, `$xr[0-7]` | +| LoongArch | `$f[8-23]` | `$ft[0-15]`, `$vr[8-23]`, `$xr[8-23]` | +| LoongArch | `$f[24-31]` | `$fs[0-7]`, `$vr[24-31]`, `$xr[24-31]` | ## Unsupported registers @@ -35,3 +42,9 @@ This tracks support for additional registers in architectures where inline assem | Architecture | Register class | Modifier | Example output | LLVM modifier | | ------------ | -------------- | -------- | -------------- | ------------- | +| LoongArch | `freg` | `w` | `$vr0` | `w` | +| LoongArch | `freg` | `u` | `$xr0` | `u` | +| LoongArch | `vreg` | None | `$vr0` | `w` | +| LoongArch | `vreg` | `u` | `$xr0` | `u` | +| LoongArch | `xreg` | None | `$xr0` | `u` | +| LoongArch | `xreg` | `w` | `$vr0` | `w` | diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 554bcb2621ac6..f77e201805a2b 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -350,28 +350,21 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { pub(crate) fn print_const(tcx: TyCtxt<'_>, n: ty::Const<'_>) -> String { match n.kind() { - ty::ConstKind::Alias(_, ty::AliasConst { kind, .. }) => match kind { - ty::AliasConstKind::Projection { def_id } => { - if let Some(local_def_id) = def_id.as_local() - && let Some(body_id) = tcx.hir_maybe_body_owned_by(local_def_id) - { - rendered_const(tcx, body_id, local_def_id) - } else { - n.to_string() - } - } - ty::AliasConstKind::Inherent { def_id } - | ty::AliasConstKind::Free { def_id } - | ty::AliasConstKind::Anon { def_id } => { - if let Some(local_def_id) = def_id.as_local() - && let Some(body_id) = tcx.hir_maybe_body_owned_by(local_def_id) - { - rendered_const(tcx, body_id, local_def_id) - } else { - inline::print_inlined_const(tcx, def_id) - } + ty::ConstKind::Alias(_, ty::AliasConst { kind, .. }) => { + let def_id: DefId = match kind { + ty::AliasConstKind::Projection { def_id } => def_id.into(), + ty::AliasConstKind::Inherent { def_id } => def_id.into(), + ty::AliasConstKind::Free { def_id } => def_id.into(), + ty::AliasConstKind::Anon { def_id } => def_id.into(), + }; + if let Some(local_def_id) = def_id.as_local() + && let Some(body_id) = tcx.hir_maybe_body_owned_by(local_def_id) + { + rendered_const(tcx, body_id, local_def_id) + } else { + n.to_string() } - }, + } // array lengths are obviously usize ty::ConstKind::Value(cv) if *cv.ty.kind() == ty::Uint(ty::UintTy::Usize) => { cv.to_leaf().to_string() diff --git a/tests/assembly-llvm/asm/loongarch-modifiers.rs b/tests/assembly-llvm/asm/loongarch-modifiers.rs new file mode 100644 index 0000000000000..93a58864ef451 --- /dev/null +++ b/tests/assembly-llvm/asm/loongarch-modifiers.rs @@ -0,0 +1,225 @@ +//@ add-minicore +//@ revisions: loongarch32 loongarch64 + +//@ assembly-output: emit-asm +//@ needs-llvm-components: loongarch + +//@[loongarch32] compile-flags: --target loongarch32-unknown-none +//@[loongarch32] compile-flags: -Ctarget-feature=+32s,+lasx + +//@[loongarch64] compile-flags: --target loongarch64-unknown-none +//@[loongarch64] compile-flags: -Ctarget-feature=+lasx + +//@ compile-flags: -Ctarget-feature=+32s +//@ compile-flags: -Zmerge-functions=disabled + +#![feature(asm_experimental_reg, no_core, repr_simd)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register)] + +extern crate minicore; +use minicore::*; + +#[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]); +#[repr(simd)] +pub struct i8x32([i8; 32]); +#[repr(simd)] +pub struct i16x16([i16; 16]); +#[repr(simd)] +pub struct i32x8([i32; 8]); +#[repr(simd)] +pub struct i64x4([i64; 4]); +#[repr(simd)] +pub struct f32x8([f32; 8]); +#[repr(simd)] +pub struct f64x4([f64; 4]); + +impl Copy for i8x16 {} +impl Copy for i16x8 {} +impl Copy for i32x4 {} +impl Copy for i64x2 {} +impl Copy for f32x4 {} +impl Copy for f64x2 {} +impl Copy for i8x32 {} +impl Copy for i16x16 {} +impl Copy for i32x8 {} +impl Copy for i64x4 {} +impl Copy for f32x8 {} +impl Copy for f64x4 {} + +macro_rules! check { ($func:ident, $ty:ty, $class:ident, $code:literal) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + let y; + asm!($code, out($class) y, in($class) x); + y + } +};} + +// CHECK-LABEL: freg_f32_lsx: +// CHECK: #APP +// CHECK: vfadd.s $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(freg_f32_lsx, f32, freg, "vfadd.s {1:w}, {0:w}, {0:w}"); + +// CHECK-LABEL: freg_f64_lasx: +// CHECK: #APP +// CHECK: xvfadd.d $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(freg_f64_lasx, f64, freg, "xvfadd.d {1:u}, {0:u}, {0:u}"); + +// CHECK-LABEL: vreg_i8x16_lsx: +// CHECK: #APP +// CHECK: vadd.b $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_i8x16_lsx, i8x16, vreg, "vadd.b {1}, {0}, {0}"); + +// CHECK-LABEL: vreg_i8x16_lasx: +// CHECK: #APP +// CHECK: xvadd.b $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_i8x16_lasx, i8x16, vreg, "xvadd.b {1:u}, {0:u}, {0:u}"); + +// CHECK-LABEL: vreg_i16x8_lsx: +// CHECK: #APP +// CHECK: vadd.h $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_i16x8_lsx, i16x8, vreg, "vadd.h {1}, {0}, {0}"); + +// CHECK-LABEL: vreg_i16x8_lasx: +// CHECK: #APP +// CHECK: xvadd.h $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_i16x8_lasx, i16x8, vreg, "xvadd.h {1:u}, {0:u}, {0:u}"); + +// CHECK-LABEL: vreg_i32x4_lsx: +// CHECK: #APP +// CHECK: vadd.w $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_i32x4_lsx, i32x4, vreg, "vadd.w {1}, {0}, {0}"); + +// CHECK-LABEL: vreg_i32x4_lasx: +// CHECK: #APP +// CHECK: xvadd.w $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_i32x4_lasx, i32x4, vreg, "xvadd.w {1:u}, {0:u}, {0:u}"); + +// CHECK-LABEL: vreg_i64x2_lsx: +// CHECK: #APP +// CHECK: vadd.d $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_i64x2_lsx, i64x2, vreg, "vadd.d {1}, {0}, {0}"); + +// CHECK-LABEL: vreg_i64x2_lasx: +// CHECK: #APP +// CHECK: xvadd.d $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_i64x2_lasx, i64x2, vreg, "xvadd.d {1:u}, {0:u}, {0:u}"); + +// CHECK-LABEL: vreg_f32x4_lsx: +// CHECK: #APP +// CHECK: vfadd.s $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_f32x4_lsx, f32x4, vreg, "vfadd.s {1}, {0}, {0}"); + +// CHECK-LABEL: vreg_f32x4_lasx: +// CHECK: #APP +// CHECK: xvfadd.s $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_f32x4_lasx, f32x4, vreg, "xvfadd.s {1:u}, {0:u}, {0:u}"); + +// CHECK-LABEL: vreg_f64x2_lsx: +// CHECK: #APP +// CHECK: vfadd.d $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_f64x2_lsx, f64x2, vreg, "vfadd.d {1}, {0}, {0}"); + +// CHECK-LABEL: vreg_f64x2_lasx: +// CHECK: #APP +// CHECK: xvfadd.d $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(vreg_f64x2_lasx, f64x2, vreg, "xvfadd.d {1:u}, {0:u}, {0:u}"); + +// CHECK-LABEL: xreg_i8x32_lasx: +// CHECK: #APP +// CHECK: xvadd.b $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_i8x32_lasx, i8x32, xreg, "xvadd.b {1}, {0}, {0}"); + +// CHECK-LABEL: xreg_i8x32_lsx: +// CHECK: #APP +// CHECK: vadd.b $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_i8x32_lsx, i8x32, xreg, "vadd.b {1:w}, {0:w}, {0:w}"); + +// CHECK-LABEL: xreg_i16x16_lasx: +// CHECK: #APP +// CHECK: xvadd.h $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_i16x16_lasx, i16x16, xreg, "xvadd.h {1}, {0}, {0}"); + +// CHECK-LABEL: xreg_i16x16_lsx: +// CHECK: #APP +// CHECK: vadd.h $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_i16x16_lsx, i16x16, xreg, "vadd.h {1:w}, {0:w}, {0:w}"); + +// CHECK-LABEL: xreg_i32x8_lasx: +// CHECK: #APP +// CHECK: xvadd.w $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_i32x8_lasx, i32x8, xreg, "xvadd.w {1}, {0}, {0}"); + +// CHECK-LABEL: xreg_i32x8_lsx: +// CHECK: #APP +// CHECK: vadd.w $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_i32x8_lsx, i32x8, xreg, "vadd.w {1:w}, {0:w}, {0:w}"); + +// CHECK-LABEL: xreg_i64x4_lasx: +// CHECK: #APP +// CHECK: xvadd.d $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_i64x4_lasx, i64x4, xreg, "xvadd.d {1}, {0}, {0}"); + +// CHECK-LABEL: xreg_i64x4_lsx: +// CHECK: #APP +// CHECK: vadd.d $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_i64x4_lsx, i64x4, xreg, "vadd.d {1:w}, {0:w}, {0:w}"); + +// CHECK-LABEL: xreg_f32x8_lasx: +// CHECK: #APP +// CHECK: xvfadd.s $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_f32x8_lasx, f32x8, xreg, "xvfadd.s {1}, {0}, {0}"); + +// CHECK-LABEL: xreg_f32x8_lsx: +// CHECK: #APP +// CHECK: vfadd.s $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_f32x8_lsx, f32x8, xreg, "vfadd.s {1:w}, {0:w}, {0:w}"); + +// CHECK-LABEL: xreg_f64x4_lasx: +// CHECK: #APP +// CHECK: xvfadd.d $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}}, $xr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_f64x4_lasx, f64x4, xreg, "xvfadd.d {1}, {0}, {0}"); + +// CHECK-LABEL: xreg_f64x4_lsx: +// CHECK: #APP +// CHECK: vfadd.d $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}}, $vr{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(xreg_f64x4_lsx, f64x4, xreg, "vfadd.d {1:w}, {0:w}, {0:w}"); diff --git a/tests/codegen-llvm/read_write_unaligned.rs b/tests/codegen-llvm/read_write_unaligned.rs new file mode 100644 index 0000000000000..beba4400dc54a --- /dev/null +++ b/tests/codegen-llvm/read_write_unaligned.rs @@ -0,0 +1,71 @@ +//@ compile-flags: -Copt-level=3 +//@ only-64bit + +#![crate_type = "lib"] + +use std::num::NonZero; +use std::ptr::NonNull; + +// CHECK-LABEL: nonnull ptr @read_unaligned_ptr(ptr{{.+}}%ptr) +#[no_mangle] +unsafe fn read_unaligned_ptr(ptr: *const NonNull) -> NonNull { + // CHECK: start: + // CHECK-NEXT: [[TEMP:%.+]] = load ptr, ptr %ptr, align 1 + // CHECK-SAME: !nonnull + // CHECK-SAME: !noundef + // CHECK-NEXT: ret ptr [[TEMP]] + ptr.read_unaligned() +} + +// CHECK-LABEL: range(i16 1, 0) i16 @read_unaligned_i16(ptr{{.+}}%ptr) +#[no_mangle] +unsafe fn read_unaligned_i16(ptr: *const NonZero) -> NonZero { + // CHECK: start: + // CHECK-NEXT: [[TEMP:%.+]] = load i16, ptr %ptr, align 1 + // CHECK-NOT: !noundef + // CHECK-NOT: !range + // CHECK-NEXT: ret i16 [[TEMP]] + ptr.read_unaligned() +} + +// CHECK-LABEL: void @typed_copy_unaligned_i32(ptr{{.+}}%src, ptr{{.+}}%dst) +#[no_mangle] +unsafe fn typed_copy_unaligned_i32(src: *const NonZero, dst: *mut NonZero) { + // CHECK: start: + // CHECK-NEXT: [[TEMP:%.+]] = load i32, ptr %src, align 1 + // CHECK-NOT: !noundef + // CHECK-NOT: !range + // CHECK-NEXT: store i32 [[TEMP]], ptr %dst, align 1 + // CHECK-NEXT: ret void + dst.write_unaligned(src.read_unaligned()) +} + +// CHECK-LABEL: void @write_unaligned_i64(ptr{{.+}}%ptr, i64{{.+}}%val) +#[no_mangle] +unsafe fn write_unaligned_i64(ptr: *mut NonZero, val: NonZero) { + // CHECK: start: + // CHECK-NEXT: store i64 %val, ptr %ptr, align 1 + // CHECK-NEXT: ret void + ptr.write_unaligned(val) +} + +#[repr(align(128))] +struct HugeBuffer([u64; 1 << 10]); + +// CHECK-LABEL: void @read_unaligned_huge(ptr{{.+}}%_0, ptr{{.+}}%ptr) +#[no_mangle] +unsafe fn read_unaligned_huge(ptr: *const HugeBuffer) -> HugeBuffer { + // CHECK: start: + // CHECK-NEXT: call void @llvm.memcpy{{.+}} align 128 dereferenceable(8192) %_0, {{.+}} align 1 dereferenceable(8192) %ptr, i64 8192, + // CHECK-NEXT: ret void + ptr.read_unaligned() +} + +// CHECK-LABEL: void @write_unaligned_huge(ptr{{.+}}%ptr, ptr{{.+}}%val) +#[no_mangle] +unsafe fn write_unaligned_huge(ptr: *mut HugeBuffer, val: HugeBuffer) { + // CHECK: start: + // CHECK-NEXT: call void @llvm.memcpy{{.+}} align 1 dereferenceable(8192) %ptr, {{.+}} align 128 dereferenceable(8192) %val, i64 8192, + // CHECK-NEXT: ret void + ptr.write_unaligned(val) +} diff --git a/tests/mir-opt/pre-codegen/unaligned.rs b/tests/mir-opt/pre-codegen/unaligned.rs new file mode 100644 index 0000000000000..4aeb10c261e21 --- /dev/null +++ b/tests/mir-opt/pre-codegen/unaligned.rs @@ -0,0 +1,39 @@ +//@ compile-flags: -O -Zmir-opt-level=2 +//@ ignore-std-debug-assertions (there's one in `ptr::read`) + +#![crate_type = "lib"] + +// EMIT_MIR unaligned.unaligned_copy_manual.runtime-optimized.after.mir +pub unsafe fn unaligned_copy_manual(src: *const u128, dst: *mut u128) { + #[repr(packed)] + struct Packed(T); + + // CHECK-LABEL: fn unaligned_copy_manual(_1: *const u128, _2: *mut u128) -> () + // CHECK: [[SRCU:_.+]] = copy _1 as *const unaligned_copy_manual::Packed (PtrToPtr); + // CHECK: [[DSTU:_.+]] = copy _2 as *mut unaligned_copy_manual::Packed (PtrToPtr); + // CHECK: [[TEMP:_.+]] = copy ((*[[SRCU]]).0: u128); + // ((*[[DSTU]]).0: u128) = move [[TEMP]]; + let src = src.cast::>(); + let dst = dst.cast::>(); + unsafe { (*dst).0 = (*src).0 }; +} + +// EMIT_MIR unaligned.unaligned_copy_generic.runtime-optimized.after.mir +pub unsafe fn unaligned_copy_generic(src: *const T, dst: *mut T) { + // CHECK-LABEL: fn unaligned_copy_generic( + // CHECK: debug src => _1; + // CHECK: debug dst => _2; + // CHECK: debug val => [[VAL:_.+]]; + // CHECK: [[SRC_P:_.+]] = copy _1 as *const {{.+}}::Packed (PtrToPtr); + // CHECK: [[PACKED1:_.+]] = copy (*[[SRC_P]]); + // CHECK: [[VAL]] = copy [[PACKED1]] as T (Transmute); + // CHECK: [[DST_P:_.+]] = copy _2 as *mut {{.+}}::Packed (PtrToPtr); + // CHECK: [[PACKED2:_.+]] = {{.+}}::Packed::(copy [[VAL]]); + // CHECK: (*[[DST_P]]) = copy [[PACKED2]]; + // CHECK-NOT: copy_nonoverlapping + // CHECK-NOT: drop + unsafe { + let val = std::ptr::read_unaligned(src); + std::ptr::write_unaligned(dst, val); + } +} diff --git a/tests/mir-opt/pre-codegen/unaligned.unaligned_copy_generic.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/unaligned.unaligned_copy_generic.runtime-optimized.after.mir new file mode 100644 index 0000000000000..4d0cfa6a4dfa3 --- /dev/null +++ b/tests/mir-opt/pre-codegen/unaligned.unaligned_copy_generic.runtime-optimized.after.mir @@ -0,0 +1,57 @@ +// MIR for `unaligned_copy_generic` after runtime-optimized + +fn unaligned_copy_generic(_1: *const T, _2: *mut T) -> () { + debug src => _1; + debug dst => _2; + let mut _0: (); + let _5: T; + scope 1 { + debug val => _5; + scope 8 (inlined #[track_caller] write_unaligned::) { + let _6: *mut std::ptr::Packed; + scope 9 { + let _7: std::ptr::Packed; + scope 10 { + scope 12 (inlined #[track_caller] std::ptr::write::>) { + } + } + } + scope 11 (inlined std::ptr::mut_ptr::::cast::>) { + } + } + } + scope 2 (inlined #[track_caller] read_unaligned::) { + let _3: *const std::ptr::Packed; + scope 3 { + let _4: std::ptr::Packed; + scope 4 { + scope 7 (inlined transmute_neo::, T>) { + } + } + scope 6 (inlined #[track_caller] std::ptr::read::>) { + } + } + scope 5 (inlined std::ptr::const_ptr::::cast::>) { + } + } + + bb0: { + StorageLive(_5); + StorageLive(_3); + _3 = copy _1 as *const std::ptr::Packed (PtrToPtr); + StorageLive(_4); + _4 = copy (*_3); + _5 = copy _4 as T (Transmute); + StorageDead(_4); + StorageDead(_3); + StorageLive(_6); + _6 = copy _2 as *mut std::ptr::Packed (PtrToPtr); + StorageLive(_7); + _7 = std::ptr::Packed::(copy _5); + (*_6) = copy _7; + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/unaligned.unaligned_copy_manual.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/unaligned.unaligned_copy_manual.runtime-optimized.after.mir new file mode 100644 index 0000000000000..450df935a0fb3 --- /dev/null +++ b/tests/mir-opt/pre-codegen/unaligned.unaligned_copy_manual.runtime-optimized.after.mir @@ -0,0 +1,34 @@ +// MIR for `unaligned_copy_manual` after runtime-optimized + +fn unaligned_copy_manual(_1: *const u128, _2: *mut u128) -> () { + debug src => _1; + debug dst => _2; + let mut _0: (); + let _3: *const unaligned_copy_manual::Packed; + let mut _5: u128; + scope 1 { + debug src => _3; + let _4: *mut unaligned_copy_manual::Packed; + scope 2 { + debug dst => _4; + } + scope 4 (inlined std::ptr::mut_ptr::::cast::>) { + } + } + scope 3 (inlined std::ptr::const_ptr::::cast::>) { + } + + bb0: { + StorageLive(_3); + _3 = copy _1 as *const unaligned_copy_manual::Packed (PtrToPtr); + StorageLive(_4); + _4 = copy _2 as *mut unaligned_copy_manual::Packed (PtrToPtr); + StorageLive(_5); + _5 = copy ((*_3).0: u128); + ((*_4).0: u128) = move _5; + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + return; + } +} diff --git a/tests/rustdoc-html/type-const-free-in-array.rs b/tests/rustdoc-html/type-const-free-in-array.rs new file mode 100644 index 0000000000000..bea46596caa58 --- /dev/null +++ b/tests/rustdoc-html/type-const-free-in-array.rs @@ -0,0 +1,11 @@ +#![crate_name = "foo"] +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +type const N: usize = 2; + +//@ has 'foo/trait.CollectArray.html' +//@ has - '//pre[@class="rust item-decl"]/code' '[A; N]' +pub trait CollectArray { + fn inner_array(&mut self) -> [A; N]; +} diff --git a/tests/rustdoc-html/type-const-inherent-with-body.rs b/tests/rustdoc-html/type-const-inherent-with-body.rs new file mode 100644 index 0000000000000..e9771b1f606c1 --- /dev/null +++ b/tests/rustdoc-html/type-const-inherent-with-body.rs @@ -0,0 +1,15 @@ +#![crate_name = "foo"] +#![feature(min_generic_const_args, inherent_associated_types)] +#![expect(incomplete_features)] + +pub struct Foo; + +impl Foo { + type const LEN: usize = 4; +} + +//@ has 'foo/fn.mk_array.html' +//@ has - '//pre[@class="rust item-decl"]/code' '[u8; Foo::LEN]' +pub fn mk_array() -> [u8; Foo::LEN] { + [0u8; Foo::LEN] +} diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr index c67c913d2a60d..28ac455c06441 100644 --- a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr +++ b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr @@ -1,38 +1,259 @@ error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", out("$r0") _); | ^^^^^^^^^^^^ error: invalid register `$tp`: reserved for TLS - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("$tp") _); | ^^^^^^^^^^^^ error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", out("$sp") _); | ^^^^^^^^^^^^ error: invalid register `$r21`: reserved by the ABI - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", out("$r21") _); | ^^^^^^^^^^^^^ error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:36:18 | LL | asm!("", out("$fp") _); | ^^^^^^^^^^^^ error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:38:18 | LL | asm!("", out("$r31") _); | ^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0658]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:52:26 + | +LL | asm!("/* {} */", in(vreg) f); + | ^^^^^^^^^^ + | + = 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:55:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + | + = 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:57:26 + | +LL | asm!("/* {} */", in(vreg) d); + | ^^^^^^^^^^ + | + = 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:60:26 + | +LL | asm!("/* {} */", out(vreg) d); + | ^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:65:26 + | +LL | asm!("/* {} */", in(xreg) f); + | ^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:68:26 + | +LL | asm!("/* {} */", out(xreg) _); + | ^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:70:26 + | +LL | asm!("/* {} */", in(xreg) d); + | ^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:73:26 + | +LL | asm!("/* {} */", out(xreg) d); + | ^^^^^^^^^^^ + | + = 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:77:31 + | +LL | asm!("", in("$f0") f, in("$vr0") d); + | ^^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:82:31 + | +LL | asm!("", in("$f0") f, in("$xr0") d); + | ^^^^^^^^^^^^ + | + = 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:87:18 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:87:32 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^^^^^^^^^^^^ + | + = 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 `f32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:52:35 + | +LL | asm!("/* {} */", in(vreg) f); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:57:35 + | +LL | asm!("/* {} */", in(vreg) d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:60:36 + | +LL | asm!("/* {} */", out(vreg) d); + | ^ + | + = 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 `f32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:65:35 + | +LL | asm!("/* {} */", in(xreg) f); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:70:35 + | +LL | asm!("/* {} */", in(xreg) d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:73:36 + | +LL | asm!("/* {} */", out(xreg) d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:77:42 + | +LL | asm!("", in("$f0") f, in("$vr0") d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:82:42 + | +LL | asm!("", in("$f0") f, in("$xr0") d); + | ^ + | + = 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 `f32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:87:29 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:87:43 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^ + | + = 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 28 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr index 99c071919acfa..1ee1b86989c4d 100644 --- a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr +++ b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr @@ -1,62 +1,295 @@ error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", out("$r0") _); | ^^^^^^^^^^^^ error: invalid register `$tp`: reserved for TLS - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("$tp") _); | ^^^^^^^^^^^^ error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", out("$sp") _); | ^^^^^^^^^^^^ error: invalid register `$r21`: reserved by the ABI - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", out("$r21") _); | ^^^^^^^^^^^^^ error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:36:18 | LL | asm!("", out("$fp") _); | ^^^^^^^^^^^^ error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:38:18 | LL | asm!("", out("$r31") _); | ^^^^^^^^^^^^^ +error[E0658]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:52:26 + | +LL | asm!("/* {} */", in(vreg) f); + | ^^^^^^^^^^ + | + = 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:55:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + | + = 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:57:26 + | +LL | asm!("/* {} */", in(vreg) d); + | ^^^^^^^^^^ + | + = 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:60:26 + | +LL | asm!("/* {} */", out(vreg) d); + | ^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:65:26 + | +LL | asm!("/* {} */", in(xreg) f); + | ^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:68:26 + | +LL | asm!("/* {} */", out(xreg) _); + | ^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:70:26 + | +LL | asm!("/* {} */", in(xreg) d); + | ^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:73:26 + | +LL | asm!("/* {} */", out(xreg) d); + | ^^^^^^^^^^^ + | + = 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:77:31 + | +LL | asm!("", in("$f0") f, in("$vr0") d); + | ^^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:82:31 + | +LL | asm!("", in("$f0") f, in("$xr0") d); + | ^^^^^^^^^^^^ + | + = 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:87:18 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:87:32 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^^^^^^^^^^^^ + | + = 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 `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:40:26 + --> $DIR/bad-reg.rs:42:26 | LL | asm!("/* {} */", in(freg) f); | ^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:42:26 + --> $DIR/bad-reg.rs:44:26 | LL | asm!("/* {} */", out(freg) _); | ^^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:44:26 + --> $DIR/bad-reg.rs:46:26 | LL | asm!("/* {} */", in(freg) d); | ^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:46:26 + --> $DIR/bad-reg.rs:48:26 | LL | asm!("/* {} */", out(freg) d); | ^^^^^^^^^^^ -error: aborting due to 10 previous errors +error[E0658]: type `f32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:52:35 + | +LL | asm!("/* {} */", in(vreg) f); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:57:35 + | +LL | asm!("/* {} */", in(vreg) d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:60:36 + | +LL | asm!("/* {} */", out(vreg) d); + | ^ + | + = 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 `f32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:65:35 + | +LL | asm!("/* {} */", in(xreg) f); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:70:35 + | +LL | asm!("/* {} */", in(xreg) d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:73:36 + | +LL | asm!("/* {} */", out(xreg) d); + | ^ + | + = 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 `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:77:18 + | +LL | asm!("", in("$f0") f, in("$vr0") d); + | ^^^^^^^^^^^ + +error[E0658]: type `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:77:42 + | +LL | asm!("", in("$f0") f, in("$vr0") d); + | ^ + | + = 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 `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:82:18 + | +LL | asm!("", in("$f0") f, in("$xr0") d); + | ^^^^^^^^^^^ + +error[E0658]: type `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:82:42 + | +LL | asm!("", in("$f0") f, in("$xr0") d); + | ^ + | + = 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 `f32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:87:29 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:87:43 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^ + | + = 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 34 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr index c67c913d2a60d..97462d6dc5f0b 100644 --- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr +++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr @@ -1,38 +1,62 @@ error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", out("$r0") _); | ^^^^^^^^^^^^ error: invalid register `$tp`: reserved for TLS - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("$tp") _); | ^^^^^^^^^^^^ error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", out("$sp") _); | ^^^^^^^^^^^^ error: invalid register `$r21`: reserved by the ABI - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", out("$r21") _); | ^^^^^^^^^^^^^ error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:36:18 | LL | asm!("", out("$fp") _); | ^^^^^^^^^^^^ error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:38:18 | LL | asm!("", out("$r31") _); | ^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: register `$vr0` conflicts with register `$f0` + --> $DIR/bad-reg.rs:77:31 + | +LL | asm!("", in("$f0") f, in("$vr0") d); + | ----------- ^^^^^^^^^^^^ register `$vr0` + | | + | register `$f0` + +error: register `$xr0` conflicts with register `$f0` + --> $DIR/bad-reg.rs:82:31 + | +LL | asm!("", in("$f0") f, in("$xr0") d); + | ----------- ^^^^^^^^^^^^ register `$xr0` + | | + | register `$f0` + +error: register `$xr0` conflicts with register `$vr0` + --> $DIR/bad-reg.rs:87:32 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ------------ ^^^^^^^^^^^^ register `$xr0` + | | + | register `$vr0` + +error: aborting due to 9 previous errors diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr index 99c071919acfa..1ee1b86989c4d 100644 --- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr +++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr @@ -1,62 +1,295 @@ error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", out("$r0") _); | ^^^^^^^^^^^^ error: invalid register `$tp`: reserved for TLS - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("$tp") _); | ^^^^^^^^^^^^ error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", out("$sp") _); | ^^^^^^^^^^^^ error: invalid register `$r21`: reserved by the ABI - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", out("$r21") _); | ^^^^^^^^^^^^^ error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:36:18 | LL | asm!("", out("$fp") _); | ^^^^^^^^^^^^ error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:38:18 | LL | asm!("", out("$r31") _); | ^^^^^^^^^^^^^ +error[E0658]: register class `vreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:52:26 + | +LL | asm!("/* {} */", in(vreg) f); + | ^^^^^^^^^^ + | + = 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:55:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + | + = 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:57:26 + | +LL | asm!("/* {} */", in(vreg) d); + | ^^^^^^^^^^ + | + = 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:60:26 + | +LL | asm!("/* {} */", out(vreg) d); + | ^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:65:26 + | +LL | asm!("/* {} */", in(xreg) f); + | ^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:68:26 + | +LL | asm!("/* {} */", out(xreg) _); + | ^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:70:26 + | +LL | asm!("/* {} */", in(xreg) d); + | ^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:73:26 + | +LL | asm!("/* {} */", out(xreg) d); + | ^^^^^^^^^^^ + | + = 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:77:31 + | +LL | asm!("", in("$f0") f, in("$vr0") d); + | ^^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:82:31 + | +LL | asm!("", in("$f0") f, in("$xr0") d); + | ^^^^^^^^^^^^ + | + = 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:87:18 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^^^^^^^^^^^^ + | + = 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 `xreg` can only be used as a clobber in stable + --> $DIR/bad-reg.rs:87:32 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^^^^^^^^^^^^ + | + = 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 `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:40:26 + --> $DIR/bad-reg.rs:42:26 | LL | asm!("/* {} */", in(freg) f); | ^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:42:26 + --> $DIR/bad-reg.rs:44:26 | LL | asm!("/* {} */", out(freg) _); | ^^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:44:26 + --> $DIR/bad-reg.rs:46:26 | LL | asm!("/* {} */", in(freg) d); | ^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:46:26 + --> $DIR/bad-reg.rs:48:26 | LL | asm!("/* {} */", out(freg) d); | ^^^^^^^^^^^ -error: aborting due to 10 previous errors +error[E0658]: type `f32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:52:35 + | +LL | asm!("/* {} */", in(vreg) f); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:57:35 + | +LL | asm!("/* {} */", in(vreg) d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:60:36 + | +LL | asm!("/* {} */", out(vreg) d); + | ^ + | + = 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 `f32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:65:35 + | +LL | asm!("/* {} */", in(xreg) f); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:70:35 + | +LL | asm!("/* {} */", in(xreg) d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:73:36 + | +LL | asm!("/* {} */", out(xreg) d); + | ^ + | + = 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 `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:77:18 + | +LL | asm!("", in("$f0") f, in("$vr0") d); + | ^^^^^^^^^^^ + +error[E0658]: type `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:77:42 + | +LL | asm!("", in("$f0") f, in("$vr0") d); + | ^ + | + = 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 `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:82:18 + | +LL | asm!("", in("$f0") f, in("$xr0") d); + | ^^^^^^^^^^^ + +error[E0658]: type `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:82:42 + | +LL | asm!("", in("$f0") f, in("$xr0") d); + | ^ + | + = 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 `f32` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:87:29 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^ + | + = 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 `f64` cannot be used with this register class in stable + --> $DIR/bad-reg.rs:87:43 + | +LL | asm!("", in("$vr0") f, in("$xr0") d); + | ^ + | + = 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 34 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/asm/loongarch/bad-reg.rs b/tests/ui/asm/loongarch/bad-reg.rs index 7d28884966d46..6bda28eb10fde 100644 --- a/tests/ui/asm/loongarch/bad-reg.rs +++ b/tests/ui/asm/loongarch/bad-reg.rs @@ -4,12 +4,14 @@ //@[loongarch32_ilp32d] needs-llvm-components: loongarch //@[loongarch32_ilp32s] compile-flags: --target loongarch32-unknown-none-softfloat //@[loongarch32_ilp32s] needs-llvm-components: loongarch -//@[loongarch64_lp64d] compile-flags: --target loongarch64-unknown-linux-gnu +//@[loongarch64_lp64d] compile-flags: --target loongarch64-unknown-linux-gnu -Ctarget-feature=+lasx //@[loongarch64_lp64d] needs-llvm-components: loongarch //@[loongarch64_lp64s] compile-flags: --target loongarch64-unknown-none-softfloat //@[loongarch64_lp64s] needs-llvm-components: loongarch //@ ignore-backends: gcc +#![cfg_attr(loongarch64_lp64d, feature(asm_experimental_reg))] + #![crate_type = "lib"] #![feature(no_core)] #![no_core] @@ -45,5 +47,48 @@ fn f() { //[loongarch32_ilp32s,loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f asm!("/* {} */", out(freg) d); //[loongarch32_ilp32s,loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f + + asm!("", out("$vr0") _); // ok + asm!("/* {} */", in(vreg) f); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `vreg` can only be used as a clobber in stable + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR type `f32` cannot be used with this register class in stable + asm!("/* {} */", out(vreg) _); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `vreg` can only be used as a clobber in stable + asm!("/* {} */", in(vreg) d); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `vreg` can only be used as a clobber in stable + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR type `f64` cannot be used with this register class in stable + asm!("/* {} */", out(vreg) d); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `vreg` can only be used as a clobber in stable + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR type `f64` cannot be used with this register class in stable + + asm!("", out("$xr0") _); // ok + asm!("/* {} */", in(xreg) f); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `xreg` can only be used as a clobber in stable + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR type `f32` cannot be used with this register class in stable + asm!("/* {} */", out(xreg) _); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `xreg` can only be used as a clobber in stable + asm!("/* {} */", in(xreg) d); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `xreg` can only be used as a clobber in stable + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR type `f64` cannot be used with this register class in stable + asm!("/* {} */", out(xreg) d); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `xreg` can only be used as a clobber in stable + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR type `f64` cannot be used with this register class in stable + + asm!("", in("$f0") f, in("$vr0") d); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `vreg` can only be used as a clobber in stable + //[loongarch32_ilp32s,loongarch64_lp64s]~| ERROR register class `freg` requires at least one of the following target features: d, f + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR type `f64` cannot be used with this register class in stable + //[loongarch64_lp64d]~^^^^ ERROR register `$vr0` conflicts with register `$f0` + asm!("", in("$f0") f, in("$xr0") d); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `xreg` can only be used as a clobber in stable + //[loongarch32_ilp32s,loongarch64_lp64s]~| ERROR register class `freg` requires at least one of the following target features: d, f + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR type `f64` cannot be used with this register class in stable + //[loongarch64_lp64d]~^^^^ ERROR register `$xr0` conflicts with register `$f0` + asm!("", in("$vr0") f, in("$xr0") d); + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~^ ERROR register class `vreg` can only be used as a clobber in stable + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR register class `xreg` can only be used as a clobber in stable + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR type `f32` cannot be used with this register class in stable + //[loongarch32_ilp32s,loongarch32_ilp32d,loongarch64_lp64s]~| ERROR type `f64` cannot be used with this register class in stable + //[loongarch64_lp64d]~^^^^^ ERROR register `$xr0` conflicts with register `$vr0` } }