diff options
| author | bors <bors@rust-lang.org> | 2024-10-01 16:32:19 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-10-01 16:32:19 +0000 |
| commit | c817d5dc2050ec443516f9700c19b1419593a83d (patch) | |
| tree | e21ddbb656fecc18a950d2edfdfa454bd40fa040 /compiler | |
| parent | 8dd5cd0bc1d683c30805e1dc831cac546b621a75 (diff) | |
| parent | 91f079aacf2dcb7352b18bc909528f7af7ef506f (diff) | |
| download | rust-c817d5dc2050ec443516f9700c19b1419593a83d.tar.gz rust-c817d5dc2050ec443516f9700c19b1419593a83d.zip | |
Auto merge of #131098 - GuillaumeGomez:rollup-kk74was, r=GuillaumeGomez
Rollup of 5 pull requests Successful merges: - #130630 (Support clobber_abi and vector/access registers (clobber-only) in s390x inline assembly) - #131042 (Instantiate binders in `supertrait_vtable_slot`) - #131079 (Update wasm-component-ld to 0.5.9) - #131085 (make test_lots_of_insertions test take less long in Miri) - #131088 (add fixme to remove LLVM_ENABLE_TERMINFO when minimal llvm version is 19) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_gcc/src/asm.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/asm.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_target/src/asm/mod.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_target/src/asm/s390x.rs | 111 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/engine.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/vtable.rs | 90 |
7 files changed, 224 insertions, 38 deletions
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 13a00f7e08d..a04cd4735f4 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -682,6 +682,11 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::S390x( + S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg, + ) => { + unreachable!("clobber-only") + } InlineAsmRegClass::Err => unreachable!(), }, }; @@ -757,6 +762,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr, ) => cx.type_i32(), InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 7621f111fe2..82ca3f519f7 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -708,6 +708,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> S390x(S390xInlineAsmRegClass::reg) => "r", S390x(S390xInlineAsmRegClass::reg_addr) => "a", S390x(S390xInlineAsmRegClass::freg) => "f", + S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { + unreachable!("clobber-only") + } Msp430(Msp430InlineAsmRegClass::reg) => "r", M68k(M68kInlineAsmRegClass::reg) => "r", M68k(M68kInlineAsmRegClass::reg_addr) => "a", @@ -866,6 +869,9 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(), S390x(S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr) => cx.type_i32(), S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), + S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { + unreachable!("clobber-only") + } Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(), M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8f226b26bef..e8aa129c6cd 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -411,6 +411,7 @@ symbols! { arbitrary_enum_discriminant, arbitrary_self_types, arbitrary_self_types_pointers, + areg, args, arith_offset, arm, diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 4d8c5cea8a8..df13d24cb9e 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -439,7 +439,7 @@ impl InlineAsmReg { Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), Self::LoongArch(_) => cb(self), Self::Mips(_) => cb(self), - Self::S390x(_) => cb(self), + Self::S390x(r) => r.overlapping_regs(|r| cb(Self::S390x(r))), Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))), Self::Msp430(_) => cb(self), @@ -892,6 +892,7 @@ pub enum InlineAsmClobberAbi { AArch64NoX18, RiscV, LoongArch, + S390x, } impl InlineAsmClobberAbi { @@ -941,6 +942,10 @@ impl InlineAsmClobberAbi { "C" | "system" => Ok(InlineAsmClobberAbi::LoongArch), _ => Err(&["C", "system"]), }, + InlineAsmArch::S390x => match name { + "C" | "system" => Ok(InlineAsmClobberAbi::S390x), + _ => Err(&["C", "system"]), + }, _ => Err(&[]), } } @@ -1098,6 +1103,28 @@ impl InlineAsmClobberAbi { f16, f17, f18, f19, f20, f21, f22, f23, } }, + InlineAsmClobberAbi::S390x => clobbered_regs! { + S390x S390xInlineAsmReg { + r0, r1, r2, r3, r4, r5, + r14, + + // f0-f7, v0-v7 + f0, f1, f2, f3, f4, f5, f6, f7, + v0, v1, v2, v3, v4, v5, v6, v7, + + // Technically the left halves of v8-v15 (i.e., f8-f15) are saved, but + // we have no way of expressing this using clobbers. + v8, v9, v10, v11, v12, v13, v14, v15, + + // Other vector registers are volatile + v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, + + // a0-a1 are reserved, other access registers are volatile + a2, a3, a4, a5, a6, a7, + a8, a9, a10, a11, a12, a13, a14, a15, + } + }, } } } diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index 4258b23ac57..9b31190a72b 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -9,6 +9,8 @@ def_reg_class! { reg, reg_addr, freg, + vreg, + areg, } } @@ -35,11 +37,13 @@ impl S390xInlineAsmRegClass { pub fn supported_types( self, - arch: InlineAsmArch, + _arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option<Symbol>)] { - match (self, arch) { - (Self::reg | Self::reg_addr, _) => types! { _: I8, I16, I32, I64; }, - (Self::freg, _) => types! { _: F32, F64; }, + match self { + Self::reg | Self::reg_addr => types! { _: I8, I16, I32, I64; }, + Self::freg => types! { _: F32, F64; }, + Self::vreg => &[], + Self::areg => &[], } } } @@ -76,6 +80,52 @@ def_regs! { f13: freg = ["f13"], f14: freg = ["f14"], f15: freg = ["f15"], + v0: vreg = ["v0"], + v1: vreg = ["v1"], + v2: vreg = ["v2"], + v3: vreg = ["v3"], + v4: vreg = ["v4"], + v5: vreg = ["v5"], + v6: vreg = ["v6"], + v7: vreg = ["v7"], + v8: vreg = ["v8"], + v9: vreg = ["v9"], + v10: vreg = ["v10"], + v11: vreg = ["v11"], + v12: vreg = ["v12"], + v13: vreg = ["v13"], + v14: vreg = ["v14"], + v15: vreg = ["v15"], + v16: vreg = ["v16"], + v17: vreg = ["v17"], + v18: vreg = ["v18"], + v19: vreg = ["v19"], + v20: vreg = ["v20"], + v21: vreg = ["v21"], + v22: vreg = ["v22"], + v23: vreg = ["v23"], + v24: vreg = ["v24"], + v25: vreg = ["v25"], + v26: vreg = ["v26"], + v27: vreg = ["v27"], + v28: vreg = ["v28"], + v29: vreg = ["v29"], + v30: vreg = ["v30"], + v31: vreg = ["v31"], + a2: areg = ["a2"], + a3: areg = ["a3"], + a4: areg = ["a4"], + a5: areg = ["a5"], + a6: areg = ["a6"], + a7: areg = ["a7"], + a8: areg = ["a8"], + a9: areg = ["a9"], + a10: areg = ["a10"], + a11: areg = ["a11"], + a12: areg = ["a12"], + a13: areg = ["a13"], + a14: areg = ["a14"], + a15: areg = ["a15"], #error = ["r11"] => "The frame pointer cannot be used as an operand for inline asm", #error = ["r15"] => @@ -87,13 +137,8 @@ def_regs! { "c12", "c13", "c14", "c15" ] => "control registers are reserved by the kernel and cannot be used as operands for inline asm", - #error = [ - "a0", "a1", "a2", "a3", - "a4", "a5", "a6", "a7", - "a8", "a9", "a10", "a11", - "a12", "a13", "a14", "a15" - ] => - "access registers are not supported and cannot be used as operands for inline asm", + #error = ["a0", "a1"] => + "a0 and a1 are reserved for system use and cannot be used as operands for inline asm", } } @@ -106,4 +151,48 @@ impl S390xInlineAsmReg { ) -> fmt::Result { write!(out, "%{}", self.name()) } + + pub fn overlapping_regs(self, mut cb: impl FnMut(S390xInlineAsmReg)) { + macro_rules! reg_conflicts { + ( + $( + $full:ident : $($field:ident)* + ),*; + ) => { + match self { + $( + Self::$full => { + cb(Self::$full); + $(cb(Self::$field);)* + } + $(Self::$field)|* => { + cb(Self::$full); + cb(self); + } + )* + r => cb(r), + } + }; + } + + // The left halves of v0-v15 are aliased to f0-f15. + reg_conflicts! { + v0 : f0, + v1 : f1, + v2 : f2, + v3 : f3, + v4 : f4, + v5 : f5, + v6 : f6, + v7 : f7, + v8 : f8, + v9 : f9, + v10 : f10, + v11 : f11, + v12 : f12, + v13 : f13, + v14 : f14, + v15 : f15; + } + } } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index de1d4ef15ac..d562692c1a8 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -9,12 +9,13 @@ use rustc_infer::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, }; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, TypeTrace}; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast, Variance}; +use rustc_type_ir::relate::Relate; use super::{FromSolverError, FulfillmentContext, ScrubbedTraitError, TraitEngine}; use crate::error_reporting::InferCtxtErrorExt; @@ -133,6 +134,20 @@ where .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } + pub fn eq_trace<T: Relate<TyCtxt<'tcx>>>( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + trace: TypeTrace<'tcx>, + expected: T, + actual: T, + ) -> Result<(), TypeError<'tcx>> { + self.infcx + .at(cause, param_env) + .eq_trace(DefineOpaqueTypes::Yes, trace, expected, actual) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) + } + /// Checks whether `expected` is a subtype of `actual`: `expected <: actual`. pub fn sub<T: ToTrace<'tcx>>( &self, diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index a2760fe6049..6e6f948a2cd 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -2,6 +2,9 @@ use std::fmt::Debug; use std::ops::ControlFlow; use rustc_hir::def_id::DefId; +use rustc_infer::infer::at::ToTrace; +use rustc_infer::infer::{BoundRegionConversionTime, TyCtxtInferExt}; +use rustc_infer::traits::ObligationCause; use rustc_infer::traits::util::PredicateSet; use rustc_middle::bug; use rustc_middle::query::Providers; @@ -13,7 +16,7 @@ use smallvec::{SmallVec, smallvec}; use tracing::debug; use crate::errors::DumpVTableEntries; -use crate::traits::{impossible_predicates, is_vtable_safe_method}; +use crate::traits::{ObligationCtxt, impossible_predicates, is_vtable_safe_method}; #[derive(Clone, Debug)] pub enum VtblSegment<'tcx> { @@ -22,6 +25,8 @@ pub enum VtblSegment<'tcx> { } /// Prepare the segments for a vtable +// FIXME: This should take a `PolyExistentialTraitRef`, since we don't care +// about our `Self` type here. pub fn prepare_vtable_segments<'tcx, T>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, @@ -327,14 +332,10 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe let ty::Dynamic(source, _, _) = *key.self_ty().kind() else { bug!(); }; - let source_principal = tcx - .normalize_erasing_regions(ty::ParamEnv::reveal_all(), source.principal().unwrap()) - .with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let source_principal = + source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self); - let target_principal = tcx - .normalize_erasing_regions(ty::ParamEnv::reveal_all(), key) - // We don't care about the self type, since it will always be the same thing. - .with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let target_principal = ty::Binder::dummy(ty::ExistentialTraitRef::erase_self_ty(tcx, key)); let vtable_segment_callback = { let mut vptr_offset = 0; @@ -343,15 +344,18 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe VtblSegment::MetadataDSA => { vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len(); } - VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - if tcx - .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), trait_ref) - == target_principal - { + VtblSegment::TraitOwnEntries { trait_ref: vtable_principal, emit_vptr } => { + if trait_refs_are_compatible( + tcx, + vtable_principal + .map_bound(|t| ty::ExistentialTraitRef::erase_self_ty(tcx, t)), + target_principal, + ) { return ControlFlow::Break(vptr_offset); } - vptr_offset += tcx.own_existential_vtable_entries(trait_ref.def_id()).len(); + vptr_offset += + tcx.own_existential_vtable_entries(vtable_principal.def_id()).len(); if emit_vptr { vptr_offset += 1; @@ -383,17 +387,14 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( let ty::Dynamic(target, _, _) = *target.kind() else { bug!(); }; - let target_principal = tcx - .normalize_erasing_regions(ty::ParamEnv::reveal_all(), target.principal()?) - .with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let target_principal = target.principal()?; // Given that we have a target principal, it is a bug for there not to be a source principal. let ty::Dynamic(source, _, _) = *source.kind() else { bug!(); }; - let source_principal = tcx - .normalize_erasing_regions(ty::ParamEnv::reveal_all(), source.principal().unwrap()) - .with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let source_principal = + source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self); let vtable_segment_callback = { let mut vptr_offset = 0; @@ -402,11 +403,15 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( VtblSegment::MetadataDSA => { vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len(); } - VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - vptr_offset += tcx.own_existential_vtable_entries(trait_ref.def_id()).len(); - if tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), trait_ref) - == target_principal - { + VtblSegment::TraitOwnEntries { trait_ref: vtable_principal, emit_vptr } => { + vptr_offset += + tcx.own_existential_vtable_entries(vtable_principal.def_id()).len(); + if trait_refs_are_compatible( + tcx, + vtable_principal + .map_bound(|t| ty::ExistentialTraitRef::erase_self_ty(tcx, t)), + target_principal, + ) { if emit_vptr { return ControlFlow::Break(Some(vptr_offset)); } else { @@ -426,6 +431,41 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap() } +fn trait_refs_are_compatible<'tcx>( + tcx: TyCtxt<'tcx>, + hr_vtable_principal: ty::PolyExistentialTraitRef<'tcx>, + hr_target_principal: ty::PolyExistentialTraitRef<'tcx>, +) -> bool { + if hr_vtable_principal.def_id() != hr_target_principal.def_id() { + return false; + } + + let infcx = tcx.infer_ctxt().build(); + let param_env = ty::ParamEnv::reveal_all(); + let ocx = ObligationCtxt::new(&infcx); + let hr_source_principal = + ocx.normalize(&ObligationCause::dummy(), param_env, hr_vtable_principal); + let hr_target_principal = + ocx.normalize(&ObligationCause::dummy(), param_env, hr_target_principal); + infcx.enter_forall(hr_target_principal, |target_principal| { + let source_principal = infcx.instantiate_binder_with_fresh_vars( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + hr_source_principal, + ); + let Ok(()) = ocx.eq_trace( + &ObligationCause::dummy(), + param_env, + ToTrace::to_trace(&ObligationCause::dummy(), hr_target_principal, hr_source_principal), + target_principal, + source_principal, + ) else { + return false; + }; + ocx.select_all_or_error().is_empty() + }) +} + pub(super) fn provide(providers: &mut Providers) { *providers = Providers { own_existential_vtable_entries, |
