Importing rustc-1.56.0

Change-Id: I98941481270706fa55f8fb2cb91686ae3bd30f38
diff --git a/compiler/rustc_target/src/abi/call/aarch64.rs b/compiler/rustc_target/src/abi/call/aarch64.rs
index a5e985d..4613a45 100644
--- a/compiler/rustc_target/src/abi/call/aarch64.rs
+++ b/compiler/rustc_target/src/abi/call/aarch64.rs
@@ -1,10 +1,10 @@
 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
         let size = arg.layout.size;
@@ -26,8 +26,8 @@
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
@@ -48,8 +48,8 @@
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(32);
@@ -70,8 +70,8 @@
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(cx, &mut fn_abi.ret);
diff --git a/compiler/rustc_target/src/abi/call/amdgpu.rs b/compiler/rustc_target/src/abi/call/amdgpu.rs
index 0b4f279..9be9747 100644
--- a/compiler/rustc_target/src/abi/call/amdgpu.rs
+++ b/compiler/rustc_target/src/abi/call/amdgpu.rs
@@ -1,26 +1,26 @@
 use crate::abi::call::{ArgAbi, FnAbi};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn classify_ret<'a, Ty, C>(_cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     ret.extend_integer_width_to(32);
 }
 
 fn classify_arg<'a, Ty, C>(_cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.extend_integer_width_to(32);
 }
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(cx, &mut fn_abi.ret);
diff --git a/compiler/rustc_target/src/abi/call/arm.rs b/compiler/rustc_target/src/abi/call/arm.rs
index b560e11..e66c213 100644
--- a/compiler/rustc_target/src/abi/call/arm.rs
+++ b/compiler/rustc_target/src/abi/call/arm.rs
@@ -1,11 +1,11 @@
 use crate::abi::call::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 use crate::spec::HasTargetSpec;
 
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
         let size = arg.layout.size;
@@ -27,8 +27,8 @@
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, vfp: bool)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
@@ -53,8 +53,8 @@
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, vfp: bool)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(32);
@@ -75,8 +75,8 @@
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout + HasTargetSpec,
 {
     // If this is a target with a hard-float ABI, and the function is not explicitly
     // `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
diff --git a/compiler/rustc_target/src/abi/call/mips.rs b/compiler/rustc_target/src/abi/call/mips.rs
index 733a732..cc44319 100644
--- a/compiler/rustc_target/src/abi/call/mips.rs
+++ b/compiler/rustc_target/src/abi/call/mips.rs
@@ -1,10 +1,9 @@
 use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, Size, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, Size};
 
-fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
+fn classify_ret<Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
@@ -14,10 +13,9 @@
     }
 }
 
-fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
+fn classify_arg<Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     let dl = cx.data_layout();
     let size = arg.layout.size;
@@ -35,10 +33,9 @@
     *offset = offset.align_to(align) + size.align_to(align);
 }
 
-pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
+pub fn compute_abi_info<Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     let mut offset = Size::ZERO;
     if !fn_abi.ret.is_ignore() {
diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs
index a630c84..28ca93c 100644
--- a/compiler/rustc_target/src/abi/call/mips64.rs
+++ b/compiler/rustc_target/src/abi/call/mips64.rs
@@ -1,5 +1,5 @@
 use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
-use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{self, HasDataLayout, Size, TyAbiInterface};
 
 fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
     // Always sign extend u32 values on 64-bit mips
@@ -19,8 +19,8 @@
 
 fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     match ret.layout.field(cx, i).abi {
         abi::Abi::Scalar(ref scalar) => match scalar.value {
@@ -34,8 +34,8 @@
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         extend_integer_width_mips(ret, 64);
@@ -74,8 +74,8 @@
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
         extend_integer_width_mips(arg, 64);
@@ -144,8 +144,8 @@
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(cx, &mut fn_abi.ret);
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 6e0e140..6d3c731 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -1,5 +1,5 @@
 use crate::abi::{self, Abi, Align, FieldsShape, Size};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout};
 use crate::spec::{self, HasTargetSpec};
 
 mod aarch64;
@@ -316,8 +316,7 @@
     /// specific targets.
     pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
     where
-        Ty: TyAndLayoutMethods<'a, C> + Copy,
-        C: LayoutOf<Ty = Ty, TyAndLayout = Self>,
+        Ty: TyAbiInterface<'a, C> + Copy,
     {
         match self.abi {
             Abi::Uninhabited => Err(Heterogeneous),
@@ -603,8 +602,8 @@
 impl<'a, Ty> FnAbi<'a, Ty> {
     pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String>
     where
-        Ty: TyAndLayoutMethods<'a, C> + Copy,
-        C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+        Ty: TyAbiInterface<'a, C> + Copy,
+        C: HasDataLayout + HasTargetSpec,
     {
         if abi == spec::abi::Abi::X86Interrupt {
             if let Some(arg) = self.args.first_mut() {
diff --git a/compiler/rustc_target/src/abi/call/powerpc64.rs b/compiler/rustc_target/src/abi/call/powerpc64.rs
index 8c2a9d0..c22ef9c 100644
--- a/compiler/rustc_target/src/abi/call/powerpc64.rs
+++ b/compiler/rustc_target/src/abi/call/powerpc64.rs
@@ -3,7 +3,7 @@
 // need to be fixed when PowerPC vector support is added.
 
 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{Endian, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{Endian, HasDataLayout, TyAbiInterface};
 use crate::spec::HasTargetSpec;
 
 #[derive(Debug, Clone, Copy, PartialEq)]
@@ -19,8 +19,8 @@
     abi: ABI,
 ) -> Option<Uniform>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
         // ELFv1 only passes one-member aggregates transparently.
@@ -43,8 +43,8 @@
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, abi: ABI)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(64);
@@ -86,8 +86,8 @@
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(64);
@@ -116,8 +116,8 @@
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout + HasTargetSpec,
 {
     let abi = if cx.target_spec().env == "musl" {
         ELFv2
diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs
index 1ab881d..8c2ef8c 100644
--- a/compiler/rustc_target/src/abi/call/riscv.rs
+++ b/compiler/rustc_target/src/abi/call/riscv.rs
@@ -5,9 +5,7 @@
 // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773
 
 use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
-use crate::abi::{
-    self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
-};
+use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
 use crate::spec::HasTargetSpec;
 
 #[derive(Copy, Clone)]
@@ -43,8 +41,7 @@
     field2_kind: &mut RegPassKind,
 ) -> Result<(), CannotUseFpConv>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
+    Ty: TyAbiInterface<'a, C> + Copy,
 {
     match arg_layout.abi {
         Abi::Scalar(ref scalar) => match scalar.value {
@@ -130,8 +127,7 @@
     flen: u64,
 ) -> Option<FloatConv>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
+    Ty: TyAbiInterface<'a, C> + Copy,
 {
     let mut field1_kind = RegPassKind::Unknown;
     let mut field2_kind = RegPassKind::Unknown;
@@ -149,8 +145,7 @@
 
 fn classify_ret<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, xlen: u64, flen: u64) -> bool
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
+    Ty: TyAbiInterface<'a, C> + Copy,
 {
     if let Some(conv) = should_use_fp_conv(cx, &arg.layout, xlen, flen) {
         match conv {
@@ -212,8 +207,7 @@
     avail_gprs: &mut u64,
     avail_fprs: &mut u64,
 ) where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
+    Ty: TyAbiInterface<'a, C> + Copy,
 {
     if !is_vararg {
         match should_use_fp_conv(cx, &arg.layout, xlen, flen) {
@@ -320,8 +314,8 @@
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout + HasTargetSpec,
 {
     let flen = match &cx.target_spec().llvm_abiname[..] {
         "ilp32f" | "lp64f" => 32,
diff --git a/compiler/rustc_target/src/abi/call/s390x.rs b/compiler/rustc_target/src/abi/call/s390x.rs
index 005dcc6..5941089 100644
--- a/compiler/rustc_target/src/abi/call/s390x.rs
+++ b/compiler/rustc_target/src/abi/call/s390x.rs
@@ -2,13 +2,9 @@
 // for a pre-z13 machine or using -mno-vx.
 
 use crate::abi::call::{ArgAbi, FnAbi, Reg};
-use crate::abi::{self, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{self, HasDataLayout, TyAbiInterface, TyAndLayout};
 
-fn classify_ret<'a, Ty, C>(ret: &mut ArgAbi<'_, Ty>)
-where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
-{
+fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
     if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
         ret.extend_integer_width_to(64);
     } else {
@@ -18,8 +14,8 @@
 
 fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C>,
+    C: HasDataLayout,
 {
     match layout.abi {
         abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
@@ -36,8 +32,8 @@
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
         arg.extend_integer_width_to(64);
@@ -63,8 +59,8 @@
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(&mut fn_abi.ret);
diff --git a/compiler/rustc_target/src/abi/call/sparc.rs b/compiler/rustc_target/src/abi/call/sparc.rs
index 733a732..cc44319 100644
--- a/compiler/rustc_target/src/abi/call/sparc.rs
+++ b/compiler/rustc_target/src/abi/call/sparc.rs
@@ -1,10 +1,9 @@
 use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, Size, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, Size};
 
-fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
+fn classify_ret<Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
@@ -14,10 +13,9 @@
     }
 }
 
-fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
+fn classify_arg<Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     let dl = cx.data_layout();
     let size = arg.layout.size;
@@ -35,10 +33,9 @@
     *offset = offset.align_to(align) + size.align_to(align);
 }
 
-pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
+pub fn compute_abi_info<Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     let mut offset = Size::ZERO;
     if !fn_abi.ret.is_ignore() {
diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs
index a647675..5d74c94 100644
--- a/compiler/rustc_target/src/abi/call/sparc64.rs
+++ b/compiler/rustc_target/src/abi/call/sparc64.rs
@@ -1,12 +1,12 @@
 // FIXME: This needs an audit for correctness and completeness.
 
 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
         // Ensure we have at most eight uniquely addressable members.
@@ -26,8 +26,8 @@
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(64);
@@ -52,8 +52,8 @@
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(64);
@@ -76,8 +76,8 @@
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(cx, &mut fn_abi.ret);
diff --git a/compiler/rustc_target/src/abi/call/wasm.rs b/compiler/rustc_target/src/abi/call/wasm.rs
index bf2c08b..3237cde 100644
--- a/compiler/rustc_target/src/abi/call/wasm.rs
+++ b/compiler/rustc_target/src/abi/call/wasm.rs
@@ -1,10 +1,10 @@
 use crate::abi::call::{ArgAbi, FnAbi, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgAbi<'a, Ty>) -> bool
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if val.layout.is_aggregate() {
         if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) {
@@ -20,8 +20,8 @@
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     ret.extend_integer_width_to(32);
     if ret.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, ret) {
@@ -31,8 +31,8 @@
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.extend_integer_width_to(32);
     if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) {
@@ -43,8 +43,8 @@
 /// The purpose of this ABI is to match the C ABI (aka clang) exactly.
 pub fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(cx, &mut fn_abi.ret);
diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs
index ff8849e..3fc197b 100644
--- a/compiler/rustc_target/src/abi/call/x86.rs
+++ b/compiler/rustc_target/src/abi/call/x86.rs
@@ -1,5 +1,5 @@
 use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
-use crate::abi::{self, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{self, HasDataLayout, TyAbiInterface, TyAndLayout};
 use crate::spec::HasTargetSpec;
 
 #[derive(PartialEq)]
@@ -10,8 +10,8 @@
 
 fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     match layout.abi {
         abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
@@ -28,8 +28,8 @@
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout + HasTargetSpec,
 {
     if !fn_abi.ret.is_ignore() {
         if fn_abi.ret.layout.is_aggregate() {
diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs
index a55658b..08f0aab 100644
--- a/compiler/rustc_target/src/abi/call/x86_64.rs
+++ b/compiler/rustc_target/src/abi/call/x86_64.rs
@@ -2,7 +2,7 @@
 // https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
 
 use crate::abi::call::{ArgAbi, CastTarget, FnAbi, Reg, RegKind};
-use crate::abi::{self, Abi, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{self, Abi, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
 
 /// Classification of "eightbyte" components.
 // N.B., the order of the variants is from general to specific,
@@ -26,8 +26,8 @@
     arg: &ArgAbi<'a, Ty>,
 ) -> Result<[Option<Class>; MAX_EIGHTBYTES], Memory>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     fn classify<'a, Ty, C>(
         cx: &C,
@@ -36,8 +36,8 @@
         off: Size,
     ) -> Result<(), Memory>
     where
-        Ty: TyAndLayoutMethods<'a, C> + Copy,
-        C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+        Ty: TyAbiInterface<'a, C> + Copy,
+        C: HasDataLayout,
     {
         if !off.is_aligned(layout.align.abi) {
             if !layout.is_zst() {
@@ -172,8 +172,8 @@
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     let mut int_regs = MAX_INT_REGS;
     let mut sse_regs = MAX_SSE_REGS;
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 9a24edf..8203999 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -5,6 +5,7 @@
 
 use std::convert::{TryFrom, TryInto};
 use std::fmt;
+use std::iter::Step;
 use std::num::NonZeroUsize;
 use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub};
 use std::str::FromStr;
@@ -36,6 +37,9 @@
     pub vector_align: Vec<(Size, AbiAndPrefAlign)>,
 
     pub instruction_address_space: AddressSpace,
+
+    /// Minimum size of #[repr(C)] enums (default I32 bits)
+    pub c_enum_min_size: Integer,
 }
 
 impl Default for TargetDataLayout {
@@ -60,6 +64,7 @@
                 (Size::from_bits(128), AbiAndPrefAlign::new(align(128))),
             ],
             instruction_address_space: AddressSpace::DATA,
+            c_enum_min_size: Integer::I32,
         }
     }
 }
@@ -173,6 +178,8 @@
             ));
         }
 
+        dl.c_enum_min_size = Integer::from_size(Size::from_bits(target.c_enum_min_bits))?;
+
         Ok(dl)
     }
 
@@ -187,6 +194,7 @@
     /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
     /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
     /// address space on 64-bit ARMv8 and x86_64.
+    #[inline]
     pub fn obj_size_bound(&self) -> u64 {
         match self.pointer_size.bits() {
             16 => 1 << 15,
@@ -196,6 +204,7 @@
         }
     }
 
+    #[inline]
     pub fn ptr_sized_integer(&self) -> Integer {
         match self.pointer_size.bits() {
             16 => I16,
@@ -205,6 +214,7 @@
         }
     }
 
+    #[inline]
     pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
         for &(size, align) in &self.vector_align {
             if size == vec_size {
@@ -434,6 +444,43 @@
     }
 }
 
+impl Step for Size {
+    #[inline]
+    fn steps_between(start: &Self, end: &Self) -> Option<usize> {
+        u64::steps_between(&start.bytes(), &end.bytes())
+    }
+
+    #[inline]
+    fn forward_checked(start: Self, count: usize) -> Option<Self> {
+        u64::forward_checked(start.bytes(), count).map(Self::from_bytes)
+    }
+
+    #[inline]
+    fn forward(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::forward(start.bytes(), count))
+    }
+
+    #[inline]
+    unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::forward_unchecked(start.bytes(), count))
+    }
+
+    #[inline]
+    fn backward_checked(start: Self, count: usize) -> Option<Self> {
+        u64::backward_checked(start.bytes(), count).map(Self::from_bytes)
+    }
+
+    #[inline]
+    fn backward(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::backward(start.bytes(), count))
+    }
+
+    #[inline]
+    unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::backward_unchecked(start.bytes(), count))
+    }
+}
+
 /// Alignment of a type in bytes (always a power of two).
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
@@ -518,14 +565,17 @@
 }
 
 impl AbiAndPrefAlign {
+    #[inline]
     pub fn new(align: Align) -> AbiAndPrefAlign {
         AbiAndPrefAlign { abi: align, pref: align }
     }
 
+    #[inline]
     pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
         AbiAndPrefAlign { abi: self.abi.min(other.abi), pref: self.pref.min(other.pref) }
     }
 
+    #[inline]
     pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
         AbiAndPrefAlign { abi: self.abi.max(other.abi), pref: self.pref.max(other.pref) }
     }
@@ -542,6 +592,7 @@
 }
 
 impl Integer {
+    #[inline]
     pub fn size(self) -> Size {
         match self {
             I8 => Size::from_bytes(1),
@@ -565,6 +616,7 @@
     }
 
     /// Finds the smallest Integer type which can represent the signed value.
+    #[inline]
     pub fn fit_signed(x: i128) -> Integer {
         match x {
             -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
@@ -576,6 +628,7 @@
     }
 
     /// Finds the smallest Integer type which can represent the unsigned value.
+    #[inline]
     pub fn fit_unsigned(x: u128) -> Integer {
         match x {
             0..=0x0000_0000_0000_00ff => I8,
@@ -610,6 +663,20 @@
         }
         I8
     }
+
+    // FIXME(eddyb) consolidate this and other methods that find the appropriate
+    // `Integer` given some requirements.
+    #[inline]
+    fn from_size(size: Size) -> Result<Self, String> {
+        match size.bits() {
+            8 => Ok(Integer::I8),
+            16 => Ok(Integer::I16),
+            32 => Ok(Integer::I32),
+            64 => Ok(Integer::I64),
+            128 => Ok(Integer::I128),
+            _ => Err(format!("rust does not support integers with {} bits", size.bits())),
+        }
+    }
 }
 
 /// Fundamental unit of memory access and layout.
@@ -651,41 +718,94 @@
         }
     }
 
+    // FIXME(eddyb) remove, it's trivial thanks to `matches!`.
+    #[inline]
     pub fn is_float(self) -> bool {
         matches!(self, F32 | F64)
     }
 
+    // FIXME(eddyb) remove, it's completely unused.
+    #[inline]
     pub fn is_int(self) -> bool {
         matches!(self, Int(..))
     }
 }
 
+/// Inclusive wrap-around range of valid values, that is, if
+/// start > end, it represents `start..=MAX`,
+/// followed by `0..=end`.
+///
+/// That is, for an i8 primitive, a range of `254..=2` means following
+/// sequence:
+///
+///    254 (-2), 255 (-1), 0, 1, 2
+///
+/// This is intended specifically to mirror LLVM’s `!range` metadata,
+/// semantics.
+#[derive(Clone, PartialEq, Eq, Hash)]
+#[derive(HashStable_Generic)]
+pub struct WrappingRange {
+    pub start: u128,
+    pub end: u128,
+}
+
+impl WrappingRange {
+    /// Returns `true` if `v` is contained in the range.
+    #[inline(always)]
+    pub fn contains(&self, v: u128) -> bool {
+        if self.start <= self.end {
+            self.start <= v && v <= self.end
+        } else {
+            self.start <= v || v <= self.end
+        }
+    }
+
+    /// Returns `true` if zero is contained in the range.
+    /// Equal to `range.contains(0)` but should be faster.
+    #[inline(always)]
+    pub fn contains_zero(&self) -> bool {
+        self.start > self.end || self.start == 0
+    }
+
+    /// Returns `self` with replaced `start`
+    #[inline(always)]
+    pub fn with_start(mut self, start: u128) -> Self {
+        self.start = start;
+        self
+    }
+
+    /// Returns `self` with replaced `end`
+    #[inline(always)]
+    pub fn with_end(mut self, end: u128) -> Self {
+        self.end = end;
+        self
+    }
+}
+
+impl fmt::Debug for WrappingRange {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(fmt, "{}..={}", self.start, self.end)?;
+        Ok(())
+    }
+}
+
 /// Information about one scalar component of a Rust type.
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub struct Scalar {
     pub value: Primitive,
 
-    /// Inclusive wrap-around range of valid values, that is, if
-    /// start > end, it represents `start..=MAX`,
-    /// followed by `0..=end`.
-    ///
-    /// That is, for an i8 primitive, a range of `254..=2` means following
-    /// sequence:
-    ///
-    ///    254 (-2), 255 (-1), 0, 1, 2
-    ///
-    /// This is intended specifically to mirror LLVM’s `!range` metadata,
-    /// semantics.
     // FIXME(eddyb) always use the shortest range, e.g., by finding
     // the largest space between two consecutive valid values and
     // taking everything else as the (shortest) valid range.
-    pub valid_range: RangeInclusive<u128>,
+    pub valid_range: WrappingRange,
 }
 
 impl Scalar {
+    #[inline]
     pub fn is_bool(&self) -> bool {
-        matches!(self.value, Int(I8, false)) && self.valid_range == (0..=1)
+        matches!(self.value, Int(I8, false))
+            && matches!(self.valid_range, WrappingRange { start: 0, end: 1 })
     }
 
     /// Returns the valid range as a `x..y` range.
@@ -698,8 +818,8 @@
         let bits = self.value.size(cx).bits();
         assert!(bits <= 128);
         let mask = !0u128 >> (128 - bits);
-        let start = *self.valid_range.start();
-        let end = *self.valid_range.end();
+        let start = self.valid_range.start;
+        let end = self.valid_range.end;
         assert_eq!(start, start & mask);
         assert_eq!(end, end & mask);
         start..(end.wrapping_add(1) & mask)
@@ -749,6 +869,7 @@
 }
 
 impl FieldsShape {
+    #[inline]
     pub fn count(&self) -> usize {
         match *self {
             FieldsShape::Primitive => 0,
@@ -758,6 +879,7 @@
         }
     }
 
+    #[inline]
     pub fn offset(&self, i: usize) -> Size {
         match *self {
             FieldsShape::Primitive => {
@@ -781,6 +903,7 @@
         }
     }
 
+    #[inline]
     pub fn memory_index(&self, i: usize) -> usize {
         match *self {
             FieldsShape::Primitive => {
@@ -864,6 +987,7 @@
     }
 
     /// Returns `true` if this is a single signed integer scalar
+    #[inline]
     pub fn is_signed(&self) -> bool {
         match *self {
             Abi::Scalar(ref scal) => match scal.value {
@@ -954,14 +1078,14 @@
         let max_value = !0u128 >> (128 - bits);
 
         // Find out how many values are outside the valid range.
-        let niche = v.end().wrapping_add(1)..*v.start();
+        let niche = v.end.wrapping_add(1)..v.start;
         niche.end.wrapping_sub(niche.start) & max_value
     }
 
     pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
         assert!(count > 0);
 
-        let Scalar { value, valid_range: ref v } = self.scalar;
+        let Scalar { value, valid_range: v } = self.scalar.clone();
         let bits = value.size(cx).bits();
         assert!(bits <= 128);
         let max_value = !0u128 >> (128 - bits);
@@ -971,24 +1095,14 @@
         }
 
         // Compute the range of invalid values being reserved.
-        let start = v.end().wrapping_add(1) & max_value;
-        let end = v.end().wrapping_add(count) & max_value;
+        let start = v.end.wrapping_add(1) & max_value;
+        let end = v.end.wrapping_add(count) & max_value;
 
-        // If the `end` of our range is inside the valid range,
-        // then we ran out of invalid values.
-        // FIXME(eddyb) abstract this with a wraparound range type.
-        let valid_range_contains = |x| {
-            if v.start() <= v.end() {
-                *v.start() <= x && x <= *v.end()
-            } else {
-                *v.start() <= x || x <= *v.end()
-            }
-        };
-        if valid_range_contains(end) {
+        if v.contains(end) {
             return None;
         }
 
-        Some((start, Scalar { value, valid_range: *v.start()..=end }))
+        Some((start, Scalar { value, valid_range: v.with_end(end) }))
     }
 }
 
@@ -1046,7 +1160,7 @@
 /// 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, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)]
 pub struct TyAndLayout<'a, Ty> {
     pub ty: Ty,
     pub layout: &'a Layout,
@@ -1060,9 +1174,9 @@
 }
 
 /// Trait for context types that can compute layouts of things.
-pub trait LayoutOf {
-    type Ty;
-    type TyAndLayout;
+pub trait LayoutOf<'a>: Sized {
+    type Ty: TyAbiInterface<'a, Self>;
+    type TyAndLayout: MaybeResult<TyAndLayout<'a, Self::Ty>>;
 
     fn layout_of(&self, ty: Self::Ty) -> Self::TyAndLayout;
     fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyAndLayout {
@@ -1070,9 +1184,6 @@
     }
 }
 
-/// The `TyAndLayout` above will always be a `MaybeResult<TyAndLayout<'_, Self>>`.
-/// We can't add the bound due to the lifetime, but this trait is still useful when
-/// writing code that's generic over the `LayoutOf` impl.
 pub trait MaybeResult<T> {
     type Error;
 
@@ -1125,41 +1236,42 @@
     pub address_space: AddressSpace,
 }
 
-pub trait TyAndLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
-    fn for_variant(
+/// 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 {
+    fn ty_and_layout_for_variant(
         this: TyAndLayout<'a, Self>,
         cx: &C,
         variant_index: VariantIdx,
     ) -> TyAndLayout<'a, Self>;
-    fn field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> C::TyAndLayout;
-    fn pointee_info_at(this: TyAndLayout<'a, Self>, cx: &C, offset: Size) -> Option<PointeeInfo>;
+    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>;
 }
 
 impl<'a, Ty> TyAndLayout<'a, Ty> {
     pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
     where
-        Ty: TyAndLayoutMethods<'a, C>,
-        C: LayoutOf<Ty = Ty>,
+        Ty: TyAbiInterface<'a, C>,
     {
-        Ty::for_variant(self, cx, variant_index)
+        Ty::ty_and_layout_for_variant(self, cx, variant_index)
     }
 
-    /// Callers might want to use `C: LayoutOf<Ty=Ty, TyAndLayout: MaybeResult<Self>>`
-    /// to allow recursion (see `might_permit_zero_init` below for an example).
-    pub fn field<C>(self, cx: &C, i: usize) -> C::TyAndLayout
+    pub fn field<C>(self, cx: &C, i: usize) -> Self
     where
-        Ty: TyAndLayoutMethods<'a, C>,
-        C: LayoutOf<Ty = Ty>,
+        Ty: TyAbiInterface<'a, C>,
     {
-        Ty::field(self, cx, i)
+        Ty::ty_and_layout_field(self, cx, i)
     }
 
     pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo>
     where
-        Ty: TyAndLayoutMethods<'a, C>,
-        C: LayoutOf<Ty = Ty>,
+        Ty: TyAbiInterface<'a, C>,
     {
-        Ty::pointee_info_at(self, cx, offset)
+        Ty::ty_and_layout_pointee_info_at(self, cx, offset)
     }
 }
 
@@ -1187,17 +1299,16 @@
     /// FIXME: Once we removed all the conservatism, we could alternatively
     /// create an all-0/all-undef constant and run the const value validator to see if
     /// this is a valid value for the given type.
-    pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
+    pub fn might_permit_raw_init<C>(self, cx: &C, zero: bool) -> bool
     where
         Self: Copy,
-        Ty: TyAndLayoutMethods<'a, C>,
-        C: LayoutOf<Ty = Ty, TyAndLayout: MaybeResult<Self, Error = E>> + HasDataLayout,
+        Ty: TyAbiInterface<'a, C>,
+        C: HasDataLayout,
     {
         let scalar_allows_raw_init = move |s: &Scalar| -> bool {
             if zero {
-                let range = &s.valid_range;
                 // The range must contain 0.
-                range.contains(&0) || (*range.start() > *range.end()) // wrap-around allows 0
+                s.valid_range.contains_zero()
             } else {
                 // The range must include all values. `valid_range_exclusive` handles
                 // the wrap-around using target arithmetic; with wrap-around then the full
@@ -1217,7 +1328,7 @@
         };
         if !valid {
             // This is definitely not okay.
-            return Ok(false);
+            return false;
         }
 
         // If we have not found an error yet, we need to recursively descend into fields.
@@ -1228,16 +1339,15 @@
             }
             FieldsShape::Arbitrary { offsets, .. } => {
                 for idx in 0..offsets.len() {
-                    let field = self.field(cx, idx).to_result()?;
-                    if !field.might_permit_raw_init(cx, zero)? {
+                    if !self.field(cx, idx).might_permit_raw_init(cx, zero) {
                         // We found a field that is unhappy with this kind of initialization.
-                        return Ok(false);
+                        return false;
                     }
                 }
             }
         }
 
         // FIXME(#66151): For now, we are conservative and do not check `self.variants`.
-        Ok(true)
+        true
     }
 }
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index b52fa5b..99699c5 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -154,6 +154,7 @@
 mod nvptx;
 mod powerpc;
 mod riscv;
+mod s390x;
 mod spirv;
 mod wasm;
 mod x86;
@@ -166,6 +167,7 @@
 pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
 pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
 pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
+pub use s390x::{S390xInlineAsmReg, S390xInlineAsmRegClass};
 pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
 pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
 pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
@@ -184,6 +186,7 @@
     Mips64,
     PowerPC,
     PowerPC64,
+    S390x,
     SpirV,
     Wasm32,
     Bpf,
@@ -206,6 +209,7 @@
             "hexagon" => Ok(Self::Hexagon),
             "mips" => Ok(Self::Mips),
             "mips64" => Ok(Self::Mips64),
+            "s390x" => Ok(Self::S390x),
             "spirv" => Ok(Self::SpirV),
             "wasm32" => Ok(Self::Wasm32),
             "bpf" => Ok(Self::Bpf),
@@ -235,6 +239,7 @@
     PowerPC(PowerPCInlineAsmReg),
     Hexagon(HexagonInlineAsmReg),
     Mips(MipsInlineAsmReg),
+    S390x(S390xInlineAsmReg),
     SpirV(SpirVInlineAsmReg),
     Wasm(WasmInlineAsmReg),
     Bpf(BpfInlineAsmReg),
@@ -252,6 +257,7 @@
             Self::PowerPC(r) => r.name(),
             Self::Hexagon(r) => r.name(),
             Self::Mips(r) => r.name(),
+            Self::S390x(r) => r.name(),
             Self::Bpf(r) => r.name(),
             Self::Err => "<reg>",
         }
@@ -266,6 +272,7 @@
             Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()),
             Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
             Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
+            Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()),
             Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
             Self::Err => InlineAsmRegClass::Err,
         }
@@ -305,6 +312,9 @@
             InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
                 Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?)
             }
+            InlineAsmArch::S390x => {
+                Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, &name)?)
+            }
             InlineAsmArch::SpirV => {
                 Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?)
             }
@@ -333,6 +343,7 @@
             Self::PowerPC(r) => r.emit(out, arch, modifier),
             Self::Hexagon(r) => r.emit(out, arch, modifier),
             Self::Mips(r) => r.emit(out, arch, modifier),
+            Self::S390x(r) => r.emit(out, arch, modifier),
             Self::Bpf(r) => r.emit(out, arch, modifier),
             Self::Err => unreachable!("Use of InlineAsmReg::Err"),
         }
