about summary refs log tree commit diff
path: root/compiler/rustc_target/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_target/src')
-rw-r--r--compiler/rustc_target/src/abi/mod.rs278
-rw-r--r--compiler/rustc_target/src/asm/mod.rs10
-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)251
-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)16
-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.rs6
-rw-r--r--compiler/rustc_target/src/lib.rs11
-rw-r--r--compiler/rustc_target/src/spec/base/avr_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs5
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs34
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs34
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs34
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs38
-rw-r--r--compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs1
-rw-r--r--compiler/rustc_target/src/target_features.rs4
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"]),