diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_abi/src/callconv.rs | 254 | ||||
| -rw-r--r-- | compiler/rustc_abi/src/layout.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_abi/src/layout/ty.rs (renamed from compiler/rustc_target/src/abi/mod.rs) | 12 | ||||
| -rw-r--r-- | compiler/rustc_abi/src/lib.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/const_eval/machine.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/memory.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/non_local_def.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/aarch64.rs (renamed from compiler/rustc_target/src/abi/call/aarch64.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/amdgpu.rs (renamed from compiler/rustc_target/src/abi/call/amdgpu.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/arm.rs (renamed from compiler/rustc_target/src/abi/call/arm.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/avr.rs (renamed from compiler/rustc_target/src/abi/call/avr.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/bpf.rs (renamed from compiler/rustc_target/src/abi/call/bpf.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/csky.rs (renamed from compiler/rustc_target/src/abi/call/csky.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/hexagon.rs (renamed from compiler/rustc_target/src/abi/call/hexagon.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/loongarch.rs (renamed from compiler/rustc_target/src/abi/call/loongarch.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/m68k.rs (renamed from compiler/rustc_target/src/abi/call/m68k.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/mips.rs (renamed from compiler/rustc_target/src/abi/call/mips.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/mips64.rs (renamed from compiler/rustc_target/src/abi/call/mips64.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/mod.rs (renamed from compiler/rustc_target/src/abi/call/mod.rs) | 249 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/msp430.rs (renamed from compiler/rustc_target/src/abi/call/msp430.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/nvptx64.rs (renamed from compiler/rustc_target/src/abi/call/nvptx64.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/powerpc.rs (renamed from compiler/rustc_target/src/abi/call/powerpc.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/powerpc64.rs (renamed from compiler/rustc_target/src/abi/call/powerpc64.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/riscv.rs (renamed from compiler/rustc_target/src/abi/call/riscv.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/s390x.rs (renamed from compiler/rustc_target/src/abi/call/s390x.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/sparc.rs (renamed from compiler/rustc_target/src/abi/call/sparc.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/sparc64.rs (renamed from compiler/rustc_target/src/abi/call/sparc64.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/wasm.rs (renamed from compiler/rustc_target/src/abi/call/wasm.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/x86.rs (renamed from compiler/rustc_target/src/abi/call/x86.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/x86_64.rs (renamed from compiler/rustc_target/src/abi/call/x86_64.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/x86_win64.rs (renamed from compiler/rustc_target/src/abi/call/x86_win64.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/callconv/xtensa.rs (renamed from compiler/rustc_target/src/abi/call/xtensa.rs) | 0 | ||||
| -rw-r--r-- | compiler/rustc_target/src/json.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_target/src/lib.rs | 11 |
35 files changed, 311 insertions, 278 deletions
diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs new file mode 100644 index 00000000000..2ecac8a9df1 --- /dev/null +++ b/compiler/rustc_abi/src/callconv.rs @@ -0,0 +1,254 @@ +mod abi { + pub(crate) use crate::Primitive::*; + pub(crate) use crate::Variants; +} + +use rustc_macros::HashStable_Generic; + +use crate::{Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] +pub enum RegKind { + Integer, + Float, + Vector, +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] +pub struct Reg { + pub kind: RegKind, + pub size: Size, +} + +macro_rules! reg_ctor { + ($name:ident, $kind:ident, $bits:expr) => { + pub fn $name() -> Reg { + Reg { kind: RegKind::$kind, size: Size::from_bits($bits) } + } + }; +} + +impl Reg { + reg_ctor!(i8, Integer, 8); + reg_ctor!(i16, Integer, 16); + reg_ctor!(i32, Integer, 32); + reg_ctor!(i64, Integer, 64); + reg_ctor!(i128, Integer, 128); + + reg_ctor!(f32, Float, 32); + reg_ctor!(f64, Float, 64); +} + +impl Reg { + pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align { + let dl = cx.data_layout(); + match self.kind { + RegKind::Integer => match self.size.bits() { + 1 => dl.i1_align.abi, + 2..=8 => dl.i8_align.abi, + 9..=16 => dl.i16_align.abi, + 17..=32 => dl.i32_align.abi, + 33..=64 => dl.i64_align.abi, + 65..=128 => dl.i128_align.abi, + _ => panic!("unsupported integer: {self:?}"), + }, + RegKind::Float => match self.size.bits() { + 16 => dl.f16_align.abi, + 32 => dl.f32_align.abi, + 64 => dl.f64_align.abi, + 128 => dl.f128_align.abi, + _ => panic!("unsupported float: {self:?}"), + }, + RegKind::Vector => dl.vector_align(self.size).abi, + } + } +} + +/// Return value from the `homogeneous_aggregate` test function. +#[derive(Copy, Clone, Debug)] +pub enum HomogeneousAggregate { + /// Yes, all the "leaf fields" of this struct are passed in the + /// same way (specified in the `Reg` value). + Homogeneous(Reg), + + /// There are no leaf fields at all. + NoData, +} + +/// Error from the `homogeneous_aggregate` test function, indicating +/// there are distinct leaf fields passed in different ways, +/// or this is uninhabited. +#[derive(Copy, Clone, Debug)] +pub struct Heterogeneous; + +impl HomogeneousAggregate { + /// If this is a homogeneous aggregate, returns the homogeneous + /// unit, else `None`. + pub fn unit(self) -> Option<Reg> { + match self { + HomogeneousAggregate::Homogeneous(reg) => Some(reg), + HomogeneousAggregate::NoData => None, + } + } + + /// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in + /// the same `struct`. Only succeeds if only one of them has any data, + /// or both units are identical. + fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> { + match (self, other) { + (x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x), + + (HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => { + if a != b { + return Err(Heterogeneous); + } + Ok(self) + } + } + } +} + +impl<'a, Ty> TyAndLayout<'a, Ty> { + /// Returns `true` if this is an aggregate type (including a ScalarPair!) + pub fn is_aggregate(&self) -> bool { + match self.abi { + Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false, + Abi::ScalarPair(..) | Abi::Aggregate { .. } => true, + } + } + + /// Returns `Homogeneous` if this layout is an aggregate containing fields of + /// only a single type (e.g., `(u32, u32)`). Such aggregates are often + /// special-cased in ABIs. + /// + /// Note: We generally ignore 1-ZST fields when computing this value (see #56877). + /// + /// This is public so that it can be used in unit tests, but + /// should generally only be relevant to the ABI details of + /// specific targets. + pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous> + where + Ty: TyAbiInterface<'a, C> + Copy, + { + match self.abi { + Abi::Uninhabited => Err(Heterogeneous), + + // The primitive for this algorithm. + Abi::Scalar(scalar) => { + let kind = match scalar.primitive() { + abi::Int(..) | abi::Pointer(_) => RegKind::Integer, + abi::Float(_) => RegKind::Float, + }; + Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size })) + } + + Abi::Vector { .. } => { + assert!(!self.is_zst()); + Ok(HomogeneousAggregate::Homogeneous(Reg { + kind: RegKind::Vector, + size: self.size, + })) + } + + Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => { + // Helper for computing `homogeneous_aggregate`, allowing a custom + // starting offset (used below for handling variants). + let from_fields_at = + |layout: Self, + start: Size| + -> Result<(HomogeneousAggregate, Size), Heterogeneous> { + let is_union = match layout.fields { + FieldsShape::Primitive => { + unreachable!("aggregates can't have `FieldsShape::Primitive`") + } + FieldsShape::Array { count, .. } => { + assert_eq!(start, Size::ZERO); + + let result = if count > 0 { + layout.field(cx, 0).homogeneous_aggregate(cx)? + } else { + HomogeneousAggregate::NoData + }; + return Ok((result, layout.size)); + } + FieldsShape::Union(_) => true, + FieldsShape::Arbitrary { .. } => false, + }; + + let mut result = HomogeneousAggregate::NoData; + let mut total = start; + + for i in 0..layout.fields.count() { + let field = layout.field(cx, i); + if field.is_1zst() { + // No data here and no impact on layout, can be ignored. + // (We might be able to also ignore all aligned ZST but that's less clear.) + continue; + } + + if !is_union && total != layout.fields.offset(i) { + // This field isn't just after the previous one we considered, abort. + return Err(Heterogeneous); + } + + result = result.merge(field.homogeneous_aggregate(cx)?)?; + + // Keep track of the offset (without padding). + let size = field.size; + if is_union { + total = total.max(size); + } else { + total += size; + } + } + + Ok((result, total)) + }; + + let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?; + + match &self.variants { + abi::Variants::Single { .. } => {} + abi::Variants::Multiple { variants, .. } => { + // Treat enum variants like union members. + // HACK(eddyb) pretend the `enum` field (discriminant) + // is at the start of every variant (otherwise the gap + // at the start of all variants would disqualify them). + // + // NB: for all tagged `enum`s (which include all non-C-like + // `enum`s with defined FFI representation), this will + // match the homogeneous computation on the equivalent + // `struct { tag; union { variant1; ... } }` and/or + // `union { struct { tag; variant1; } ... }` + // (the offsets of variant fields should be identical + // between the two for either to be a homogeneous aggregate). + let variant_start = total; + for variant_idx in variants.indices() { + let (variant_result, variant_total) = + from_fields_at(self.for_variant(cx, variant_idx), variant_start)?; + + result = result.merge(variant_result)?; + total = total.max(variant_total); + } + } + } + + // There needs to be no padding. + if total != self.size { + Err(Heterogeneous) + } else { + match result { + HomogeneousAggregate::Homogeneous(_) => { + assert_ne!(total, Size::ZERO); + } + HomogeneousAggregate::NoData => { + assert_eq!(total, Size::ZERO); + } + } + Ok(result) + } + } + Abi::Aggregate { sized: false } => Err(Heterogeneous), + } + } +} diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 620a051eeb7..6e1299944a0 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -11,6 +11,10 @@ use crate::{ Variants, WrappingRange, }; +mod ty; + +pub use ty::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx}; + // A variant is absent if it's uninhabited and only has ZST fields. // Present uninhabited variants only require space for their fields, // but *not* an encoding of the discriminant (e.g., a tag value). diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_abi/src/layout/ty.rs index b744d5ad4ed..c6812c4d4c0 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -6,18 +6,8 @@ use Primitive::*; use rustc_data_structures::intern::Interned; use rustc_macros::HashStable_Generic; -use crate::json::{Json, ToJson}; - -pub mod call; - // Explicitly import `Float` to avoid ambiguity with `Primitive::Float`. -pub use rustc_abi::{Float, *}; - -impl ToJson for Endian { - fn to_json(&self) -> Json { - self.as_str().to_json() - } -} +use crate::{Float, *}; rustc_index::newtype_index! { /// The *source-order* index of a field in a variant. diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index fa7c98a7fa0..84d756b6d51 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1,6 +1,7 @@ // tidy-alphabetical-start #![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(feature = "nightly", doc(rust_logo))] +#![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![cfg_attr(feature = "nightly", feature(rustdoc_internals))] #![cfg_attr(feature = "nightly", feature(step_trait))] #![warn(unreachable_pub)] @@ -22,11 +23,16 @@ use rustc_macros::HashStable_Generic; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_Generic, Encodable_Generic}; +mod callconv; mod layout; #[cfg(test)] mod tests; -pub use layout::{LayoutCalculator, LayoutCalculatorError}; +pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind}; +pub use layout::{ + FIRST_VARIANT, FieldIdx, Layout, LayoutCalculator, LayoutCalculatorError, TyAbiInterface, + TyAndLayout, VariantIdx, +}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 4aec74595bc..2db43a0f787 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -140,7 +140,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> { #[inline(always)] fn filter_map_collect<T>(&self, mut f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T> { - self.iter().filter_map(move |(k, v)| f(k, &*v)).collect() + self.iter().filter_map(move |(k, v)| f(k, v)).collect() } #[inline(always)] diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index e6ab8ca12a8..7700eb792ef 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -993,11 +993,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { bytes } - /// Find leaked allocations. Allocations reachable from `static_roots` or a `Global` allocation - /// are not considered leaked, as well as leaks whose kind's `may_leak()` returns true. - pub fn find_leaked_allocations( - &self, - static_roots: &[AllocId], + /// Find leaked allocations, remove them from memory and return them. Allocations reachable from + /// `static_roots` or a `Global` allocation are not considered leaked, as well as leaks whose + /// kind's `may_leak()` returns true. + /// + /// This is highly destructive, no more execution can happen after this! + pub fn take_leaked_allocations( + &mut self, + static_roots: impl FnOnce(&Self) -> &[AllocId], ) -> Vec<(AllocId, MemoryKind<M::MemoryKind>, Allocation<M::Provenance, M::AllocExtra, M::Bytes>)> { // Collect the set of allocations that are *reachable* from `Global` allocations. @@ -1008,7 +1011,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.memory.alloc_map.filter_map_collect(move |&id, &(kind, _)| { if Some(kind) == global_kind { Some(id) } else { None } }); - todo.extend(static_roots); + todo.extend(static_roots(self)); while let Some(id) = todo.pop() { if reachable.insert(id) { // This is a new allocation, add the allocation it points to `todo`. @@ -1023,13 +1026,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; // All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking. - self.memory.alloc_map.filter_map_collect(|id, (kind, alloc)| { - if kind.may_leak() || reachable.contains(id) { - None - } else { - Some((*id, *kind, alloc.clone())) - } - }) + let leaked: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| { + if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) } + }); + let mut result = Vec::new(); + for &id in leaked.iter() { + let (kind, alloc) = self.memory.alloc_map.remove(&id).unwrap(); + result.push((id, kind, alloc)); + } + result } /// Runs the closure in "validation" mode, which means the machine's memory read hooks will be diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 6fecddb3319..3c31b879bd6 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -301,9 +301,13 @@ fn did_has_local_parent( return false; }; - peel_parent_while(tcx, parent_did, |tcx, did| tcx.def_kind(did) == DefKind::Mod) - .map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent) - .unwrap_or(false) + peel_parent_while(tcx, parent_did, |tcx, did| { + tcx.def_kind(did) == DefKind::Mod + || (tcx.def_kind(did) == DefKind::Const + && tcx.opt_item_name(did) == Some(kw::Underscore)) + }) + .map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent) + .unwrap_or(false) } /// Given a `DefId` checks if it satisfies `f` if it does check with it's parent and continue diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 50e7be82a79..1bdcae4dfb4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -12,6 +12,7 @@ use std::marker::PhantomData; use std::ops::{Bound, Deref}; use std::{fmt, iter, mem}; +use rustc_abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_ast::{self as ast, attr}; use rustc_data_structures::defer; use rustc_data_structures::fingerprint::Fingerprint; @@ -48,7 +49,6 @@ use rustc_session::{Limit, MetadataKind, Session}; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; use rustc_type_ir::TyKind::*; use rustc_type_ir::fold::TypeFoldable; diff --git a/compiler/rustc_target/src/abi/call/aarch64.rs b/compiler/rustc_target/src/callconv/aarch64.rs index 55b65fb1caa..55b65fb1caa 100644 --- a/compiler/rustc_target/src/abi/call/aarch64.rs +++ b/compiler/rustc_target/src/callconv/aarch64.rs diff --git a/compiler/rustc_target/src/abi/call/amdgpu.rs b/compiler/rustc_target/src/callconv/amdgpu.rs index 3007a729a8b..3007a729a8b 100644 --- a/compiler/rustc_target/src/abi/call/amdgpu.rs +++ b/compiler/rustc_target/src/callconv/amdgpu.rs diff --git a/compiler/rustc_target/src/abi/call/arm.rs b/compiler/rustc_target/src/callconv/arm.rs index bd6f781fb81..bd6f781fb81 100644 --- a/compiler/rustc_target/src/abi/call/arm.rs +++ b/compiler/rustc_target/src/callconv/arm.rs diff --git a/compiler/rustc_target/src/abi/call/avr.rs b/compiler/rustc_target/src/callconv/avr.rs index dfc991e0954..dfc991e0954 100644 --- a/compiler/rustc_target/src/abi/call/avr.rs +++ b/compiler/rustc_target/src/callconv/avr.rs diff --git a/compiler/rustc_target/src/abi/call/bpf.rs b/compiler/rustc_target/src/callconv/bpf.rs index f19772ac709..f19772ac709 100644 --- a/compiler/rustc_target/src/abi/call/bpf.rs +++ b/compiler/rustc_target/src/callconv/bpf.rs diff --git a/compiler/rustc_target/src/abi/call/csky.rs b/compiler/rustc_target/src/callconv/csky.rs index b1c1ae814a7..b1c1ae814a7 100644 --- a/compiler/rustc_target/src/abi/call/csky.rs +++ b/compiler/rustc_target/src/callconv/csky.rs diff --git a/compiler/rustc_target/src/abi/call/hexagon.rs b/compiler/rustc_target/src/callconv/hexagon.rs index 0a0688880c0..0a0688880c0 100644 --- a/compiler/rustc_target/src/abi/call/hexagon.rs +++ b/compiler/rustc_target/src/callconv/hexagon.rs diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs index 4a21935623b..4a21935623b 100644 --- a/compiler/rustc_target/src/abi/call/loongarch.rs +++ b/compiler/rustc_target/src/callconv/loongarch.rs diff --git a/compiler/rustc_target/src/abi/call/m68k.rs b/compiler/rustc_target/src/callconv/m68k.rs index 82fe81f8c52..82fe81f8c52 100644 --- a/compiler/rustc_target/src/abi/call/m68k.rs +++ b/compiler/rustc_target/src/callconv/m68k.rs diff --git a/compiler/rustc_target/src/abi/call/mips.rs b/compiler/rustc_target/src/callconv/mips.rs index 37980a91c76..37980a91c76 100644 --- a/compiler/rustc_target/src/abi/call/mips.rs +++ b/compiler/rustc_target/src/callconv/mips.rs diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs index 2c3258c8d42..2c3258c8d42 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/callconv/mips64.rs diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 352861c5ccb..832246495bc 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -1,10 +1,11 @@ use std::fmt; use std::str::FromStr; +pub use rustc_abi::{Reg, RegKind}; use rustc_macros::HashStable_Generic; use rustc_span::Symbol; -use crate::abi::{self, Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; +use crate::abi::{self, Abi, Align, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi}; mod aarch64; @@ -192,63 +193,6 @@ impl ArgAttributes { } } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] -pub enum RegKind { - Integer, - Float, - Vector, -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] -pub struct Reg { - pub kind: RegKind, - pub size: Size, -} - -macro_rules! reg_ctor { - ($name:ident, $kind:ident, $bits:expr) => { - pub fn $name() -> Reg { - Reg { kind: RegKind::$kind, size: Size::from_bits($bits) } - } - }; -} - -impl Reg { - reg_ctor!(i8, Integer, 8); - reg_ctor!(i16, Integer, 16); - reg_ctor!(i32, Integer, 32); - reg_ctor!(i64, Integer, 64); - reg_ctor!(i128, Integer, 128); - - reg_ctor!(f32, Float, 32); - reg_ctor!(f64, Float, 64); -} - -impl Reg { - pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align { - let dl = cx.data_layout(); - match self.kind { - RegKind::Integer => match self.size.bits() { - 1 => dl.i1_align.abi, - 2..=8 => dl.i8_align.abi, - 9..=16 => dl.i16_align.abi, - 17..=32 => dl.i32_align.abi, - 33..=64 => dl.i64_align.abi, - 65..=128 => dl.i128_align.abi, - _ => panic!("unsupported integer: {self:?}"), - }, - RegKind::Float => match self.size.bits() { - 16 => dl.f16_align.abi, - 32 => dl.f32_align.abi, - 64 => dl.f64_align.abi, - 128 => dl.f128_align.abi, - _ => panic!("unsupported float: {self:?}"), - }, - RegKind::Vector => dl.vector_align(self.size).abi, - } - } -} - /// An argument passed entirely registers with the /// same kind (e.g., HFA / HVA on PPC64 and AArch64). #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] @@ -380,195 +324,6 @@ impl CastTarget { } } -/// Return value from the `homogeneous_aggregate` test function. -#[derive(Copy, Clone, Debug)] -pub enum HomogeneousAggregate { - /// Yes, all the "leaf fields" of this struct are passed in the - /// same way (specified in the `Reg` value). - Homogeneous(Reg), - - /// There are no leaf fields at all. - NoData, -} - -/// Error from the `homogeneous_aggregate` test function, indicating -/// there are distinct leaf fields passed in different ways, -/// or this is uninhabited. -#[derive(Copy, Clone, Debug)] -pub struct Heterogeneous; - -impl HomogeneousAggregate { - /// If this is a homogeneous aggregate, returns the homogeneous - /// unit, else `None`. - pub fn unit(self) -> Option<Reg> { - match self { - HomogeneousAggregate::Homogeneous(reg) => Some(reg), - HomogeneousAggregate::NoData => None, - } - } - - /// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in - /// the same `struct`. Only succeeds if only one of them has any data, - /// or both units are identical. - fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> { - match (self, other) { - (x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x), - - (HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => { - if a != b { - return Err(Heterogeneous); - } - Ok(self) - } - } - } -} - -impl<'a, Ty> TyAndLayout<'a, Ty> { - /// Returns `true` if this is an aggregate type (including a ScalarPair!) - fn is_aggregate(&self) -> bool { - match self.abi { - Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false, - Abi::ScalarPair(..) | Abi::Aggregate { .. } => true, - } - } - - /// Returns `Homogeneous` if this layout is an aggregate containing fields of - /// only a single type (e.g., `(u32, u32)`). Such aggregates are often - /// special-cased in ABIs. - /// - /// Note: We generally ignore 1-ZST fields when computing this value (see #56877). - /// - /// This is public so that it can be used in unit tests, but - /// should generally only be relevant to the ABI details of - /// specific targets. - pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous> - where - Ty: TyAbiInterface<'a, C> + Copy, - { - match self.abi { - Abi::Uninhabited => Err(Heterogeneous), - - // The primitive for this algorithm. - Abi::Scalar(scalar) => { - let kind = match scalar.primitive() { - abi::Int(..) | abi::Pointer(_) => RegKind::Integer, - abi::Float(_) => RegKind::Float, - }; - Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size })) - } - - Abi::Vector { .. } => { - assert!(!self.is_zst()); - Ok(HomogeneousAggregate::Homogeneous(Reg { - kind: RegKind::Vector, - size: self.size, - })) - } - - Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => { - // Helper for computing `homogeneous_aggregate`, allowing a custom - // starting offset (used below for handling variants). - let from_fields_at = - |layout: Self, - start: Size| - -> Result<(HomogeneousAggregate, Size), Heterogeneous> { - let is_union = match layout.fields { - FieldsShape::Primitive => { - unreachable!("aggregates can't have `FieldsShape::Primitive`") - } - FieldsShape::Array { count, .. } => { - assert_eq!(start, Size::ZERO); - - let result = if count > 0 { - layout.field(cx, 0).homogeneous_aggregate(cx)? - } else { - HomogeneousAggregate::NoData - }; - return Ok((result, layout.size)); - } - FieldsShape::Union(_) => true, - FieldsShape::Arbitrary { .. } => false, - }; - - let mut result = HomogeneousAggregate::NoData; - let mut total = start; - - for i in 0..layout.fields.count() { - let field = layout.field(cx, i); - if field.is_1zst() { - // No data here and no impact on layout, can be ignored. - // (We might be able to also ignore all aligned ZST but that's less clear.) - continue; - } - - if !is_union && total != layout.fields.offset(i) { - // This field isn't just after the previous one we considered, abort. - return Err(Heterogeneous); - } - - result = result.merge(field.homogeneous_aggregate(cx)?)?; - - // Keep track of the offset (without padding). - let size = field.size; - if is_union { - total = total.max(size); - } else { - total += size; - } - } - - Ok((result, total)) - }; - - let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?; - - match &self.variants { - abi::Variants::Single { .. } => {} - abi::Variants::Multiple { variants, .. } => { - // Treat enum variants like union members. - // HACK(eddyb) pretend the `enum` field (discriminant) - // is at the start of every variant (otherwise the gap - // at the start of all variants would disqualify them). - // - // NB: for all tagged `enum`s (which include all non-C-like - // `enum`s with defined FFI representation), this will - // match the homogeneous computation on the equivalent - // `struct { tag; union { variant1; ... } }` and/or - // `union { struct { tag; variant1; } ... }` - // (the offsets of variant fields should be identical - // between the two for either to be a homogeneous aggregate). - let variant_start = total; - for variant_idx in variants.indices() { - let (variant_result, variant_total) = - from_fields_at(self.for_variant(cx, variant_idx), variant_start)?; - - result = result.merge(variant_result)?; - total = total.max(variant_total); - } - } - } - - // There needs to be no padding. - if total != self.size { - Err(Heterogeneous) - } else { - match result { - HomogeneousAggregate::Homogeneous(_) => { - assert_ne!(total, Size::ZERO); - } - HomogeneousAggregate::NoData => { - assert_eq!(total, Size::ZERO); - } - } - Ok(result) - } - } - Abi::Aggregate { sized: false } => Err(Heterogeneous), - } - } -} - /// Information about how to pass an argument to, /// or return a value from, a function, under some ABI. #[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)] diff --git a/compiler/rustc_target/src/abi/call/msp430.rs b/compiler/rustc_target/src/callconv/msp430.rs index 4f613aa6c15..4f613aa6c15 100644 --- a/compiler/rustc_target/src/abi/call/msp430.rs +++ b/compiler/rustc_target/src/callconv/msp430.rs diff --git a/compiler/rustc_target/src/abi/call/nvptx64.rs b/compiler/rustc_target/src/callconv/nvptx64.rs index 2e8b16d3a93..2e8b16d3a93 100644 --- a/compiler/rustc_target/src/abi/call/nvptx64.rs +++ b/compiler/rustc_target/src/callconv/nvptx64.rs diff --git a/compiler/rustc_target/src/abi/call/powerpc.rs b/compiler/rustc_target/src/callconv/powerpc.rs index f3b05c48173..f3b05c48173 100644 --- a/compiler/rustc_target/src/abi/call/powerpc.rs +++ b/compiler/rustc_target/src/callconv/powerpc.rs diff --git a/compiler/rustc_target/src/abi/call/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs index 71e533b8cc5..71e533b8cc5 100644 --- a/compiler/rustc_target/src/abi/call/powerpc64.rs +++ b/compiler/rustc_target/src/callconv/powerpc64.rs diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs index be6bc701b49..be6bc701b49 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/callconv/riscv.rs diff --git a/compiler/rustc_target/src/abi/call/s390x.rs b/compiler/rustc_target/src/callconv/s390x.rs index 502e7331267..502e7331267 100644 --- a/compiler/rustc_target/src/abi/call/s390x.rs +++ b/compiler/rustc_target/src/callconv/s390x.rs diff --git a/compiler/rustc_target/src/abi/call/sparc.rs b/compiler/rustc_target/src/callconv/sparc.rs index 37980a91c76..37980a91c76 100644 --- a/compiler/rustc_target/src/abi/call/sparc.rs +++ b/compiler/rustc_target/src/callconv/sparc.rs diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs index 835353f76fc..835353f76fc 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/callconv/sparc64.rs diff --git a/compiler/rustc_target/src/abi/call/wasm.rs b/compiler/rustc_target/src/callconv/wasm.rs index 3c4cd76a754..3c4cd76a754 100644 --- a/compiler/rustc_target/src/abi/call/wasm.rs +++ b/compiler/rustc_target/src/callconv/wasm.rs diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index d9af83d3205..d9af83d3205 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs index 9910e623ac9..9910e623ac9 100644 --- a/compiler/rustc_target/src/abi/call/x86_64.rs +++ b/compiler/rustc_target/src/callconv/x86_64.rs diff --git a/compiler/rustc_target/src/abi/call/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs index e5a20b248e4..e5a20b248e4 100644 --- a/compiler/rustc_target/src/abi/call/x86_win64.rs +++ b/compiler/rustc_target/src/callconv/x86_win64.rs diff --git a/compiler/rustc_target/src/abi/call/xtensa.rs b/compiler/rustc_target/src/callconv/xtensa.rs index e1728b08a39..e1728b08a39 100644 --- a/compiler/rustc_target/src/abi/call/xtensa.rs +++ b/compiler/rustc_target/src/callconv/xtensa.rs diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs index 2c367defe7b..b09d8d724ef 100644 --- a/compiler/rustc_target/src/json.rs +++ b/compiler/rustc_target/src/json.rs @@ -134,3 +134,9 @@ impl ToJson for TargetMetadata { }) } } + +impl ToJson for rustc_abi::Endian { + fn to_json(&self) -> Json { + self.as_str().to_json() + } +} diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index 2121c4110dd..50679ab8cc8 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -21,8 +21,8 @@ use std::path::{Path, PathBuf}; -pub mod abi; pub mod asm; +pub mod callconv; pub mod json; pub mod spec; pub mod target_features; @@ -30,6 +30,15 @@ pub mod target_features; #[cfg(test)] mod tests; +pub mod abi { + pub(crate) use Float::*; + pub(crate) use Primitive::*; + // Explicitly import `Float` to avoid ambiguity with `Primitive::Float`. + pub use rustc_abi::{Float, *}; + + pub use crate::callconv as call; +} + pub use rustc_abi::HashStableContext; /// The name of rustc's own place to organize libraries. |