@@ -344,9 +355,10 @@
             Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))),
             Self::AArch64(_) => cb(self),
             Self::RiscV(_) => cb(self),
-            Self::PowerPC(_) => cb(self),
+            Self::PowerPC(r) => r.overlapping_regs(|r| cb(Self::PowerPC(r))),
             Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
             Self::Mips(_) => cb(self),
+            Self::S390x(_) => cb(self),
             Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
             Self::Err => unreachable!("Use of InlineAsmReg::Err"),
         }
@@ -374,6 +386,7 @@
     PowerPC(PowerPCInlineAsmRegClass),
     Hexagon(HexagonInlineAsmRegClass),
     Mips(MipsInlineAsmRegClass),
+    S390x(S390xInlineAsmRegClass),
     SpirV(SpirVInlineAsmRegClass),
     Wasm(WasmInlineAsmRegClass),
     Bpf(BpfInlineAsmRegClass),
@@ -392,6 +405,7 @@
             Self::PowerPC(r) => r.name(),
             Self::Hexagon(r) => r.name(),
             Self::Mips(r) => r.name(),
+            Self::S390x(r) => r.name(),
             Self::SpirV(r) => r.name(),
             Self::Wasm(r) => r.name(),
             Self::Bpf(r) => r.name(),
@@ -412,6 +426,7 @@
             Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC),
             Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon),
             Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
