diff options
Diffstat (limited to 'compiler/rustc_target/src')
43 files changed, 213 insertions, 535 deletions
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs deleted file mode 100644 index 3eaff652618..00000000000 --- a/compiler/rustc_target/src/abi/mod.rs +++ /dev/null @@ -1,278 +0,0 @@ -use std::fmt; -use std::ops::Deref; - -pub use Float::*; -pub use Integer::*; -pub 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() - } -} - -rustc_index::newtype_index! { - /// The *source-order* index of a field in a variant. - /// - /// This is how most code after type checking refers to fields, rather than - /// using names (as names have hygiene complications and more complex lookup). - /// - /// Particularly for `repr(Rust)` types, this may not be the same as *layout* order. - /// (It is for `repr(C)` `struct`s, however.) - /// - /// For example, in the following types, - /// ```rust - /// # enum Never {} - /// # #[repr(u16)] - /// enum Demo1 { - /// Variant0 { a: Never, b: i32 } = 100, - /// Variant1 { c: u8, d: u64 } = 10, - /// } - /// struct Demo2 { e: u8, f: u16, g: u8 } - /// ``` - /// `b` is `FieldIdx(1)` in `VariantIdx(0)`, - /// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and - /// `f` is `FieldIdx(1)` in `VariantIdx(0)`. - #[derive(HashStable_Generic)] - #[encodable] - #[orderable] - pub struct FieldIdx {} -} - -rustc_index::newtype_index! { - /// The *source-order* index of a variant in a type. - /// - /// For enums, these are always `0..variant_count`, regardless of any - /// custom discriminants that may have been defined, and including any - /// variants that may end up uninhabited due to field types. (Some of the - /// variants may not be present in a monomorphized ABI [`Variants`], but - /// those skipped variants are always counted when determining the *index*.) - /// - /// `struct`s, `tuples`, and `unions`s are considered to have a single variant - /// with variant index zero, aka [`FIRST_VARIANT`]. - #[derive(HashStable_Generic)] - #[encodable] - #[orderable] - pub struct VariantIdx { - /// Equivalent to `VariantIdx(0)`. - const FIRST_VARIANT = 0; - } -} -#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)] -#[rustc_pass_by_value] -pub struct Layout<'a>(pub Interned<'a, LayoutS<FieldIdx, VariantIdx>>); - -impl<'a> fmt::Debug for Layout<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // See comment on `<LayoutS as Debug>::fmt` above. - self.0.0.fmt(f) - } -} - -impl<'a> Deref for Layout<'a> { - type Target = &'a LayoutS<FieldIdx, VariantIdx>; - fn deref(&self) -> &&'a LayoutS<FieldIdx, VariantIdx> { - &self.0.0 - } -} - -impl<'a> Layout<'a> { - pub fn fields(self) -> &'a FieldsShape<FieldIdx> { - &self.0.0.fields - } - - pub fn variants(self) -> &'a Variants<FieldIdx, VariantIdx> { - &self.0.0.variants - } - - pub fn abi(self) -> Abi { - self.0.0.abi - } - - pub fn largest_niche(self) -> Option<Niche> { - self.0.0.largest_niche - } - - pub fn align(self) -> AbiAndPrefAlign { - self.0.0.align - } - - pub fn size(self) -> Size { - self.0.0.size - } - - pub fn max_repr_align(self) -> Option<Align> { - self.0.0.max_repr_align - } - - pub fn unadjusted_abi_align(self) -> Align { - self.0.0.unadjusted_abi_align - } - - /// Whether the layout is from a type that implements [`std::marker::PointerLike`]. - /// - /// Currently, that means that the type is pointer-sized, pointer-aligned, - /// and has a initialized (non-union), scalar ABI. - pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool { - self.size() == data_layout.pointer_size - && self.align().abi == data_layout.pointer_align.abi - && matches!(self.abi(), Abi::Scalar(Scalar::Initialized { .. })) - } -} - -/// The layout of a type, alongside the type itself. -/// Provides various type traversal APIs (e.g., recursing into fields). -/// -/// Note that the layout is NOT guaranteed to always be identical -/// to that obtained from `layout_of(ty)`, as we need to produce -/// layouts for which Rust types do not exist, such as enum variants -/// or synthetic fields of enums (i.e., discriminants) and fat pointers. -#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)] -pub struct TyAndLayout<'a, Ty> { - pub ty: Ty, - pub layout: Layout<'a>, -} - -impl<'a, Ty: fmt::Display> fmt::Debug for TyAndLayout<'a, Ty> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Print the type in a readable way, not its debug representation. - f.debug_struct("TyAndLayout") - .field("ty", &format_args!("{}", self.ty)) - .field("layout", &self.layout) - .finish() - } -} - -impl<'a, Ty> Deref for TyAndLayout<'a, Ty> { - type Target = &'a LayoutS<FieldIdx, VariantIdx>; - fn deref(&self) -> &&'a LayoutS<FieldIdx, VariantIdx> { - &self.layout.0.0 - } -} - -/// Trait that needs to be implemented by the higher-level type representation -/// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality. -pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug { - fn ty_and_layout_for_variant( - this: TyAndLayout<'a, Self>, - cx: &C, - variant_index: VariantIdx, - ) -> TyAndLayout<'a, Self>; - fn ty_and_layout_field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> TyAndLayout<'a, Self>; - fn ty_and_layout_pointee_info_at( - this: TyAndLayout<'a, Self>, - cx: &C, - offset: Size, - ) -> Option<PointeeInfo>; - fn is_adt(this: TyAndLayout<'a, Self>) -> bool; - fn is_never(this: TyAndLayout<'a, Self>) -> bool; - fn is_tuple(this: TyAndLayout<'a, Self>) -> bool; - fn is_unit(this: TyAndLayout<'a, Self>) -> bool; - fn is_transparent(this: TyAndLayout<'a, Self>) -> bool; -} - -impl<'a, Ty> TyAndLayout<'a, Ty> { - pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self - where - Ty: TyAbiInterface<'a, C>, - { - Ty::ty_and_layout_for_variant(self, cx, variant_index) - } - - pub fn field<C>(self, cx: &C, i: usize) -> Self - where - Ty: TyAbiInterface<'a, C>, - { - Ty::ty_and_layout_field(self, cx, i) - } - - pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo> - where - Ty: TyAbiInterface<'a, C>, - { - Ty::ty_and_layout_pointee_info_at(self, cx, offset) - } - - pub fn is_single_fp_element<C>(self, cx: &C) -> bool - where - Ty: TyAbiInterface<'a, C>, - C: HasDataLayout, - { - match self.abi { - Abi::Scalar(scalar) => matches!(scalar.primitive(), Float(F32 | F64)), - Abi::Aggregate { .. } => { - if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 { - self.field(cx, 0).is_single_fp_element(cx) - } else { - false - } - } - _ => false, - } - } - - pub fn is_adt<C>(self) -> bool - where - Ty: TyAbiInterface<'a, C>, - { - Ty::is_adt(self) - } - - pub fn is_never<C>(self) -> bool - where - Ty: TyAbiInterface<'a, C>, - { - Ty::is_never(self) - } - - pub fn is_tuple<C>(self) -> bool - where - Ty: TyAbiInterface<'a, C>, - { - Ty::is_tuple(self) - } - - pub fn is_unit<C>(self) -> bool - where - Ty: TyAbiInterface<'a, C>, - { - Ty::is_unit(self) - } - - pub fn is_transparent<C>(self) -> bool - where - Ty: TyAbiInterface<'a, C>, - { - Ty::is_transparent(self) - } - - /// Finds the one field that is not a 1-ZST. - /// Returns `None` if there are multiple non-1-ZST fields or only 1-ZST-fields. - pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(usize, Self)> - where - Ty: TyAbiInterface<'a, C> + Copy, - { - let mut found = None; - for field_idx in 0..self.fields.count() { - let field = self.field(cx, field_idx); - if field.is_1zst() { - continue; - } - if found.is_some() { - // More than one non-1-ZST field. - return None; - } - found = Some((field_idx, field)); - } - found - } -} diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index df13d24cb9e..73ae1ae96ae 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -893,6 +893,7 @@ pub enum InlineAsmClobberAbi { RiscV, LoongArch, S390x, + Msp430, } impl InlineAsmClobberAbi { @@ -946,6 +947,10 @@ impl InlineAsmClobberAbi { "C" | "system" => Ok(InlineAsmClobberAbi::S390x), _ => Err(&["C", "system"]), }, + InlineAsmArch::Msp430 => match name { + "C" | "system" => Ok(InlineAsmClobberAbi::Msp430), + _ => Err(&["C", "system"]), + }, _ => Err(&[]), } } @@ -1125,6 +1130,11 @@ impl InlineAsmClobberAbi { a8, a9, a10, a11, a12, a13, a14, a15, } }, + InlineAsmClobberAbi::Msp430 => clobbered_regs! { + Msp430 Msp430InlineAsmReg { + r11, r12, r13, r14, r15, + } + }, } } } 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 f4469467249..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)] @@ -637,7 +392,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } } - /// Pass this argument indirectly, by passing a (thin or fat) pointer to the argument instead. + /// Pass this argument indirectly, by passing a (thin or wide) pointer to the argument instead. /// This is valid for both sized and unsized arguments. pub fn make_indirect(&mut self) { match self.mode { 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 b9767bf906b..71e533b8cc5 100644 --- a/compiler/rustc_target/src/abi/call/powerpc64.rs +++ b/compiler/rustc_target/src/callconv/powerpc64.rs @@ -10,6 +10,7 @@ use crate::spec::HasTargetSpec; enum ABI { ELFv1, // original ABI used for powerpc64 (big-endian) ELFv2, // newer ABI used for powerpc64le and musl (both endians) + AIX, // used by AIX OS, big-endian only } use ABI::*; @@ -23,9 +24,9 @@ where C: HasDataLayout, { arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| { - // ELFv1 only passes one-member aggregates transparently. + // ELFv1 and AIX only passes one-member aggregates transparently. // ELFv2 passes up to eight uniquely addressable members. - if (abi == ELFv1 && arg.layout.size > unit.size) + if ((abi == ELFv1 || abi == AIX) && arg.layout.size > unit.size) || arg.layout.size > unit.size.checked_mul(8, cx).unwrap() { return None; @@ -55,8 +56,15 @@ where return; } + // The AIX ABI expect byval for aggregates + // See https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/Targets/PPC.cpp. + if !is_ret && abi == AIX { + arg.pass_by_stack_offset(None); + return; + } + // The ELFv1 ABI doesn't return aggregates in registers - if is_ret && abi == ELFv1 { + if is_ret && (abi == ELFv1 || abi == AIX) { arg.make_indirect(); return; } @@ -93,6 +101,8 @@ where { let abi = if cx.target_spec().env == "musl" { ELFv2 + } else if cx.target_spec().os == "aix" { + AIX } else { match cx.data_layout().endian { Endian::Big => ELFv1, 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. diff --git a/compiler/rustc_target/src/spec/base/avr_gnu.rs b/compiler/rustc_target/src/spec/base/avr_gnu.rs index fb97738618b..4f348af21ad 100644 --- a/compiler/rustc_target/src/spec/base/avr_gnu.rs +++ b/compiler/rustc_target/src/spec/base/avr_gnu.rs @@ -19,6 +19,8 @@ pub(crate) fn target(target_cpu: &'static str, mmcu: &'static str) -> Target { llvm_target: "avr-unknown-unknown".into(), pointer_width: 16, options: TargetOptions { + env: "gnu".into(), + c_int_width: "16".into(), cpu: target_cpu.into(), exe_suffix: ".elf".into(), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c557091242e..82e11a3afce 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1830,6 +1830,7 @@ supported_targets! { ("armv7-unknown-trusty", armv7_unknown_trusty), ("aarch64-unknown-trusty", aarch64_unknown_trusty), + ("x86_64-unknown-trusty", x86_64_unknown_trusty), ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf), ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf), @@ -1840,6 +1841,10 @@ supported_targets! { ("riscv32imac-esp-espidf", riscv32imac_esp_espidf), ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf), + ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf), + ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf), + ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf), + ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf), ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf), ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf), diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs index de8d99977b4..e869314d4d8 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions, base}; +use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base}; pub(crate) fn target() -> Target { Target { @@ -18,6 +18,11 @@ pub(crate) fn target() -> Target { features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD, direct_access_external_data: Some(false), ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs index a5088bcd5c2..70e8bf633a9 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions, base}; +use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base}; pub(crate) fn target() -> Target { Target { @@ -19,6 +19,11 @@ pub(crate) fn target() -> Target { llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), crt_static_default: false, + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs index 32a856be669..90bcd9a45cf 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions, base}; +use crate::spec::{SanitizerSet, Target, TargetOptions, base}; pub(crate) fn target() -> Target { Target { @@ -17,6 +17,11 @@ pub(crate) fn target() -> Target { features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD, ..base::linux_ohos::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs new file mode 100644 index 00000000000..b1f52973c10 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs @@ -0,0 +1,34 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub(crate) fn target() -> Target { + Target { + // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also + // `options.llvm_abiname`. + data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), + llvm_target: "riscv32".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Bare RISC-V (RV32E ISA)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + arch: "riscv32".into(), + + options: TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + cpu: "generic-rv32".into(), + // The ilp32e ABI specifies the `data_layout` + llvm_abiname: "ilp32e".into(), + max_atomic_width: Some(32), + atomic_cas: false, + features: "+e,+forced-atomics".into(), + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs new file mode 100644 index 00000000000..feeaa48778d --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs @@ -0,0 +1,34 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub(crate) fn target() -> Target { + Target { + // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also + // `options.llvm_abiname`. + data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), + llvm_target: "riscv32".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Bare RISC-V (RV32EM ISA)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + arch: "riscv32".into(), + + options: TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + cpu: "generic-rv32".into(), + // The ilp32e ABI specifies the `data_layout` + llvm_abiname: "ilp32e".into(), + max_atomic_width: Some(32), + atomic_cas: false, + features: "+e,+m,+forced-atomics".into(), + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs new file mode 100644 index 00000000000..45d73c13233 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs @@ -0,0 +1,34 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub(crate) fn target() -> Target { + Target { + // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also + // `options.llvm_abiname`. + data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), + llvm_target: "riscv32".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Bare RISC-V (RV32EMC ISA)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + arch: "riscv32".into(), + + options: TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + cpu: "generic-rv32".into(), + // The ilp32e ABI specifies the `data_layout` + llvm_abiname: "ilp32e".into(), + max_atomic_width: Some(32), + atomic_cas: false, + features: "+e,+m,+c,+forced-atomics".into(), + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs index 0cd4faefd6b..0157d03f854 100644 --- a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs @@ -7,7 +7,6 @@ pub(crate) fn target() -> Target { linker: Some("sparc-elf-gcc".into()), endian: Endian::Big, cpu: "v7".into(), - abi: "elf".into(), max_atomic_width: Some(32), atomic_cas: true, panic_strategy: PanicStrategy::Abort, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs new file mode 100644 index 00000000000..a6af06b03db --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs @@ -0,0 +1,38 @@ +// Trusty OS target for X86_64. + +use crate::spec::{ + LinkSelfContainedDefault, PanicStrategy, RelroLevel, StackProbeType, Target, TargetOptions, +}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "x86_64-unknown-unknown-musl".into(), + metadata: crate::spec::TargetMetadata { + description: Some("x86_64 Trusty".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), + arch: "x86_64".into(), + options: TargetOptions { + executables: true, + max_atomic_width: Some(64), + panic_strategy: PanicStrategy::Abort, + os: "trusty".into(), + link_self_contained: LinkSelfContainedDefault::InferredForMusl, + position_independent_executables: true, + static_position_independent_executables: true, + crt_static_default: true, + crt_static_respected: true, + dynamic_linking: false, + plt_by_default: false, + relro_level: RelroLevel::Full, + stack_probes: StackProbeType::Inline, + mcount: "\u{1}_mcount".into(), + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs index 51960dbec4a..254ae54db21 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs @@ -15,6 +15,7 @@ pub(crate) fn target() -> Target { }, options: TargetOptions { + vendor: "espressif".into(), cpu: "esp32".into(), linker: Some("xtensa-esp32-elf-gcc".into()), max_atomic_width: Some(32), diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs index 21330615a87..34d8383a604 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs @@ -15,6 +15,7 @@ pub(crate) fn target() -> Target { }, options: TargetOptions { + vendor: "espressif".into(), cpu: "esp32-s2".into(), linker: Some("xtensa-esp32s2-elf-gcc".into()), max_atomic_width: Some(32), diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs index fca47b4bdb1..023a67f2871 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs @@ -15,6 +15,7 @@ pub(crate) fn target() -> Target { }, options: TargetOptions { + vendor: "espressif".into(), cpu: "esp32-s3".into(), linker: Some("xtensa-esp32s3-elf-gcc".into()), max_atomic_width: Some(32), diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 0a98b363b1a..e92366d5c5c 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -191,6 +191,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sm4", Stable, &["neon"]), // FEAT_SME ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + // FEAT_SME_B16B16 + ("sme-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]), // FEAT_SME_F16F16 ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), // FEAT_SME_F64F64 @@ -227,7 +229,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // // "For backwards compatibility, Neon and VFP are required in the latest architectures." ("sve", Stable, &["neon"]), - // FEAT_SVE_B16B16 (SVE or SME Instructions) + // FEAT_SVE_B16B16 (SVE or SME Z-targeting instructions) ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), // FEAT_SVE2 ("sve2", Stable, &["sve"]), |