+            Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x),
             Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
             Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
             Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
@@ -439,6 +454,7 @@
             Self::PowerPC(r) => r.suggest_modifier(arch, ty),
             Self::Hexagon(r) => r.suggest_modifier(arch, ty),
             Self::Mips(r) => r.suggest_modifier(arch, ty),
+            Self::S390x(r) => r.suggest_modifier(arch, ty),
             Self::SpirV(r) => r.suggest_modifier(arch, ty),
             Self::Wasm(r) => r.suggest_modifier(arch, ty),
             Self::Bpf(r) => r.suggest_modifier(arch, ty),
@@ -462,6 +478,7 @@
             Self::PowerPC(r) => r.default_modifier(arch),
             Self::Hexagon(r) => r.default_modifier(arch),
             Self::Mips(r) => r.default_modifier(arch),
+            Self::S390x(r) => r.default_modifier(arch),
             Self::SpirV(r) => r.default_modifier(arch),
             Self::Wasm(r) => r.default_modifier(arch),
             Self::Bpf(r) => r.default_modifier(arch),
@@ -469,7 +486,7 @@
         }
     }
 
-    /// Returns a list of supported types for this register class, each with a
+    /// Returns a list of supported types for this register class, each with an
     /// options target feature required to use this type.
     pub fn supported_types(
         self,
@@ -484,6 +501,7 @@
             Self::PowerPC(r) => r.supported_types(arch),
             Self::Hexagon(r) => r.supported_types(arch),
             Self::Mips(r) => r.supported_types(arch),
+            Self::S390x(r) => r.supported_types(arch),
             Self::SpirV(r) => r.supported_types(arch),
             Self::Wasm(r) => r.supported_types(arch),
             Self::Bpf(r) => r.supported_types(arch),
@@ -509,6 +527,7 @@
             InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
                 Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
             }
+            InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(arch, name)?),
             InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
             InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?),
             InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?),
@@ -527,6 +546,7 @@
             Self::PowerPC(r) => r.valid_modifiers(arch),
             Self::Hexagon(r) => r.valid_modifiers(arch),
             Self::Mips(r) => r.valid_modifiers(arch),
+            Self::S390x(r) => r.valid_modifiers(arch),
             Self::SpirV(r) => r.valid_modifiers(arch),
             Self::Wasm(r) => r.valid_modifiers(arch),
             Self::Bpf(r) => r.valid_modifiers(arch),
@@ -695,6 +715,11 @@
             mips::fill_reg_map(arch, has_feature, target, &mut map);
             map
         }
+        InlineAsmArch::S390x => {
+            let mut map = s390x::regclass_map();
+            s390x::fill_reg_map(arch, has_feature, target, &mut map);
+            map
+        }
         InlineAsmArch::SpirV => {
             let mut map = spirv::regclass_map();
             spirv::fill_reg_map(arch, has_feature, target, &mut map);
@@ -712,3 +737,185 @@
         }
     }
 }
+
+#[derive(
+    Copy,
+    Clone,
+    Encodable,
+    Decodable,
+    Debug,
+    Eq,
+    PartialEq,
+    PartialOrd,
+    Hash,
+    HashStable_Generic
+)]
+pub enum InlineAsmClobberAbi {
+    X86,
+    X86_64Win,
+    X86_64SysV,
+    Arm,
+    AArch64,
+    RiscV,
+}
+
+impl InlineAsmClobberAbi {
+    /// Parses a clobber ABI for the given target, or returns a list of supported
+    /// clobber ABIs for the target.
+    pub fn parse(
+        arch: InlineAsmArch,
+        target: &Target,
+        name: Symbol,
+    ) -> Result<Self, &'static [&'static str]> {
+        let name = &*name.as_str();
+        match arch {
+            InlineAsmArch::X86 => match name {
+                "C" | "system" | "efiapi" | "cdecl" | "stdcall" | "fastcall" => {
+                    Ok(InlineAsmClobberAbi::X86)
+                }
+                _ => Err(&["C", "system", "efiapi", "cdecl", "stdcall", "fastcall"]),
+            },
+            InlineAsmArch::X86_64 => match name {
+                "C" | "system" if !target.is_like_windows => Ok(InlineAsmClobberAbi::X86_64SysV),
+                "C" | "system" if target.is_like_windows => Ok(InlineAsmClobberAbi::X86_64Win),
+                "win64" | "efiapi" => Ok(InlineAsmClobberAbi::X86_64Win),
+                "sysv64" => Ok(InlineAsmClobberAbi::X86_64SysV),
+                _ => Err(&["C", "system", "efiapi", "win64", "sysv64"]),
+            },
+            InlineAsmArch::Arm => match name {
+                "C" | "system" | "efiapi" | "aapcs" => Ok(InlineAsmClobberAbi::Arm),
+                _ => Err(&["C", "system", "efiapi", "aapcs"]),
+            },
+            InlineAsmArch::AArch64 => match name {
+                "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::AArch64),
+                _ => Err(&["C", "system", "efiapi"]),
+            },
+            InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
+                "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV),
+                _ => Err(&["C", "system", "efiapi"]),
+            },
+            _ => Err(&[]),
+        }
+    }
+
+    /// Returns the set of registers which are clobbered by this ABI.
+    pub fn clobbered_regs(self) -> &'static [InlineAsmReg] {
+        macro_rules! clobbered_regs {
+            ($arch:ident $arch_reg:ident {
+                $(
+                    $reg:ident,
+                )*
+            }) => {
+                &[
+                    $(InlineAsmReg::$arch($arch_reg::$reg),)*
+                ]
+            };
+        }
+        match self {
+            InlineAsmClobberAbi::X86 => clobbered_regs! {
+                X86 X86InlineAsmReg {
+                    ax, cx, dx,
+
+                    xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+
+                    k1, k2, k3, k4, k5, k6, k7,
+
+                    mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
+                    st0, st1, st2, st3, st4, st5, st6, st7,
+                }
+            },
+            InlineAsmClobberAbi::X86_64SysV => clobbered_regs! {
+                X86 X86InlineAsmReg {
+                    ax, cx, dx, si, di, r8, r9, r10, r11,
+
+                    xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+                    xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
+                    zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23,
+                    zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31,
+
+                    k1, k2, k3, k4, k5, k6, k7,
+
+                    mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
+                    st0, st1, st2, st3, st4, st5, st6, st7,
+                }
+            },
+            InlineAsmClobberAbi::X86_64Win => clobbered_regs! {
+                X86 X86InlineAsmReg {
+                    // rdi and rsi are callee-saved on windows
+                    ax, cx, dx, r8, r9, r10, r11,
+
+                    // xmm6-xmm15 are callee-saved on windows, but we need to
+                    // mark them as clobbered anyways because the upper portions
+                    // of ymm6-ymm15 are volatile.
+                    xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+                    xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
+                    zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23,
+                    zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31,
+
+                    k1, k2, k3, k4, k5, k6, k7,
+
+                    mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
+                    st0, st1, st2, st3, st4, st5, st6, st7,
+                }
+            },
+            InlineAsmClobberAbi::AArch64 => clobbered_regs! {
+                AArch64 AArch64InlineAsmReg {
+                    x0, x1, x2, x3, x4, x5, x6, x7,
+                    x8, x9, x10, x11, x12, x13, x14, x15,
+                    // x18 is platform-reserved or temporary, but we exclude it
+                    // here since it is a reserved register.
+                    x16, x17, x30,
+
+                    // Technically the low 64 bits of v8-v15 are preserved, but
+                    // we have no way of expressing this using clobbers.
+                    v0, v1, v2, v3, v4, v5, v6, v7,
+                    v8, v9, v10, v11, v12, v13, v14, v15,
+                    v16, v17, v18, v19, v20, v21, v22, v23,
+                    v24, v25, v26, v27, v28, v29, v30, v31,
+
+                    p0, p1, p2, p3, p4, p5, p6, p7,
+                    p8, p9, p10, p11, p12, p13, p14, p15,
+                    ffr,
+
+                }
+            },
+            InlineAsmClobberAbi::Arm => clobbered_regs! {
+                Arm ArmInlineAsmReg {
+                    // r9 is platform-reserved and is treated as callee-saved.
+                    r0, r1, r2, r3, r12, r14,
+
+                    // The finest-grained register variant is used here so that
+                    // partial uses of larger registers are properly handled.
+                    s0, s1, s2, s3, s4, s5, s6, s7,
+                    s8, s9, s10, s11, s12, s13, s14, s15,
+                    // s16-s31 are callee-saved
+                    d16, d17, d18, d19, d20, d21, d22, d23,
+                    d24, d25, d26, d27, d28, d29, d30, d31,
+                }
+            },
+            InlineAsmClobberAbi::RiscV => clobbered_regs! {
+                RiscV RiscVInlineAsmReg {
+                    // ra
+                    x1,
+                    // t0-t2
+                    x5, x6, x7,
+                    // a0-a7
+                    x10, x11, x12, x13, x14, x15, x16, x17,
+                    // t3-t6
+                    x28, x29, x30, x31,
+                    // ft0-ft7
+                    f0, f1, f2, f3, f4, f5, f6, f7,
+                    // fa0-fa7
+                    f10, f11, f12, f13, f14, f15, f16, f17,
+                    // ft8-ft11
+                    f28, f29, f30, f31,
+
+                    v0, v1, v2, v3, v4, v5, v6, v7,
+                    v8, v9, v10, v11, v12, v13, v14, v15,
+                    v16, v17, v18, v19, v20, v21, v22, v23,
+                    v24, v25, v26, v27, v28, v29, v30, v31,
+                }
+            },
+        }
+    }
+}
diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs
index 42fc25c..51a4303 100644
--- a/compiler/rustc_target/src/asm/powerpc.rs
+++ b/compiler/rustc_target/src/asm/powerpc.rs
@@ -7,6 +7,8 @@
         reg,
         reg_nonzero,
         freg,
+        cr,
+        xer,
     }
 }
 
@@ -44,6 +46,7 @@
                 }
             }
             Self::freg => types! { _: F32, F64; },
+            Self::cr | Self::xer => &[],
         }
     }
 }
@@ -108,6 +111,16 @@
         f29: freg = ["f29", "fr29"],
         f30: freg = ["f30", "fr30"],
         f31: freg = ["f31", "fr31"],
+        cr: cr = ["cr"],
+        cr0: cr = ["cr0"],
+        cr1: cr = ["cr1"],
+        cr2: cr = ["cr2"],
+        cr3: cr = ["cr3"],
+        cr4: cr = ["cr4"],
+        cr5: cr = ["cr5"],
+        cr6: cr = ["cr6"],
+        cr7: cr = ["cr7"],
+        xer: xer = ["xer"],
         #error = ["r1", "1", "sp"] =>
             "the stack pointer cannot be used as an operand for inline asm",
         #error = ["r2", "2"] =>
@@ -136,17 +149,55 @@
         _arch: InlineAsmArch,
         _modifier: Option<char>,
     ) -> fmt::Result {
+        macro_rules! do_emit {
+            (
+                $($(($reg:ident, $value:literal)),*;)*
+            ) => {
+                out.write_str(match self {
+                    $($(Self::$reg => $value,)*)*
+                })
+            };
+        }
         // Strip off the leading prefix.
-        if self as u32 <= Self::r28 as u32 {
-            let index = self as u32 - Self::r28 as u32;
-            write!(out, "{}", index)
-        } else if self as u32 >= Self::f0 as u32 && self as u32 <= Self::f31 as u32 {
-            let index = self as u32 - Self::f31 as u32;
-            write!(out, "{}", index)
-        } else {
-            unreachable!()
+        do_emit! {
+            (r0, "0"), (r3, "3"), (r4, "4"), (r5, "5"), (r6, "6"), (r7, "7");
+            (r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r14, "14"), (r15, "15");
+            (r16, "16"), (r17, "17"), (r18, "18"), (r19, "19"), (r20, "20"), (r21, "21"), (r22, "22"), (r23, "23");
+            (r24, "24"), (r25, "25"), (r26, "26"), (r27, "27"), (r28, "28");
+            (f0, "0"), (f1, "1"), (f2, "2"), (f3, "3"), (f4, "4"), (f5, "5"), (f6, "6"), (f7, "7");
+            (f8, "8"), (f9, "9"), (f10, "10"), (f11, "11"), (f12, "12"), (f13, "13"), (f14, "14"), (f15, "15");
+            (f16, "16"), (f17, "17"), (f18, "18"), (f19, "19"), (f20, "20"), (f21, "21"), (f22, "22"), (f23, "23");
+            (f24, "24"), (f25, "25"), (f26, "26"), (f27, "27"), (f28, "28"), (f29, "29"), (f30, "30"), (f31, "31");
+            (cr, "cr");
+            (cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7");
+            (xer, "xer");
         }
     }
 
-    pub fn overlapping_regs(self, mut _cb: impl FnMut(PowerPCInlineAsmReg)) {}
+    pub fn overlapping_regs(self, mut cb: impl FnMut(PowerPCInlineAsmReg)) {
+        macro_rules! reg_conflicts {
+            (
+                $(
+                    $full:ident : $($field:ident)*
+                ),*;
+            ) => {
+                match self {
+                    $(
+                        Self::$full => {
+                            cb(Self::$full);
+                            $(cb(Self::$field);)*
+                        }
+                        $(Self::$field)|* => {
+                            cb(Self::$full);
+                            cb(self);
+                        }
+                    )*
+                    r => cb(r),
+                }
+            };
+        }
+        reg_conflicts! {
+            cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7;
+        }
+    }
 }
diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs
new file mode 100644
index 0000000..a74873f
--- /dev/null
+++ b/compiler/rustc_target/src/asm/s390x.rs
@@ -0,0 +1,106 @@
+use super::{InlineAsmArch, InlineAsmType};
+use rustc_macros::HashStable_Generic;
+use std::fmt;
+
+def_reg_class! {
+    S390x S390xInlineAsmRegClass {
+        reg,
+        freg,
+    }
+}
+
+impl S390xInlineAsmRegClass {
+    pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
+        &[]
+    }
+
+    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
+        None
+    }
+
+    pub fn suggest_modifier(
+        self,
+        _arch: InlineAsmArch,
+        _ty: InlineAsmType,
+    ) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn supported_types(
+        self,
+        arch: InlineAsmArch,
+    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+        match (self, arch) {
+            (Self::reg, _) => types! { _: I8, I16, I32, I64; },
+            (Self::freg, _) => types! { _: F32, F64; },
+        }
+    }
+}
+
+def_regs! {
+    S390x S390xInlineAsmReg S390xInlineAsmRegClass {
+        r0: reg = ["r0"],
+        r1: reg = ["r1"],
+        r2: reg = ["r2"],
+        r3: reg = ["r3"],
+        r4: reg = ["r4"],
+        r5: reg = ["r5"],
+        r6: reg = ["r6"],
+        r7: reg = ["r7"],
+        r8: reg = ["r8"],
+        r9: reg = ["r9"],
+        r10: reg = ["r10"],
+        r12: reg = ["r12"],
+        r13: reg = ["r13"],
+        r14: reg = ["r14"],
+        f0: freg = ["f0"],
+        f1: freg = ["f1"],
+        f2: freg = ["f2"],
+        f3: freg = ["f3"],
+        f4: freg = ["f4"],
+        f5: freg = ["f5"],
+        f6: freg = ["f6"],
+        f7: freg = ["f7"],
+        f8: freg = ["f8"],
+        f9: freg = ["f9"],
+        f10: freg = ["f10"],
+        f11: freg = ["f11"],
+        f12: freg = ["f12"],
+        f13: freg = ["f13"],
+        f14: freg = ["f14"],
+        f15: freg = ["f15"],
+        #error = ["r11"] =>
+            "The frame pointer cannot be used as an operand for inline asm",
+        #error = ["r15"] =>
+            "The stack pointer cannot be used as an operand for inline asm",
+        #error = [
+            "c0", "c1", "c2", "c3",
+            "c4", "c5", "c6", "c7",
+            "c8", "c9", "c10", "c11",
+            "c12", "c13", "c14", "c15"
+        ] =>
+            "control registers are reserved by the kernel and cannot be used as operands for inline asm",
+        #error = [
+            "a0", "a1", "a2", "a3",
+            "a4", "a5", "a6", "a7",
+            "a8", "a9", "a10", "a11",
+            "a12", "a13", "a14", "a15"
+        ] =>
+            "access registers are not supported and cannot be used as operands for inline asm",
+    }
+}
+
+impl S390xInlineAsmReg {
+    pub fn emit(
+        self,
+        out: &mut dyn fmt::Write,
+        _arch: InlineAsmArch,
+        _modifier: Option<char>,
+    ) -> fmt::Result {
+        write!(out, "%{}", self.name())
+    }
+}
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index d39e5a5..e75c525 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -14,6 +14,8 @@
 #![feature(associated_type_bounds)]
 #![feature(exhaustive_patterns)]
 #![feature(min_specialization)]
+#![feature(step_trait)]
+#![feature(unchecked_math)]
 
 use std::path::{Path, PathBuf};
 
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
index e5805d9..6468419 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
@@ -2,8 +2,15 @@
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
+    // Clang automatically chooses a more specific target based on
+    // IPHONEOS_DEPLOYMENT_TARGET.
+    // This is required for the target to pick the right
+    // MACH-O commands, so we do too.
+    let arch = "arm64";
+    let llvm_target = super::apple_base::ios_llvm_target(arch);
+
     Target {
-        llvm_target: "arm64-apple-ios".to_string(),
+        llvm_target,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
index 09ea7d3..0caecd2 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
@@ -6,6 +6,12 @@
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
         arch: "aarch64".to_string(),
-        options: TargetOptions { max_atomic_width: Some(128), ..super::freebsd_base::opts() },
+        options: TargetOptions {
+            max_atomic_width: Some(128),
+            supported_sanitizers: SanitizerSet::ADDRESS
+                | SanitizerSet::MEMORY
+                | SanitizerSet::THREAD,
+            ..super::freebsd_base::opts()
+        },
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
new file mode 100644
index 0000000..20c528d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
@@ -0,0 +1,27 @@
+// This defines the aarch64 target for UEFI systems as described in the UEFI specification. See the
+// uefi-base module for generic UEFI options.
+
+use super::uefi_msvc_base;
+use crate::spec::{LinkerFlavor, LldFlavor, Target};
+
+pub fn target() -> Target {
+    let mut base = uefi_msvc_base::opts();
+
+    base.max_atomic_width = Some(64);
+
+    let pre_link_args_msvc = vec!["/machine:arm64".to_string()];
+
+    base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone());
+    base.pre_link_args
+        .get_mut(&LinkerFlavor::Lld(LldFlavor::Link))
+        .unwrap()
+        .extend(pre_link_args_msvc);
+
+    Target {
+        llvm_target: "aarch64-unknown-windows".to_string(),
+        pointer_width: 64,
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs
index ee36090..e3a2226 100644
--- a/compiler/rustc_target/src/spec/abi.rs
+++ b/compiler/rustc_target/src/spec/abi.rs
@@ -87,6 +87,9 @@
 }
 
 impl Abi {
+    /// Default ABI chosen for `extern fn` declarations without an explicit ABI.
+    pub const FALLBACK: Abi = Abi::C { unwind: false };
+
     #[inline]
     pub fn index(self) -> usize {
         // N.B., this ordering MUST match the AbiDatas array above.
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index 0c8a892..a21b784 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -1,6 +1,6 @@
 use std::env;
 
-use crate::spec::{FramePointer, SplitDebuginfo, TargetOptions};
+use crate::spec::{FramePointer, LldFlavor, SplitDebuginfo, TargetOptions};
 
 pub fn opts(os: &str) -> TargetOptions {
     // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
@@ -35,6 +35,7 @@
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
         eh_frame_header: false,
+        lld_flavor: LldFlavor::Ld64,
 
         // The historical default for macOS targets is to run `dsymutil` which
         // generates a packed version of debuginfo split from the main file.
@@ -91,6 +92,17 @@
     deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0))
 }
 
+pub fn ios_llvm_target(arch: &str) -> String {
+    // Modern iOS tooling extracts information about deployment target
+    // from LC_BUILD_VERSION. This load command will only be emitted when
+    // we build with a version specific `llvm_target`, with the version
+    // set high enough. Luckily one LC_BUILD_VERSION is enough, for Xcode
+    // to pick it up (since std and core are still built with the fallback
+    // of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION).
+    let (major, minor) = ios_deployment_target();
+    format!("{}-apple-ios{}.{}.0", arch, major, minor)
+}
+
 pub fn ios_sim_llvm_target(arch: &str) -> String {
     let (major, minor) = ios_deployment_target();
     format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor)
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
index c98a12c..ed4779c 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
@@ -20,6 +20,8 @@
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
+            // GCC and Clang default to 8 for arm-none here
+            c_enum_min_bits: 8,
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
index 2926354..b60e289 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
@@ -21,6 +21,8 @@
             features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
+            // GCC and Clang default to 8 for arm-none here
+            c_enum_min_bits: 8,
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs
index 2f22868..1f90c78 100644
--- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/armv7_apple_ios.rs
@@ -3,7 +3,7 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7-apple-ios".to_string(),
+        llvm_target: super::apple_base::ios_llvm_target("armv7"),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
         arch: "arm".to_string(),
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
index 8bff60e..88040f4 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
@@ -28,6 +28,7 @@
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
         emit_debug_gdb_scripts: false,
+        c_enum_min_bits: 8,
         ..Default::default()
     };
     Target {
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
index ea2751e..af32484 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
@@ -19,6 +19,8 @@
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
         emit_debug_gdb_scripts: false,
+        // GCC and Clang default to 8 for arm-none here
+        c_enum_min_bits: 8,
         ..Default::default()
     };
     Target {
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
index c695542..c0e9709 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
@@ -19,6 +19,8 @@
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
+            // GCC and Clang default to 8 for arm-none here
+            c_enum_min_bits: 8,
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
index 50c3702..b126887 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
@@ -20,6 +20,8 @@
             features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
+            // GCC and Clang default to 8 for arm-none here
+            c_enum_min_bits: 8,
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/freebsd_base.rs b/compiler/rustc_target/src/spec/freebsd_base.rs
index 998d6ff..f2ec6aa 100644
--- a/compiler/rustc_target/src/spec/freebsd_base.rs
+++ b/compiler/rustc_target/src/spec/freebsd_base.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FramePointer, RelroLevel, TargetOptions};
+use crate::spec::{RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
@@ -8,7 +8,6 @@
         families: vec!["unix".to_string()],
         has_rpath: true,
         position_independent_executables: true,
-        frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit...
         relro_level: RelroLevel::Full,
         abi_return_struct_as_int: true,
         dwarf_version: Some(2),
diff --git a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
index e0097ee..27d306c 100644
--- a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
@@ -13,6 +13,8 @@
     base.dynamic_linking = true;
     base.executables = true;
 
+    base.c_enum_min_bits = 8;
+
     Target {
         llvm_target: "hexagon-unknown-linux-musl".to_string(),
         pointer_width: 32,
diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs
index f5d7be4..4419dfe 100644
--- a/compiler/rustc_target/src/spec/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs
@@ -4,7 +4,7 @@
 pub fn target() -> Target {
     let base = opts("ios", Arch::I386);
     Target {
-        llvm_target: "i386-apple-ios".to_string(),
+        llvm_target: super::apple_base::ios_sim_llvm_target("i386"),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:128-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 0185132..27322136 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -664,7 +664,7 @@
         self.into_iter()
             .map(|v| Some(v.as_str()?.to_json()))
             .collect::<Option<Vec<_>>>()
-            .unwrap_or(Vec::new())
+            .unwrap_or_default()
             .to_json()
     }
 }
@@ -802,6 +802,7 @@
     ("armv6-unknown-freebsd", armv6_unknown_freebsd),
     ("armv7-unknown-freebsd", armv7_unknown_freebsd),
     ("i686-unknown-freebsd", i686_unknown_freebsd),
+    ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
     ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
     ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
     ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
@@ -902,6 +903,7 @@
 
     ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
     ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
+    ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
     ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
     ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
     ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
@@ -917,6 +919,7 @@
 
     ("x86_64-unknown-uefi", x86_64_unknown_uefi),
     ("i686-unknown-uefi", i686_unknown_uefi),
+    ("aarch64-unknown-uefi", aarch64_unknown_uefi),
 
     ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
 
@@ -1333,6 +1336,9 @@
 
     /// If present it's a default value to use for adjusting the C ABI.
     pub default_adjusted_cabi: Option<Abi>,
+
+    /// Minimum number of bits in #[repr(C)] enum. Defaults to 32.
+    pub c_enum_min_bits: u64,
 }
 
 impl Default for TargetOptions {
@@ -1437,6 +1443,7 @@
             split_debuginfo: SplitDebuginfo::Off,
             supported_sanitizers: SanitizerSet::empty(),
             default_adjusted_cabi: None,
+            c_enum_min_bits: 32,
         }
     }
 }
@@ -1494,7 +1501,8 @@
             | Cdecl
             | EfiApi => true,
             X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
-            Aapcs | CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
+            Aapcs => "arm" == self.arch,
+            CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
             Win64 | SysV64 => self.arch == "x86_64",
             PtxKernel => self.arch == "nvptx64",
             Msp430Interrupt => self.arch == "msp430",
@@ -1601,6 +1609,12 @@
                     base.$key_name = s;
                 }
             } );
+            ($key_name:ident, u64) => ( {
+                let name = (stringify!($key_name)).replace("_", "-");
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
+                    base.$key_name = s;
+                }
+            } );
             ($key_name:ident, Option<u32>) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
                 if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
@@ -2014,10 +2028,11 @@
         key!(split_debuginfo, SplitDebuginfo)?;
         key!(supported_sanitizers, SanitizerSet)?;
         key!(default_adjusted_cabi, Option<Abi>)?;
+        key!(c_enum_min_bits, u64);
 
         if base.is_builtin {
             // This can cause unfortunate ICEs later down the line.
-            return Err(format!("may not set is_builtin for targets not built-in"));
+            return Err("may not set is_builtin for targets not built-in".to_string());
         }
         // Each field should have been read using `Json::remove_key` so any keys remaining are unused.
         let remaining_keys = obj.as_object().ok_or("Expected JSON object for target")?.keys();
@@ -2252,6 +2267,7 @@
         target_option_val!(has_thumb_interworking);
         target_option_val!(split_debuginfo);
         target_option_val!(supported_sanitizers);
+        target_option_val!(c_enum_min_bits);
 
         if let Some(abi) = self.default_adjusted_cabi {
             d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json());
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
index 559a1a4..f10d4d4 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
@@ -14,7 +14,7 @@
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".to_string(),
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-v256:256:256-v512:512:512".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(),
         arch: "powerpc64".to_string(),
         options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
index f1190b1..6116217 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
@@ -10,7 +10,7 @@
     Target {
         llvm_target: "powerpc64-unknown-linux-musl".to_string(),
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-v256:256:256-v512:512:512".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(),
         arch: "powerpc64".to_string(),
         options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
index 3ebc546..9c63997 100644
--- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
@@ -10,7 +10,7 @@
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".to_string(),
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-v256:256:256-v512:512:512".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(),
         arch: "powerpc64".to_string(),
         options: TargetOptions { endian: Endian::Big, ..base },
     }
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
index 76f70e4..f645ece 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
@@ -9,7 +9,7 @@
     Target {
         llvm_target: "powerpc64le-unknown-linux-gnu".to_string(),
         pointer_width: 64,
-        data_layout: "e-m:e-i64:64-n32:64-v256:256:256-v512:512:512".to_string(),
+        data_layout: "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(),
         arch: "powerpc64".to_string(),
         options: TargetOptions { mcount: "_mcount".to_string(), ..base },
     }
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
index 42c4910..934371f 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
@@ -9,7 +9,7 @@
     Target {
         llvm_target: "powerpc64le-unknown-linux-musl".to_string(),
         pointer_width: 64,
-        data_layout: "e-m:e-i64:64-n32:64-v256:256:256-v512:512:512".to_string(),
+        data_layout: "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(),
         arch: "powerpc64".to_string(),
         options: TargetOptions { mcount: "_mcount".to_string(), ..base },
     }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
new file mode 100644
index 0000000..e113180
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
@@ -0,0 +1,27 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+    let mut base = super::freebsd_base::opts();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
+    // Extra hint to linker that we are generating secure-PLT code.
+    base.pre_link_args
+        .entry(LinkerFlavor::Gcc)
+        .or_default()
+        .push("--target=powerpc-unknown-freebsd13.0".to_string());
+    base.max_atomic_width = Some(32);
+
+    Target {
+        llvm_target: "powerpc-unknown-freebsd13.0".to_string(),
+        pointer_width: 32,
+        data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
+        arch: "powerpc".to_string(),
+        options: TargetOptions {
+            endian: Endian::Big,
+            features: "+secure-plt".to_string(),
+            relocation_model: RelocModel::Pic,
+            mcount: "_mcount".to_string(),
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
new file mode 100644
index 0000000..fb084af
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
@@ -0,0 +1,37 @@
+use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
+        llvm_target: "riscv32".to_string(),
+        pointer_width: 32,
+        arch: "riscv32".to_string(),
+
+        options: TargetOptions {
+            families: vec!["unix".to_string()],
+            os: "espidf".to_string(),
+            env: "newlib".to_string(),
+            vendor: "espressif".to_string(),
+            linker_flavor: LinkerFlavor::Gcc,
+            linker: Some("riscv32-esp-elf-gcc".to_string()),
+            cpu: "generic-rv32".to_string(),
+
+            // While the RiscV32IMC architecture does not natively support atomics, ESP-IDF does support
+            // the __atomic* and __sync* GCC builtins, so setting `max_atomic_width` to `Some(32)`
+            // and `atomic_cas` to `true` will cause the compiler to emit libcalls to these builtins.
+            //
+            // Support for atomics is necessary for the Rust STD library, which is supported by the ESP-IDF framework.
+            max_atomic_width: Some(32),
+            atomic_cas: true,
+
+            features: "+m,+c".to_string(),
+            executables: true,
+            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/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs
index bac1203..e2e5285 100644
--- a/compiler/rustc_target/src/spec/thumb_base.rs
+++ b/compiler/rustc_target/src/spec/thumb_base.rs
@@ -53,6 +53,9 @@
         // LLVM is eager to trash the link register when calling `noreturn` functions, which
         // breaks debugging. Preserve LR by default to prevent that from happening.
         frame_pointer: FramePointer::Always,
+        // ARM supports multiple ABIs for enums, the linux one matches the default of 32 here
+        // but any arm-none or thumb-none target will be defaulted to 8 on GCC and clang
+        c_enum_min_bits: 8,
         ..Default::default()
     }
 }
diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
index 3021393..86b1a75 100644
--- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
@@ -43,7 +43,7 @@
     Target {
         llvm_target: "wasm32-unknown-emscripten".to_string(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-f128:64-n32:64-S128-ni:1:10:20".to_string(),
         arch: "wasm32".to_string(),
         options: opts,
     }
diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
index 834c4db..134c680 100644
--- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
@@ -54,7 +54,7 @@
     Target {
         llvm_target: "wasm32-unknown-unknown".to_string(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20".to_string(),
         arch: "wasm32".to_string(),
         options,
     }
diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs
index a6b12d2..2dab206 100644
--- a/compiler/rustc_target/src/spec/wasm32_wasi.rs
+++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs
@@ -109,7 +109,7 @@
     Target {
         llvm_target: "wasm32-wasi".to_string(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20".to_string(),
         arch: "wasm32".to_string(),
         options,
     }
diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
index 8bfb229..fb6526c 100644
--- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
@@ -32,7 +32,7 @@
     Target {
         llvm_target: "wasm64-unknown-unknown".to_string(),
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128".to_string(),
+        data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128-ni:1:10:20".to_string(),
         arch: "wasm64".to_string(),
         options,
     }
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
index adb8771..6e20bd2 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
@@ -4,7 +4,7 @@
 pub fn target() -> Target {
     let base = opts("ios", Arch::X86_64);
     Target {
-        llvm_target: "x86_64-apple-ios".to_string(),
+        llvm_target: super::apple_base::ios_sim_llvm_target("x86_64"),
         pointer_width: 64,
         data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
             .to_string(),
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
index b78e43d..34b6d29 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
 
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
@@ -8,6 +8,7 @@
     base.max_atomic_width = Some(64);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
+    base.supported_sanitizers = SanitizerSet::ADDRESS;
 
     Target {
         llvm_target: "x86_64-pc-solaris".to_string(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
index d3f9349..ec196a7 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
@@ -1,10 +1,11 @@
-use crate::spec::{LinkerFlavor, Target};
+use crate::spec::{LinkerFlavor, SanitizerSet, Target};
 
 pub fn target() -> Target {
     let mut base = super::illumos_base::opts();
     base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string(), "-std=c99".to_string()]);
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
+    base.supported_sanitizers = SanitizerSet::ADDRESS;
 
     Target {
         // LLVM does not currently have a separate illumos target,
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
index 0269c7a..9ba8628 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
@@ -7,6 +7,8 @@
     base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
+    base.supported_sanitizers =
+        SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
 
     Target {
         llvm_target: "x86_64-unknown-netbsd".to_string(),