Importing rustc-1.61.0

Test: ./build.py --lto=thin
Change-Id: I5c65158a0532cb09120797ae48d6b353492c1011
diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs
index 39d80c4..72709d3 100644
--- a/compiler/rustc_target/src/abi/call/sparc64.rs
+++ b/compiler/rustc_target/src/abi/call/sparc64.rs
@@ -1,29 +1,135 @@
 // FIXME: This needs an audit for correctness and completeness.
 
 use crate::abi::call::{
-    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, RegKind, Uniform,
+    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, Uniform,
 };
-use crate::abi::{self, HasDataLayout, Size, TyAbiInterface};
+use crate::abi::{self, HasDataLayout, Scalar, Size, TyAbiInterface, TyAndLayout};
 
-fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
+#[derive(Clone, Debug)]
+pub struct Sdata {
+    pub prefix: [Option<Reg>; 8],
+    pub prefix_index: usize,
+    pub last_offset: Size,
+    pub has_float: bool,
+    pub arg_attribute: ArgAttribute,
+}
+
+fn arg_scalar<C>(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdata
+where
+    C: HasDataLayout,
+{
+    let dl = cx.data_layout();
+
+    if scalar.value != abi::F32 && scalar.value != abi::F64 {
+        return data;
+    }
+
+    data.has_float = true;
+
+    if !data.last_offset.is_aligned(dl.f64_align.abi) && data.last_offset < offset {
+        if data.prefix_index == data.prefix.len() {
+            return data;
+        }
+        data.prefix[data.prefix_index] = Some(Reg::i32());
+        data.prefix_index += 1;
+        data.last_offset = data.last_offset + Reg::i32().size;
+    }
+
+    for _ in 0..((offset - data.last_offset).bits() / 64)
+        .min((data.prefix.len() - data.prefix_index) as u64)
+    {
+        data.prefix[data.prefix_index] = Some(Reg::i64());
+        data.prefix_index += 1;
+        data.last_offset = data.last_offset + Reg::i64().size;
+    }
+
+    if data.last_offset < offset {
+        if data.prefix_index == data.prefix.len() {
+            return data;
+        }
+        data.prefix[data.prefix_index] = Some(Reg::i32());
+        data.prefix_index += 1;
+        data.last_offset = data.last_offset + Reg::i32().size;
+    }
+
+    if data.prefix_index == data.prefix.len() {
+        return data;
+    }
+
+    if scalar.value == abi::F32 {
+        data.arg_attribute = ArgAttribute::InReg;
+        data.prefix[data.prefix_index] = Some(Reg::f32());
+        data.last_offset = offset + Reg::f32().size;
+    } else {
+        data.prefix[data.prefix_index] = Some(Reg::f64());
+        data.last_offset = offset + Reg::f64().size;
+    }
+    data.prefix_index += 1;
+    return data;
+}
+
+fn arg_scalar_pair<C>(
+    cx: &C,
+    scalar1: &Scalar,
+    scalar2: &Scalar,
+    mut offset: Size,
+    mut data: Sdata,
+) -> Sdata
+where
+    C: HasDataLayout,
+{
+    data = arg_scalar(cx, &scalar1, offset, data);
+    if scalar1.value == abi::F32 {
+        offset += Reg::f32().size;
+    } else if scalar2.value == abi::F64 {
+        offset += Reg::f64().size;
+    } else if let abi::Int(i, _signed) = scalar1.value {
+        offset += i.size();
+    } else if scalar1.value == abi::Pointer {
+        offset = offset + Reg::i64().size;
+    }
+
+    if (offset.raw % 4) != 0 && (scalar2.value == abi::F32 || scalar2.value == abi::F64) {
+        offset.raw += 4 - (offset.raw % 4);
+    }
+    data = arg_scalar(cx, &scalar2, offset, data);
+    return data;
+}
+
+fn parse_structure<'a, Ty, C>(
+    cx: &C,
+    layout: TyAndLayout<'a, Ty>,
+    mut data: Sdata,
+    mut offset: Size,
+) -> Sdata
 where
     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.
-        if arg.layout.size > unit.size.checked_mul(8, cx).unwrap() {
-            return None;
+    if let abi::FieldsShape::Union(_) = layout.fields {
+        return data;
+    }
+
+    match layout.abi {
+        abi::Abi::Scalar(scalar) => {
+            data = arg_scalar(cx, &scalar, offset, data);
         }
+        abi::Abi::Aggregate { .. } => {
+            for i in 0..layout.fields.count().clone() {
+                if offset < layout.fields.offset(i) {
+                    offset = layout.fields.offset(i);
+                }
+                data = parse_structure(cx, layout.field(cx, i).clone(), data.clone(), offset);
+            }
+        }
+        _ => {
+            if let abi::Abi::ScalarPair(scalar1, scalar2) = &layout.abi {
+                data = arg_scalar_pair(cx, scalar1, scalar2, offset, data);
+            }
+        }
+    }
 
-        let valid_unit = match unit.kind {
-            RegKind::Integer => false,
-            RegKind::Float => false,
-            RegKind::Vector => arg.layout.size.bits() == 128,
-        };
-
-        valid_unit.then_some(Uniform { unit, total: arg.layout.size })
-    })
+    return data;
 }
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size)
@@ -36,101 +142,71 @@
         return;
     }
 
-    // This doesn't intentionally handle structures with floats which needs
-    // special care below.
-    if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
-        arg.cast_to(uniform);
-        return;
-    }
-
-    if let abi::FieldsShape::Arbitrary { .. } = arg.layout.fields {
-        let dl = cx.data_layout();
-        let size = arg.layout.size;
-        let mut prefix = [None; 8];
-        let mut prefix_index = 0;
-        let mut last_offset = Size::ZERO;
-        let mut has_float = false;
-        let mut arg_attribute = ArgAttribute::default();
-
-        for i in 0..arg.layout.fields.count() {
-            let field = arg.layout.field(cx, i);
-            let offset = arg.layout.fields.offset(i);
-
-            if let abi::Abi::Scalar(scalar) = &field.abi {
-                if scalar.value == abi::F32 || scalar.value == abi::F64 {
-                    has_float = true;
-
-                    if !last_offset.is_aligned(dl.f64_align.abi) && last_offset < offset {
-                        if prefix_index == prefix.len() {
-                            break;
-                        }
-                        prefix[prefix_index] = Some(Reg::i32());
-                        prefix_index += 1;
-                        last_offset = last_offset + Reg::i32().size;
-                    }
-
-                    for _ in 0..((offset - last_offset).bits() / 64)
-                        .min((prefix.len() - prefix_index) as u64)
-                    {
-                        prefix[prefix_index] = Some(Reg::i64());
-                        prefix_index += 1;
-                        last_offset = last_offset + Reg::i64().size;
-                    }
-
-                    if last_offset < offset {
-                        if prefix_index == prefix.len() {
-                            break;
-                        }
-                        prefix[prefix_index] = Some(Reg::i32());
-                        prefix_index += 1;
-                        last_offset = last_offset + Reg::i32().size;
-                    }
-
-                    if prefix_index == prefix.len() {
-                        break;
-                    }
-
-                    if scalar.value == abi::F32 {
-                        arg_attribute = ArgAttribute::InReg;
-                        prefix[prefix_index] = Some(Reg::f32());
-                        last_offset = offset + Reg::f32().size;
-                    } else {
-                        prefix[prefix_index] = Some(Reg::f64());
-                        last_offset = offset + Reg::f64().size;
-                    }
-                    prefix_index += 1;
-                }
-            }
-        }
-
-        if has_float && arg.layout.size <= in_registers_max {
-            let mut rest_size = size - last_offset;
-
-            if (rest_size.raw % 8) != 0 && prefix_index < prefix.len() {
-                prefix[prefix_index] = Some(Reg::i32());
-                rest_size = rest_size - Reg::i32().size;
-            }
-
-            arg.cast_to(CastTarget {
-                prefix,
-                rest: Uniform { unit: Reg::i64(), total: rest_size },
-                attrs: ArgAttributes {
-                    regular: arg_attribute,
-                    arg_ext: ArgExtension::None,
-                    pointee_size: Size::ZERO,
-                    pointee_align: None,
-                },
-            });
-            return;
-        }
-    }
-
     let total = arg.layout.size;
     if total > in_registers_max {
         arg.make_indirect();
         return;
     }
 
+    match arg.layout.fields {
+        abi::FieldsShape::Primitive => unreachable!(),
+        abi::FieldsShape::Array { .. } => {
+            // Arrays are passed indirectly
+            arg.make_indirect();
+            return;
+        }
+        abi::FieldsShape::Union(_) => {
+            // Unions and are always treated as a series of 64-bit integer chunks
+        }
+        abi::FieldsShape::Arbitrary { .. } => {
+            // Structures with floating point numbers need special care.
+
+            let mut data = parse_structure(
+                cx,
+                arg.layout.clone(),
+                Sdata {
+                    prefix: [None; 8],
+                    prefix_index: 0,
+                    last_offset: Size::ZERO,
+                    has_float: false,
+                    arg_attribute: ArgAttribute::default(),
+                },
+                Size { raw: 0 },
+            );
+
+            if data.has_float {
+                // Structure { float, int, int } doesn't like to be handled like
+                // { float, long int }. Other way around it doesn't mind.
+                if data.last_offset < arg.layout.size
+                    && (data.last_offset.raw % 8) != 0
+                    && data.prefix_index < data.prefix.len()
+                {
+                    data.prefix[data.prefix_index] = Some(Reg::i32());
+                    data.prefix_index += 1;
+                    data.last_offset += Reg::i32().size;
+                }
+
+                let mut rest_size = arg.layout.size - data.last_offset;
+                if (rest_size.raw % 8) != 0 && data.prefix_index < data.prefix.len() {
+                    data.prefix[data.prefix_index] = Some(Reg::i32());
+                    rest_size = rest_size - Reg::i32().size;
+                }
+
+                arg.cast_to(CastTarget {
+                    prefix: data.prefix,
+                    rest: Uniform { unit: Reg::i64(), total: rest_size },
+                    attrs: ArgAttributes {
+                        regular: data.arg_attribute,
+                        arg_ext: ArgExtension::None,
+                        pointee_size: Size::ZERO,
+                        pointee_align: None,
+                    },
+                });
+                return;
+            }
+        }
+    }
+
     arg.cast_to(Uniform { unit: Reg::i64(), total });
 }
 
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 7f1fd28..52fce7c 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -10,6 +10,7 @@
 use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
 use std::str::FromStr;
 
+use rustc_data_structures::intern::Interned;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::json::{Json, ToJson};
@@ -121,12 +122,9 @@
                     dl.pointer_align = align(a, p)?;
                 }
                 [s, ref a @ ..] if s.starts_with('i') => {
-                    let bits = match s[1..].parse::<u64>() {
-                        Ok(bits) => bits,
-                        Err(_) => {
-                            size(&s[1..], "i")?; // For the user error.
-                            continue;
-                        }
+                    let Ok(bits) = s[1..].parse::<u64>() else {
+                        size(&s[1..], "i")?; // For the user error.
+                        continue;
                     };
                     let a = align(a, s)?;
                     match bits {
@@ -281,7 +279,6 @@
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
 pub struct Size {
-    // The top 3 bits are ALWAYS zero.
     raw: u64,
 }
 
@@ -289,22 +286,9 @@
     pub const ZERO: Size = Size { raw: 0 };
 
     /// Rounds `bits` up to the next-higher byte boundary, if `bits` is
-    /// is not aligned.
+    /// not a multiple of 8.
     pub fn from_bits(bits: impl TryInto<u64>) -> Size {
         let bits = bits.try_into().ok().unwrap();
-
-        #[cold]
-        fn overflow(bits: u64) -> ! {
-            panic!("Size::from_bits({}) has overflowed", bits);
-        }
-
-        // This is the largest value of `bits` that does not cause overflow
-        // during rounding, and guarantees that the resulting number of bytes
-        // cannot cause overflow when multiplied by 8.
-        if bits > 0xffff_ffff_ffff_fff8 {
-            overflow(bits);
-        }
-
         // Avoid potential overflow from `bits + 7`.
         Size { raw: bits / 8 + ((bits % 8) + 7) / 8 }
     }
@@ -327,7 +311,12 @@
 
     #[inline]
     pub fn bits(self) -> u64 {
-        self.raw << 3
+        #[cold]
+        fn overflow(bytes: u64) -> ! {
+            panic!("Size::bits: {} bytes in bits doesn't fit in u64", bytes)
+        }
+
+        self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes()))
     }
 
     #[inline]
@@ -1027,7 +1016,7 @@
 }
 
 #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub enum Variants {
+pub enum Variants<'a> {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
     Single { index: VariantIdx },
 
@@ -1041,7 +1030,7 @@
         tag: Scalar,
         tag_encoding: TagEncoding,
         tag_field: usize,
-        variants: IndexVec<VariantIdx, Layout>,
+        variants: IndexVec<VariantIdx, Layout<'a>>,
     },
 }
 
@@ -1107,7 +1096,7 @@
 
         // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
         // Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
-        // This is accomplished by prefering enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
+        // This is accomplished by preferring enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
         // Having `None` in niche zero can enable some special optimizations.
         //
         // Bound selection criteria:
@@ -1149,8 +1138,8 @@
     }
 }
 
-#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub struct Layout {
+#[derive(PartialEq, Eq, Hash, HashStable_Generic)]
+pub struct LayoutS<'a> {
     /// Says where the fields are located within the layout.
     pub fields: FieldsShape,
 
@@ -1161,7 +1150,7 @@
     ///
     /// To access all fields of this layout, both `fields` and the fields of the active variant
     /// must be taken into account.
-    pub variants: Variants,
+    pub variants: Variants<'a>,
 
     /// The `abi` defines how this data is passed between functions, and it defines
     /// value restrictions via `valid_range`.
@@ -1180,12 +1169,12 @@
     pub size: Size,
 }
 
-impl Layout {
+impl<'a> LayoutS<'a> {
     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
         let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
         let size = scalar.value.size(cx);
         let align = scalar.value.align(cx);
-        Layout {
+        LayoutS {
             variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Primitive,
             abi: Abi::Scalar(scalar),
@@ -1196,6 +1185,59 @@
     }
 }
 
+impl<'a> fmt::Debug for LayoutS<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // This is how `Layout` used to print before it become
+        // `Interned<LayoutS>`. We print it like this to avoid having to update
+        // expected output in a lot of tests.
+        f.debug_struct("Layout")
+            .field("fields", &self.fields)
+            .field("variants", &self.variants)
+            .field("abi", &self.abi)
+            .field("largest_niche", &self.largest_niche)
+            .field("align", &self.align)
+            .field("size", &self.size)
+            .finish()
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
+#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
+pub struct Layout<'a>(pub Interned<'a, LayoutS<'a>>);
+
+impl<'a> fmt::Debug for Layout<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // See comment on `<LayoutS as Debug>::fmt` above.
+        self.0.0.fmt(f)
+    }
+}
+
+impl<'a> Layout<'a> {
+    pub fn fields(self) -> &'a FieldsShape {
+        &self.0.0.fields
+    }
+
+    pub fn variants(self) -> &'a Variants<'a> {
+        &self.0.0.variants
+    }
+
+    pub fn abi(self) -> Abi {
+        self.0.0.abi
+    }
+
+    pub fn largest_niche(self) -> Option<Niche> {
+        self.0.0.largest_niche
+    }
+
+    pub fn align(self) -> AbiAndPrefAlign {
+        self.0.0.align
+    }
+
+    pub fn size(self) -> Size {
+        self.0.0.size
+    }
+}
+
 /// The layout of a type, alongside the type itself.
 /// Provides various type traversal APIs (e.g., recursing into fields).
 ///
@@ -1206,13 +1248,13 @@
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)]
 pub struct TyAndLayout<'a, Ty> {
     pub ty: Ty,
-    pub layout: &'a Layout,
+    pub layout: Layout<'a>,
 }
 
 impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
-    type Target = &'a Layout;
-    fn deref(&self) -> &&'a Layout {
-        &self.layout
+    type Target = &'a LayoutS<'a>;
+    fn deref(&self) -> &&'a LayoutS<'a> {
+        &self.layout.0.0
     }
 }
 
diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs
index d184ad4..fba8cc6 100644
--- a/compiler/rustc_target/src/asm/aarch64.rs
+++ b/compiler/rustc_target/src/asm/aarch64.rs
@@ -1,5 +1,5 @@
 use super::{InlineAsmArch, InlineAsmType};
-use crate::spec::Target;
+use crate::spec::{RelocModel, Target};
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_macros::HashStable_Generic;
 use rustc_span::Symbol;
@@ -64,7 +64,7 @@
         match self {
             Self::reg => types! { _: I8, I16, I32, I64, F32, F64; },
             Self::vreg | Self::vreg_low16 => types! {
-                fp: I8, I16, I32, I64, F32, F64,
+                neon: I8, I16, I32, I64, F32, F64,
                     VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1),
                     VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
             },
@@ -73,17 +73,18 @@
     }
 }
 
-pub fn reserved_x18(
+pub fn target_reserves_x18(target: &Target) -> bool {
+    target.os == "android" || target.is_like_fuchsia || target.is_like_osx || target.is_like_windows
+}
+
+fn reserved_x18(
     _arch: InlineAsmArch,
+    _reloc_model: RelocModel,
     _target_features: &FxHashSet<Symbol>,
     target: &Target,
     _is_clobber: bool,
 ) -> Result<(), &'static str> {
-    if target.os == "android"
-        || target.is_like_fuchsia
-        || target.is_like_osx
-        || target.is_like_windows
-    {
+    if target_reserves_x18(target) {
         Err("x18 is a reserved register on this target")
     } else {
         Ok(())
diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs
index b2d5bb3..aaa6323 100644
--- a/compiler/rustc_target/src/asm/arm.rs
+++ b/compiler/rustc_target/src/asm/arm.rs
@@ -1,5 +1,5 @@
 use super::{InlineAsmArch, InlineAsmType};
-use crate::spec::Target;
+use crate::spec::{RelocModel, Target};
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_macros::HashStable_Generic;
 use rustc_span::{sym, Symbol};
@@ -50,9 +50,12 @@
         match self {
             Self::reg => types! { _: I8, I16, I32, F32; },
             Self::sreg | Self::sreg_low16 => types! { vfp2: I32, F32; },
-            Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! {
+            Self::dreg_low16 | Self::dreg_low8 => types! {
                 vfp2: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
             },
+            Self::dreg => types! {
+                d32: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
+            },
             Self::qreg | Self::qreg_low8 | Self::qreg_low4 => types! {
                 neon: VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4);
             },
@@ -67,11 +70,12 @@
 
 fn frame_pointer_r11(
     arch: InlineAsmArch,
+    reloc_model: RelocModel,
     target_features: &FxHashSet<Symbol>,
     target: &Target,
     is_clobber: bool,
 ) -> Result<(), &'static str> {
-    not_thumb1(arch, target_features, target, is_clobber)?;
+    not_thumb1(arch, reloc_model, target_features, target, is_clobber)?;
 
     if !frame_pointer_is_r7(target_features, target) {
         Err("the frame pointer (r11) cannot be used as an operand for inline asm")
@@ -82,6 +86,7 @@
 
 fn frame_pointer_r7(
     _arch: InlineAsmArch,
+    _reloc_model: RelocModel,
     target_features: &FxHashSet<Symbol>,
     target: &Target,
     _is_clobber: bool,
@@ -95,6 +100,7 @@
 
 fn not_thumb1(
     _arch: InlineAsmArch,
+    _reloc_model: RelocModel,
     target_features: &FxHashSet<Symbol>,
     _target: &Target,
     is_clobber: bool,
@@ -111,18 +117,18 @@
 
 fn reserved_r9(
     arch: InlineAsmArch,
+    reloc_model: RelocModel,
     target_features: &FxHashSet<Symbol>,
     target: &Target,
     is_clobber: bool,
 ) -> Result<(), &'static str> {
-    not_thumb1(arch, target_features, target, is_clobber)?;
+    not_thumb1(arch, reloc_model, target_features, target, is_clobber)?;
 
-    // We detect this using the reserved-r9 feature instead of using the target
-    // because the relocation model can be changed with compiler options.
-    if target_features.contains(&sym::reserved_r9) {
-        Err("the RWPI static base register (r9) cannot be used as an operand for inline asm")
-    } else {
-        Ok(())
+    match reloc_model {
+        RelocModel::Rwpi | RelocModel::RopiRwpi => {
+            Err("the RWPI static base register (r9) cannot be used as an operand for inline asm")
+        }
+        _ => Ok(()),
     }
 }
 
diff --git a/compiler/rustc_target/src/asm/bpf.rs b/compiler/rustc_target/src/asm/bpf.rs
index b4d982f..3b03766 100644
--- a/compiler/rustc_target/src/asm/bpf.rs
+++ b/compiler/rustc_target/src/asm/bpf.rs
@@ -1,7 +1,6 @@
-use super::{InlineAsmArch, InlineAsmType, Target};
-use rustc_data_structures::stable_set::FxHashSet;
+use super::{InlineAsmArch, InlineAsmType};
 use rustc_macros::HashStable_Generic;
-use rustc_span::{sym, Symbol};
+use rustc_span::Symbol;
 use std::fmt;
 
 def_reg_class! {
@@ -43,19 +42,6 @@
     }
 }
 
-fn only_alu32(
-    _arch: InlineAsmArch,
-    target_features: &FxHashSet<Symbol>,
-    _target: &Target,
-    _is_clobber: bool,
-) -> Result<(), &'static str> {
-    if !target_features.contains(&sym::alu32) {
-        Err("register can't be used without the `alu32` target feature")
-    } else {
-        Ok(())
-    }
-}
-
 def_regs! {
     Bpf BpfInlineAsmReg BpfInlineAsmRegClass {
         r0: reg = ["r0"],
@@ -68,16 +54,16 @@
         r7: reg = ["r7"],
         r8: reg = ["r8"],
         r9: reg = ["r9"],
-        w0: wreg = ["w0"] % only_alu32,
-        w1: wreg = ["w1"] % only_alu32,
-        w2: wreg = ["w2"] % only_alu32,
-        w3: wreg = ["w3"] % only_alu32,
-        w4: wreg = ["w4"] % only_alu32,
-        w5: wreg = ["w5"] % only_alu32,
-        w6: wreg = ["w6"] % only_alu32,
-        w7: wreg = ["w7"] % only_alu32,
-        w8: wreg = ["w8"] % only_alu32,
-        w9: wreg = ["w9"] % only_alu32,
+        w0: wreg = ["w0"],
+        w1: wreg = ["w1"],
+        w2: wreg = ["w2"],
+        w3: wreg = ["w3"],
+        w4: wreg = ["w4"],
+        w5: wreg = ["w5"],
+        w6: wreg = ["w6"],
+        w7: wreg = ["w7"],
+        w8: wreg = ["w8"],
+        w9: wreg = ["w9"],
 
         #error = ["r10", "w10"] =>
             "the stack pointer cannot be used as an operand for inline asm",
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index fd95b03..5bc4b56 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -1,5 +1,5 @@
-use crate::abi::Size;
 use crate::spec::Target;
+use crate::{abi::Size, spec::RelocModel};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_macros::HashStable_Generic;
 use rustc_span::Symbol;
@@ -25,7 +25,7 @@
                 }
             }
 
-            pub fn parse(_arch: super::InlineAsmArch, name: rustc_span::Symbol) -> Result<Self, &'static str> {
+            pub fn parse(name: rustc_span::Symbol) -> Result<Self, &'static str> {
                 match name {
                     $(
                         rustc_span::sym::$class => Ok(Self::$class),
@@ -79,19 +79,10 @@
                 }
             }
 
-            pub fn parse(
-                _arch: super::InlineAsmArch,
-                _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
-                _target: &crate::spec::Target,
-                _is_clobber: bool,
-                name: &str,
-            ) -> Result<Self, &'static str> {
+            pub fn parse(name: &str) -> Result<Self, &'static str> {
                 match name {
                     $(
-                        $($alias)|* | $reg_name => {
-                            $($filter(_arch, _target_features, _target, _is_clobber)?;)?
-                            Ok(Self::$reg)
-                        }
+                        $($alias)|* | $reg_name => Ok(Self::$reg),
                     )*
                     $(
                         $($bad_reg)|* => Err($error),
@@ -99,10 +90,34 @@
                     _ => Err("unknown register"),
                 }
             }
+
+            pub fn validate(self,
+                _arch: super::InlineAsmArch,
+                _reloc_model: crate::spec::RelocModel,
+                _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
+                _target: &crate::spec::Target,
+                _is_clobber: bool,
+            ) -> Result<(), &'static str> {
+                match self {
+                    $(
+                        Self::$reg => {
+                            $($filter(
+                                _arch,
+                                _reloc_model,
+                                _target_features,
+                                _target,
+                                _is_clobber
+                            )?;)?
+                            Ok(())
+                        }
+                    )*
+                }
+            }
         }
 
         pub(super) fn fill_reg_map(
             _arch: super::InlineAsmArch,
+            _reloc_model: crate::spec::RelocModel,
             _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
             _target: &crate::spec::Target,
             _map: &mut rustc_data_structures::fx::FxHashMap<
@@ -113,7 +128,7 @@
             #[allow(unused_imports)]
             use super::{InlineAsmReg, InlineAsmRegClass};
             $(
-                if $($filter(_arch, _target_features, _target, false).is_ok() &&)? true {
+                if $($filter(_arch, _reloc_model, _target_features, _target, false).is_ok() &&)? true {
                     if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
                         set.insert(InlineAsmReg::$arch($arch_reg::$reg));
                     }
@@ -295,94 +310,60 @@
         }
     }
 
-    pub fn parse(
-        arch: InlineAsmArch,
-        target_features: &FxHashSet<Symbol>,
-        target: &Target,
-        is_clobber: bool,
-        name: Symbol,
-    ) -> Result<Self, &'static str> {
+    pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
         // FIXME: use direct symbol comparison for register names
         // Use `Symbol::as_str` instead of `Symbol::with` here because `has_feature` may access `Symbol`.
         let name = name.as_str();
         Ok(match arch {
-            InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
-                Self::X86(X86InlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
+            InlineAsmArch::X86 | InlineAsmArch::X86_64 => Self::X86(X86InlineAsmReg::parse(name)?),
+            InlineAsmArch::Arm => Self::Arm(ArmInlineAsmReg::parse(name)?),
+            InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmReg::parse(name)?),
+            InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
+                Self::RiscV(RiscVInlineAsmReg::parse(name)?)
             }
-            InlineAsmArch::Arm => {
-                Self::Arm(ArmInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
+            InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmReg::parse(name)?),
+            InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
+                Self::PowerPC(PowerPCInlineAsmReg::parse(name)?)
             }
-            InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => Self::RiscV(
-                RiscVInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?,
-            ),
-            InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => Self::PowerPC(
-                PowerPCInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?,
-            ),
-            InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::Mips | InlineAsmArch::Mips64 => Self::Mips(MipsInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => Self::Wasm(WasmInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::Bpf => {
-                Self::Bpf(BpfInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
+            InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmReg::parse(name)?),
+            InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
+                Self::Mips(MipsInlineAsmReg::parse(name)?)
             }
-            InlineAsmArch::Avr => {
-                Self::Avr(AvrInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
+            InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(name)?),
+            InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(name)?),
+            InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
+                Self::Wasm(WasmInlineAsmReg::parse(name)?)
             }
-            InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
+            InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmReg::parse(name)?),
+            InlineAsmArch::Avr => Self::Avr(AvrInlineAsmReg::parse(name)?),
+            InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmReg::parse(name)?),
         })
     }
 
+    pub fn validate(
+        self,
+        arch: InlineAsmArch,
+        reloc_model: RelocModel,
+        target_features: &FxHashSet<Symbol>,
+        target: &Target,
+        is_clobber: bool,
+    ) -> Result<(), &'static str> {
+        match self {
+            Self::X86(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Arm(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::AArch64(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::RiscV(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::PowerPC(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Hexagon(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::S390x(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Err => unreachable!(),
+        }
+    }
+
     // NOTE: This function isn't used at the moment, but is needed to support
     // falling back to an external assembler.
     pub fn emit(
@@ -584,29 +565,29 @@
     pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
         Ok(match arch {
             InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
-                Self::X86(X86InlineAsmRegClass::parse(arch, name)?)
+                Self::X86(X86InlineAsmRegClass::parse(name)?)
             }
-            InlineAsmArch::Arm => Self::Arm(ArmInlineAsmRegClass::parse(arch, name)?),
-            InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::Arm => Self::Arm(ArmInlineAsmRegClass::parse(name)?),
+            InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmRegClass::parse(name)?),
             InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
-                Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?)
+                Self::RiscV(RiscVInlineAsmRegClass::parse(name)?)
             }
-            InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(name)?),
             InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
-                Self::PowerPC(PowerPCInlineAsmRegClass::parse(arch, name)?)
+                Self::PowerPC(PowerPCInlineAsmRegClass::parse(name)?)
             }
-            InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(name)?),
             InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
-                Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
+                Self::Mips(MipsInlineAsmRegClass::parse(name)?)
             }
-            InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(arch, name)?),
-            InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(name)?),
+            InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(name)?),
             InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
-                Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?)
+                Self::Wasm(WasmInlineAsmRegClass::parse(name)?)
             }
-            InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?),
-            InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(arch, name)?),
-            InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(name)?),
+            InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(name)?),
+            InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmRegClass::parse(name)?),
         })
     }
 
@@ -749,78 +730,79 @@
 // falling back to an external assembler.
 pub fn allocatable_registers(
     arch: InlineAsmArch,
+    reloc_model: RelocModel,
     target_features: &FxHashSet<Symbol>,
     target: &crate::spec::Target,
 ) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> {
     match arch {
         InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
             let mut map = x86::regclass_map();
-            x86::fill_reg_map(arch, target_features, target, &mut map);
+            x86::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Arm => {
             let mut map = arm::regclass_map();
-            arm::fill_reg_map(arch, target_features, target, &mut map);
+            arm::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::AArch64 => {
             let mut map = aarch64::regclass_map();
-            aarch64::fill_reg_map(arch, target_features, target, &mut map);
+            aarch64::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
             let mut map = riscv::regclass_map();
-            riscv::fill_reg_map(arch, target_features, target, &mut map);
+            riscv::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Nvptx64 => {
             let mut map = nvptx::regclass_map();
-            nvptx::fill_reg_map(arch, target_features, target, &mut map);
+            nvptx::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
             let mut map = powerpc::regclass_map();
-            powerpc::fill_reg_map(arch, target_features, target, &mut map);
+            powerpc::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Hexagon => {
             let mut map = hexagon::regclass_map();
-            hexagon::fill_reg_map(arch, target_features, target, &mut map);
+            hexagon::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
             let mut map = mips::regclass_map();
-            mips::fill_reg_map(arch, target_features, target, &mut map);
+            mips::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::S390x => {
             let mut map = s390x::regclass_map();
-            s390x::fill_reg_map(arch, target_features, target, &mut map);
+            s390x::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::SpirV => {
             let mut map = spirv::regclass_map();
-            spirv::fill_reg_map(arch, target_features, target, &mut map);
+            spirv::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
             let mut map = wasm::regclass_map();
-            wasm::fill_reg_map(arch, target_features, target, &mut map);
+            wasm::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Bpf => {
             let mut map = bpf::regclass_map();
-            bpf::fill_reg_map(arch, target_features, target, &mut map);
+            bpf::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Avr => {
             let mut map = avr::regclass_map();
-            avr::fill_reg_map(arch, target_features, target, &mut map);
+            avr::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Msp430 => {
             let mut map = msp430::regclass_map();
-            msp430::fill_reg_map(arch, target_features, target, &mut map);
+            msp430::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
     }
@@ -853,7 +835,6 @@
     /// clobber ABIs for the target.
     pub fn parse(
         arch: InlineAsmArch,
-        target_features: &FxHashSet<Symbol>,
         target: &Target,
         name: Symbol,
     ) -> Result<Self, &'static [&'static str]> {
@@ -877,13 +858,11 @@
                 _ => Err(&["C", "system", "efiapi", "aapcs"]),
             },
             InlineAsmArch::AArch64 => match name {
-                "C" | "system" | "efiapi" => {
-                    Ok(if aarch64::reserved_x18(arch, target_features, target, true).is_err() {
-                        InlineAsmClobberAbi::AArch64NoX18
-                    } else {
-                        InlineAsmClobberAbi::AArch64
-                    })
-                }
+                "C" | "system" | "efiapi" => Ok(if aarch64::target_reserves_x18(target) {
+                    InlineAsmClobberAbi::AArch64NoX18
+                } else {
+                    InlineAsmClobberAbi::AArch64
+                }),
                 _ => Err(&["C", "system", "efiapi"]),
             },
             InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs
index e145ba8..987bf97 100644
--- a/compiler/rustc_target/src/asm/riscv.rs
+++ b/compiler/rustc_target/src/asm/riscv.rs
@@ -1,5 +1,5 @@
 use super::{InlineAsmArch, InlineAsmType};
-use crate::spec::Target;
+use crate::spec::{RelocModel, Target};
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_macros::HashStable_Generic;
 use rustc_span::{sym, Symbol};
@@ -54,6 +54,7 @@
 
 fn not_e(
     _arch: InlineAsmArch,
+    _reloc_model: RelocModel,
     target_features: &FxHashSet<Symbol>,
     _target: &Target,
     _is_clobber: bool,
diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs
index a8ee80e..7c136a4 100644
--- a/compiler/rustc_target/src/asm/x86.rs
+++ b/compiler/rustc_target/src/asm/x86.rs
@@ -1,5 +1,5 @@
 use super::{InlineAsmArch, InlineAsmType};
-use crate::spec::Target;
+use crate::spec::{RelocModel, Target};
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_macros::HashStable_Generic;
 use rustc_span::Symbol;
@@ -139,6 +139,7 @@
 
 fn x86_64_only(
     arch: InlineAsmArch,
+    _reloc_model: RelocModel,
     _target_features: &FxHashSet<Symbol>,
     _target: &Target,
     _is_clobber: bool,
@@ -152,6 +153,7 @@
 
 fn high_byte(
     arch: InlineAsmArch,
+    _reloc_model: RelocModel,
     _target_features: &FxHashSet<Symbol>,
     _target: &Target,
     _is_clobber: bool,
@@ -164,6 +166,7 @@
 
 fn rbx_reserved(
     arch: InlineAsmArch,
+    _reloc_model: RelocModel,
     _target_features: &FxHashSet<Symbol>,
     _target: &Target,
     _is_clobber: bool,
@@ -179,6 +182,7 @@
 
 fn esi_reserved(
     arch: InlineAsmArch,
+    _reloc_model: RelocModel,
     _target_features: &FxHashSet<Symbol>,
     _target: &Target,
     _is_clobber: bool,
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index b18d17c..e9ef71e 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -8,12 +8,14 @@
 //! LLVM.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(bool_to_option)]
-#![feature(nll)]
-#![feature(never_type)]
 #![feature(associated_type_bounds)]
+#![feature(bool_to_option)]
 #![feature(exhaustive_patterns)]
+#![feature(let_else)]
 #![feature(min_specialization)]
+#![feature(never_type)]
+#![feature(nll)]
+#![feature(rustc_attrs)]
 #![feature(step_trait)]
 
 use std::iter::FromIterator;
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
index f01ff02..86f76fdb 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
@@ -2,14 +2,14 @@
 
 pub fn target() -> Target {
     let mut base = super::apple_base::opts("macos");
-    base.cpu = "apple-a14".to_string();
+    base.cpu = "apple-a14".into();
     base.max_atomic_width = Some(128);
 
     // FIXME: The leak sanitizer currently fails the tests, see #88132.
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
 
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]);
-    base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".into(), "arm64".into()]);
+    base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
 
     // Clang automatically chooses a more specific target based on
     // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
@@ -17,12 +17,12 @@
     let llvm_target = super::apple_base::macos_llvm_target("arm64");
 
     Target {
-        llvm_target,
+        llvm_target: llvm_target.into(),
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
-        arch: "aarch64".to_string(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            mcount: "\u{1}mcount".to_string(),
+            mcount: "\u{1}mcount".into(),
             frame_pointer: FramePointer::NonLeaf,
             ..base
         },
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
index 6468419..beb9042 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
@@ -10,12 +10,12 @@
     let llvm_target = super::apple_base::ios_llvm_target(arch);
 
     Target {
-        llvm_target,
+        llvm_target: llvm_target.into(),
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
-        arch: "aarch64".to_string(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            features: "+neon,+fp-armv8,+apple-a7".to_string(),
+            features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             forces_embed_bitcode: true,
             frame_pointer: FramePointer::NonLeaf,
@@ -29,7 +29,7 @@
                 -target-abi\0\
                 darwinpcs\0\
                 -Os\0"
-                .to_string(),
+                .into(),
             ..opts("ios", Arch::Arm64)
         },
     }
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
index d16328f..57634cb 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -3,12 +3,12 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "arm64-apple-ios14.0-macabi".to_string(),
+        llvm_target: "arm64-apple-ios14.0-macabi".into(),
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
-        arch: "aarch64".to_string(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            features: "+neon,+fp-armv8,+apple-a12".to_string(),
+            features: "+neon,+fp-armv8,+apple-a12".into(),
             max_atomic_width: Some(128),
             forces_embed_bitcode: true,
             frame_pointer: FramePointer::NonLeaf,
@@ -20,7 +20,7 @@
                 -emit-obj\0\
                 -disable-llvm-passes\0\
                 -Os\0"
-                .to_string(),
+                .into(),
             ..opts("ios", Arch::Arm64_macabi)
         },
     }
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
index 07b3453..b4e135f 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
@@ -12,12 +12,12 @@
     let llvm_target = super::apple_base::ios_sim_llvm_target(arch);
 
     Target {
-        llvm_target: llvm_target,
+        llvm_target: llvm_target.into(),
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
-        arch: "aarch64".to_string(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            features: "+neon,+fp-armv8,+apple-a7".to_string(),
+            features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             forces_embed_bitcode: true,
             frame_pointer: FramePointer::NonLeaf,
@@ -31,7 +31,7 @@
                 -target-abi\0\
                 darwinpcs\0\
                 -Os\0"
-                .to_string(),
+                .into(),
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
index b4bd72a..2e31d16 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
@@ -3,12 +3,12 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "arm64-apple-tvos".to_string(),
+        llvm_target: "arm64-apple-tvos".into(),
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
-        arch: "aarch64".to_string(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            features: "+neon,+fp-armv8,+apple-a7".to_string(),
+            features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             forces_embed_bitcode: true,
             frame_pointer: FramePointer::NonLeaf,
diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
index a393858..9bce82a 100644
--- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
@@ -3,14 +3,14 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "aarch64_be-unknown-linux-gnu".to_string(),
+        llvm_target: "aarch64_be-unknown-linux-gnu".into(),
         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(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            features: "+outline-atomics".to_string(),
+            features: "+outline-atomics".into(),
             max_atomic_width: Some(128),
-            mcount: "\u{1}_mcount".to_string(),
+            mcount: "\u{1}_mcount".into(),
             endian: Endian::Big,
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
index e75100f..c9ceb55 100644
--- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -6,14 +6,14 @@
     base.max_atomic_width = Some(128);
 
     Target {
-        llvm_target: "aarch64_be-unknown-linux-gnu_ilp32".to_string(),
+        llvm_target: "aarch64_be-unknown-linux-gnu_ilp32".into(),
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
-        arch: "aarch64".to_string(),
+        data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            abi: "ilp32".to_string(),
-            features: "+outline-atomics".to_string(),
-            mcount: "\u{1}_mcount".to_string(),
+            abi: "ilp32".into(),
+            features: "+outline-atomics".into(),
+            mcount: "\u{1}_mcount".into(),
             endian: Endian::Big,
             ..base
         },
diff --git a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs
index 05e0c65..4634433 100644
--- a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs
@@ -2,10 +2,10 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "aarch64-fuchsia".to_string(),
+        llvm_target: "aarch64-fuchsia".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
             max_atomic_width: Some(128),
             supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI,
diff --git a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs
index 61e3be6..6ea9ae2 100644
--- a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs
+++ b/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs
@@ -3,13 +3,13 @@
 pub fn target() -> Target {
     let base = super::solid_base::opts("asp3");
     Target {
-        llvm_target: "aarch64-unknown-none".to_string(),
+        llvm_target: "aarch64-unknown-none".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            linker: Some("aarch64-kmc-elf-gcc".to_owned()),
-            features: "+neon,+fp-armv8".to_string(),
+            linker: Some("aarch64-kmc-elf-gcc".into()),
+            features: "+neon,+fp-armv8".into(),
             relocation_model: RelocModel::Static,
             disable_redzone: true,
             max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/aarch64_linux_android.rs
index 5692925..5e31859 100644
--- a/compiler/rustc_target/src/spec/aarch64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/aarch64_linux_android.rs
@@ -5,18 +5,19 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "aarch64-linux-android".to_string(),
+        llvm_target: "aarch64-linux-android".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
             max_atomic_width: Some(128),
             // As documented in https://developer.android.com/ndk/guides/cpu-features.html
             // the neon (ASIMD) and FP must exist on all android aarch64 targets.
-            features: "+neon,+fp-armv8".to_string(),
+            features: "+neon,+fp-armv8".into(),
             supported_sanitizers: SanitizerSet::CFI
                 | SanitizerSet::HWADDRESS
-                | SanitizerSet::MEMTAG,
+                | SanitizerSet::MEMTAG
+                | SanitizerSet::ADDRESS,
             ..super::android_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs
index a9a0977..856ec4f 100644
--- a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs
@@ -3,13 +3,13 @@
 pub fn target() -> Target {
     let mut base = super::windows_msvc_base::opts();
     base.max_atomic_width = Some(64);
-    base.features = "+neon,+fp-armv8".to_string();
+    base.features = "+neon,+fp-armv8".into();
 
     Target {
-        llvm_target: "aarch64-pc-windows-msvc".to_string(),
+        llvm_target: "aarch64-pc-windows-msvc".into(),
         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(),
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
index 03ee7ba..2f39c48 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
@@ -2,10 +2,10 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "aarch64-unknown-freebsd".to_string(),
+        llvm_target: "aarch64-unknown-freebsd".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
             max_atomic_width: Some(128),
             supported_sanitizers: SanitizerSet::ADDRESS
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
index f8e1e1b..1d7269c 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
@@ -3,13 +3,13 @@
 pub fn target() -> Target {
     let mut base = super::hermit_base::opts();
     base.max_atomic_width = Some(128);
-    base.features = "+strict-align,+neon,+fp-armv8".to_string();
+    base.features = "+strict-align,+neon,+fp-armv8".into();
 
     Target {
-        llvm_target: "aarch64-unknown-hermit".to_string(),
+        llvm_target: "aarch64-unknown-hermit".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
index 974a5b8..3006044 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
@@ -2,13 +2,13 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "aarch64-unknown-linux-gnu".to_string(),
+        llvm_target: "aarch64-unknown-linux-gnu".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            features: "+outline-atomics".to_string(),
-            mcount: "\u{1}_mcount".to_string(),
+            features: "+outline-atomics".into(),
+            mcount: "\u{1}_mcount".into(),
             max_atomic_width: Some(128),
             supported_sanitizers: SanitizerSet::ADDRESS
                 | SanitizerSet::CFI
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
index 1c931d5..63023df 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "aarch64-unknown-linux-gnu_ilp32".to_string(),
+        llvm_target: "aarch64-unknown-linux-gnu_ilp32".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
-        arch: "aarch64".to_string(),
+        data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            abi: "ilp32".to_string(),
-            features: "+outline-atomics".to_string(),
+            abi: "ilp32".into(),
+            features: "+outline-atomics".into(),
             max_atomic_width: Some(128),
-            mcount: "\u{1}_mcount".to_string(),
+            mcount: "\u{1}_mcount".into(),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
index 6a16b4c..002d0da 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
@@ -5,10 +5,10 @@
     base.max_atomic_width = Some(128);
 
     Target {
-        llvm_target: "aarch64-unknown-linux-musl".to_string(),
+        llvm_target: "aarch64-unknown-linux-musl".into(),
         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 { mcount: "\u{1}_mcount".to_string(), ..base },
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
+        options: TargetOptions { mcount: "\u{1}_mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs
index 4042028..703f750 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs
@@ -2,12 +2,12 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "aarch64-unknown-netbsd".to_string(),
+        llvm_target: "aarch64-unknown-netbsd".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions {
-            mcount: "__mcount".to_string(),
+            mcount: "__mcount".into(),
             max_atomic_width: Some(128),
             ..super::netbsd_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
index 9d36527..2c7834c 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
@@ -11,8 +11,8 @@
 pub fn target() -> Target {
     let opts = TargetOptions {
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-        linker: Some("rust-lld".to_owned()),
-        features: "+strict-align,+neon,+fp-armv8".to_string(),
+        linker: Some("rust-lld".into()),
+        features: "+strict-align,+neon,+fp-armv8".into(),
         executables: true,
         relocation_model: RelocModel::Static,
         disable_redzone: true,
@@ -21,10 +21,10 @@
         ..Default::default()
     };
     Target {
-        llvm_target: "aarch64-unknown-none".to_string(),
+        llvm_target: "aarch64-unknown-none".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: opts,
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none_hermitkernel.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none_hermitkernel.rs
deleted file mode 100644
index 6e9d6c6..0000000
--- a/compiler/rustc_target/src/spec/aarch64_unknown_none_hermitkernel.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-use crate::spec::Target;
-
-pub fn target() -> Target {
-    let mut base = super::hermit_kernel_base::opts();
-    base.max_atomic_width = Some(128);
-    base.abi = "softfloat".to_string();
-    base.features = "+strict-align,-neon,-fp-armv8".to_string();
-
-    Target {
-        llvm_target: "aarch64-unknown-hermit".to_string(),
-        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: base,
-    }
-}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
index fa93ca8..1b6525a 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
@@ -10,10 +10,10 @@
 
 pub fn target() -> Target {
     let opts = TargetOptions {
-        abi: "softfloat".to_string(),
+        abi: "softfloat".into(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-        linker: Some("rust-lld".to_owned()),
-        features: "+strict-align,-neon,-fp-armv8".to_string(),
+        linker: Some("rust-lld".into()),
+        features: "+strict-align,-neon,-fp-armv8".into(),
         executables: true,
         relocation_model: RelocModel::Static,
         disable_redzone: true,
@@ -22,10 +22,10 @@
         ..Default::default()
     };
     Target {
-        llvm_target: "aarch64-unknown-none".to_string(),
+        llvm_target: "aarch64-unknown-none".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: opts,
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs
index 193f981..3d99040 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs
@@ -2,10 +2,10 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "aarch64-unknown-openbsd".to_string(),
+        llvm_target: "aarch64-unknown-openbsd".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions { max_atomic_width: Some(128), ..super::openbsd_base::opts() },
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs
index b9c9325..6c9be4c 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs
@@ -5,10 +5,10 @@
     base.max_atomic_width = Some(128);
 
     Target {
-        llvm_target: "aarch64-unknown-redox".to_string(),
+        llvm_target: "aarch64-unknown-redox".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
index 20c528d..965b254 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
@@ -9,7 +9,7 @@
 
     base.max_atomic_width = Some(64);
 
-    let pre_link_args_msvc = vec!["/machine:arm64".to_string()];
+    let pre_link_args_msvc = vec!["/machine:arm64".into()];
 
     base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone());
     base.pre_link_args
@@ -18,10 +18,10 @@
         .extend(pre_link_args_msvc);
 
     Target {
-        llvm_target: "aarch64-unknown-windows".to_string(),
+        llvm_target: "aarch64-unknown-windows".into(),
         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(),
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs
index db4eb20..54247fd 100644
--- a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs
@@ -5,10 +5,10 @@
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "aarch64-pc-windows-msvc".to_string(),
+        llvm_target: "aarch64-pc-windows-msvc".into(),
         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(),
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs
index 6614006..e118553 100644
--- a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs
@@ -2,10 +2,10 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "aarch64-unknown-linux-gnu".to_string(),
+        llvm_target: "aarch64-unknown-linux-gnu".into(),
         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(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
         options: TargetOptions { max_atomic_width: Some(128), ..super::vxworks_base::opts() },
     }
 }
diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs
index dc14d26..c2b9d69 100644
--- a/compiler/rustc_target/src/spec/android_base.rs
+++ b/compiler/rustc_target/src/spec/android_base.rs
@@ -2,7 +2,7 @@
 
 pub fn opts() -> TargetOptions {
     let mut base = super::linux_base::opts();
-    base.os = "android".to_string();
+    base.os = "android".into();
     base.dwarf_version = Some(2);
     base.position_independent_executables = true;
     base.has_thread_local = false;
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index a4488f6..238d3f8 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -1,8 +1,8 @@
-use std::env;
+use std::{borrow::Cow, env};
 
-use crate::spec::{FramePointer, LldFlavor, SplitDebuginfo, TargetOptions};
+use crate::spec::{cvs, FramePointer, LldFlavor, SplitDebuginfo, TargetOptions};
 
-pub fn opts(os: &str) -> TargetOptions {
+pub fn opts(os: &'static str) -> TargetOptions {
     // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
     // either the linker will complain if it is used or the binary will end up
     // segfaulting at runtime when run on 10.6. Rust by default supports macOS
@@ -19,20 +19,20 @@
     let has_thread_local = macos_deployment_target("x86_64") >= (10, 7);
 
     TargetOptions {
-        os: os.to_string(),
-        vendor: "apple".to_string(),
+        os: os.into(),
+        vendor: "apple".into(),
         // macOS has -dead_strip, which doesn't rely on function_sections
         function_sections: false,
         dynamic_linking: true,
         linker_is_gnu: false,
         executables: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         is_like_osx: true,
         dwarf_version: Some(2),
         frame_pointer: FramePointer::Always,
         has_rpath: true,
-        dll_suffix: ".dylib".to_string(),
-        archive_format: "darwin".to_string(),
+        dll_suffix: ".dylib".into(),
+        archive_format: "darwin".into(),
         has_thread_local,
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
@@ -51,7 +51,7 @@
         // this environment variable too in recent versions.
         //
         // For some more info see the commentary on #47086
-        link_env: vec![("ZERO_AR_DATE".to_string(), "1".to_string())],
+        link_env: Cow::Borrowed(&[(Cow::Borrowed("ZERO_AR_DATE"), Cow::Borrowed("1"))]),
 
         ..Default::default()
     }
@@ -79,19 +79,19 @@
     format!("{}-apple-macosx{}.{}.0", arch, major, minor)
 }
 
-pub fn macos_link_env_remove() -> Vec<String> {
+pub fn macos_link_env_remove() -> Vec<Cow<'static, str>> {
     let mut env_remove = Vec::with_capacity(2);
     // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
     // may occur when we're linking a custom build script while targeting iOS for example.
     if let Ok(sdkroot) = env::var("SDKROOT") {
         if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") {
-            env_remove.push("SDKROOT".to_string())
+            env_remove.push("SDKROOT".into())
         }
     }
     // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at
     // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",
     // although this is apparently ignored when using the linker at "/usr/bin/ld".
-    env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".to_string());
+    env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".into());
     env_remove
 }
 
diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs
index 874e9b5..e2d0895 100644
--- a/compiler/rustc_target/src/spec/apple_sdk_base.rs
+++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs
@@ -1,4 +1,5 @@
-use crate::spec::TargetOptions;
+use crate::{spec::cvs, spec::TargetOptions};
+use std::borrow::Cow;
 
 use Arch::*;
 #[allow(non_camel_case_types)]
@@ -14,16 +15,15 @@
     Arm64_sim,
 }
 
-fn target_abi(arch: Arch) -> String {
+fn target_abi(arch: Arch) -> &'static str {
     match arch {
         Armv7 | Armv7s | Arm64 | I386 | X86_64 => "",
         X86_64_macabi | Arm64_macabi => "macabi",
         Arm64_sim => "sim",
     }
-    .to_string()
 }
 
-fn target_cpu(arch: Arch) -> String {
+fn target_cpu(arch: Arch) -> &'static str {
     match arch {
         Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
         Armv7s => "cortex-a9",
@@ -34,22 +34,21 @@
         Arm64_macabi => "apple-a12",
         Arm64_sim => "apple-a12",
     }
-    .to_string()
 }
 
-fn link_env_remove(arch: Arch) -> Vec<String> {
+fn link_env_remove(arch: Arch) -> Cow<'static, [Cow<'static, str>]> {
     match arch {
         Armv7 | Armv7s | Arm64 | I386 | X86_64 | Arm64_sim => {
-            vec!["MACOSX_DEPLOYMENT_TARGET".to_string()]
+            cvs!["MACOSX_DEPLOYMENT_TARGET"]
         }
-        X86_64_macabi | Arm64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
+        X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
     }
 }
 
-pub fn opts(os: &str, arch: Arch) -> TargetOptions {
+pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
     TargetOptions {
-        abi: target_abi(arch),
-        cpu: target_cpu(arch),
+        abi: target_abi(arch).into(),
+        cpu: target_cpu(arch).into(),
         dynamic_linking: false,
         executables: true,
         link_env_remove: link_env_remove(arch),
diff --git a/compiler/rustc_target/src/spec/arm_linux_androideabi.rs b/compiler/rustc_target/src/spec/arm_linux_androideabi.rs
index 9b5366c..bbf1fa3 100644
--- a/compiler/rustc_target/src/spec/arm_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/arm_linux_androideabi.rs
@@ -1,15 +1,16 @@
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "arm-linux-androideabi".to_string(),
+        llvm_target: "arm-linux-androideabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
+            abi: "eabi".into(),
             // https://developer.android.com/ndk/guides/abis.html#armeabi
-            features: "+strict-align,+v5te".to_string(),
+            features: "+strict-align,+v5te".into(),
+            supported_sanitizers: SanitizerSet::ADDRESS,
             max_atomic_width: Some(32),
             ..super::android_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
index 442f56d..c0f1827 100644
--- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "arm-unknown-linux-gnueabi".to_string(),
+        llvm_target: "arm-unknown-linux-gnueabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
-            features: "+strict-align,+v6".to_string(),
+            abi: "eabi".into(),
+            features: "+strict-align,+v6".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            mcount: "\u{1}__gnu_mcount_nc".into(),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
index 2c12a71..79b8958 100644
--- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
+        llvm_target: "arm-unknown-linux-gnueabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabihf".to_string(),
-            features: "+strict-align,+v6,+vfp2,-d32".to_string(),
+            abi: "eabihf".into(),
+            features: "+strict-align,+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            mcount: "\u{1}__gnu_mcount_nc".into(),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs
index d187dfd..3ef441d 100644
--- a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs
@@ -5,17 +5,17 @@
         // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it
         // to determine the calling convention and float ABI, and it doesn't
         // support the "musleabi" value.
-        llvm_target: "arm-unknown-linux-gnueabi".to_string(),
+        llvm_target: "arm-unknown-linux-gnueabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
+            abi: "eabi".into(),
             // Most of these settings are copied from the arm_unknown_linux_gnueabi
             // target.
-            features: "+strict-align,+v6".to_string(),
+            features: "+strict-align,+v6".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}mcount".to_string(),
+            mcount: "\u{1}mcount".into(),
             ..super::linux_musl_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs
index 3d72734..eb6660d 100644
--- a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs
@@ -5,17 +5,17 @@
         // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
         // uses it to determine the calling convention and float ABI, and it
         // doesn't support the "musleabihf" value.
-        llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
+        llvm_target: "arm-unknown-linux-gnueabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             // Most of these settings are copied from the arm_unknown_linux_gnueabihf
             // target.
-            features: "+strict-align,+v6,+vfp2,-d32".to_string(),
+            features: "+strict-align,+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}mcount".to_string(),
+            mcount: "\u{1}mcount".into(),
             ..super::linux_musl_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
index ed4779c..0cb18f1 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
@@ -6,16 +6,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armebv7r-unknown-none-eabi".to_string(),
+        llvm_target: "armebv7r-unknown-none-eabi".into(),
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
+            abi: "eabi".into(),
             endian: Endian::Big,
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
-            linker: Some("rust-lld".to_owned()),
+            linker: Some("rust-lld".into()),
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
index b60e289..a5b7c12 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
@@ -6,19 +6,19 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armebv7r-unknown-none-eabihf".to_string(),
+        llvm_target: "armebv7r-unknown-none-eabihf".into(),
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             endian: Endian::Big,
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
-            linker: Some("rust-lld".to_owned()),
+            linker: Some("rust-lld".into()),
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
-            features: "+vfp3,-d32,-fp16".to_string(),
+            features: "+vfp3,-d32,-fp16".into(),
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
             // GCC and Clang default to 8 for arm-none here
diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
index f1b193a..1de63a9 100644
--- a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
@@ -2,16 +2,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv4t-unknown-linux-gnueabi".to_string(),
+        llvm_target: "armv4t-unknown-linux-gnueabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
-            features: "+soft-float,+strict-align".to_string(),
+            abi: "eabi".into(),
+            features: "+soft-float,+strict-align".into(),
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
-            mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            mcount: "\u{1}__gnu_mcount_nc".into(),
             has_thumb_interworking: true,
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs
index a6c4f23..b940563 100644
--- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs
@@ -2,16 +2,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv5te-unknown-linux-gnueabi".to_string(),
+        llvm_target: "armv5te-unknown-linux-gnueabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
-            features: "+soft-float,+strict-align".to_string(),
+            abi: "eabi".into(),
+            features: "+soft-float,+strict-align".into(),
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
-            mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            mcount: "\u{1}__gnu_mcount_nc".into(),
             has_thumb_interworking: true,
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs
index de2a350..2530971 100644
--- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs
@@ -6,16 +6,16 @@
         // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
         // uses it to determine the calling convention and float ABI, and LLVM
         // doesn't support the "musleabihf" value.
-        llvm_target: "armv5te-unknown-linux-gnueabi".to_string(),
+        llvm_target: "armv5te-unknown-linux-gnueabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
-            features: "+soft-float,+strict-align".to_string(),
+            abi: "eabi".into(),
+            features: "+soft-float,+strict-align".into(),
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
-            mcount: "\u{1}mcount".to_string(),
+            mcount: "\u{1}mcount".into(),
             has_thumb_interworking: true,
             ..super::linux_musl_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs
index 91b4bd2..a51be10 100644
--- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs
+++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs
@@ -2,16 +2,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv5te-unknown-linux-uclibcgnueabi".to_string(),
+        llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
-            features: "+soft-float,+strict-align".to_string(),
+            abi: "eabi".into(),
+            features: "+soft-float,+strict-align".into(),
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
-            mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            mcount: "\u{1}__gnu_mcount_nc".into(),
             has_thumb_interworking: true,
             ..super::linux_uclibc_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
index ee2f8f6..b7cfccc 100644
--- a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
@@ -2,17 +2,17 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv6-unknown-freebsd-gnueabihf".to_string(),
+        llvm_target: "armv6-unknown-freebsd-gnueabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             // FIXME: change env to "gnu" when cfg_target_abi becomes stable
-            env: "gnueabihf".to_string(),
-            features: "+v6,+vfp2,-d32".to_string(),
+            env: "gnueabihf".into(),
+            features: "+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            mcount: "\u{1}__gnu_mcount_nc".into(),
             ..super::freebsd_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs
index b046819..6e26f68 100644
--- a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs
@@ -2,17 +2,17 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv6-unknown-netbsdelf-eabihf".to_string(),
+        llvm_target: "armv6-unknown-netbsdelf-eabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             // FIXME: remove env when cfg_target_abi becomes stable
-            env: "eabihf".to_string(),
-            features: "+v6,+vfp2,-d32".to_string(),
+            env: "eabihf".into(),
+            features: "+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
-            mcount: "__mcount".to_string(),
+            mcount: "__mcount".into(),
             ..super::netbsd_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
index 3e3a6ac..ffcd1a3 100644
--- a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
+++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkArgs, LinkerFlavor, RelocModel, Target, TargetOptions};
+use crate::spec::{cvs, LinkArgs, LinkerFlavor, RelocModel, Target, TargetOptions};
 
 /// A base target for Nintendo 3DS devices using the devkitARM toolchain.
 ///
@@ -9,34 +9,35 @@
     pre_link_args.insert(
         LinkerFlavor::Gcc,
         vec![
-            "-specs=3dsx.specs".to_string(),
-            "-mtune=mpcore".to_string(),
-            "-mfloat-abi=hard".to_string(),
-            "-mtp=soft".to_string(),
+            "-specs=3dsx.specs".into(),
+            "-mtune=mpcore".into(),
+            "-mfloat-abi=hard".into(),
+            "-mtp=soft".into(),
         ],
     );
 
     Target {
-        llvm_target: "armv6k-none-eabihf".to_string(),
+        llvm_target: "armv6k-none-eabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            os: "horizon".to_string(),
-            env: "newlib".to_string(),
-            vendor: "nintendo".to_string(),
-            abi: "eabihf".to_string(),
+            os: "horizon".into(),
+            env: "newlib".into(),
+            vendor: "nintendo".into(),
+            abi: "eabihf".into(),
             linker_flavor: LinkerFlavor::Gcc,
-            cpu: "mpcore".to_string(),
+            cpu: "mpcore".into(),
             executables: true,
-            families: vec!["unix".to_string()],
-            linker: Some("arm-none-eabi-gcc".to_string()),
+            families: cvs!["unix"],
+            linker: Some("arm-none-eabi-gcc".into()),
             relocation_model: RelocModel::Static,
-            features: "+vfp2".to_string(),
+            features: "+vfp2".into(),
             pre_link_args,
-            exe_suffix: ".elf".to_string(),
+            exe_suffix: ".elf".into(),
             no_default_libraries: false,
+            has_thread_local: true,
             ..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 1f90c78..57fd74a 100644
--- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/armv7_apple_ios.rs
@@ -2,13 +2,15 @@
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
+    let llvm_target = super::apple_base::ios_llvm_target("armv7");
+
     Target {
-        llvm_target: super::apple_base::ios_llvm_target("armv7"),
+        llvm_target: llvm_target.into(),
         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(),
+        data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            features: "+v7,+vfp3,+neon".to_string(),
+            features: "+v7,+vfp3,+neon".into(),
             max_atomic_width: Some(64),
             ..opts("ios", Arch::Armv7)
         },
diff --git a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
index 55956f3..2afd93f 100644
--- a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
 
 // This target if is for the baseline of the Android v7a ABI
 // in thumb mode. It's named armv7-* instead of thumbv7-*
@@ -10,15 +10,16 @@
 
 pub fn target() -> Target {
     let mut base = super::android_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".into());
     Target {
-        llvm_target: "armv7-none-linux-android".to_string(),
+        llvm_target: "armv7-none-linux-android".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
-            features: "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string(),
+            abi: "eabi".into(),
+            features: "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".into(),
+            supported_sanitizers: SanitizerSet::ADDRESS,
             max_atomic_width: Some(64),
             ..base
         },
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs
index fbfb1c2..bc37b62 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs
@@ -2,17 +2,17 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7-unknown-freebsd-gnueabihf".to_string(),
+        llvm_target: "armv7-unknown-freebsd-gnueabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             // FIXME: change env to "gnu" when cfg_target_abi becomes stable
-            env: "gnueabihf".to_string(),
-            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
+            env: "gnueabihf".into(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            mcount: "\u{1}__gnu_mcount_nc".into(),
             ..super::freebsd_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
index 0a3b803..903042d 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
@@ -5,15 +5,15 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7-unknown-linux-gnueabi".to_string(),
+        llvm_target: "armv7-unknown-linux-gnueabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
-            features: "+v7,+thumb2,+soft-float,-neon".to_string(),
+            abi: "eabi".into(),
+            features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            mcount: "\u{1}__gnu_mcount_nc".into(),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs
index 662b81c..e39ea49 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs
@@ -5,16 +5,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
+        llvm_target: "armv7-unknown-linux-gnueabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
-            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            mcount: "\u{1}__gnu_mcount_nc".into(),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs
index c0fd1de..7dae857 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs
@@ -10,16 +10,16 @@
         // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it
         // to determine the calling convention and float ABI, and it doesn't
         // support the "musleabi" value.
-        llvm_target: "armv7-unknown-linux-gnueabi".to_string(),
+        llvm_target: "armv7-unknown-linux-gnueabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            abi: "eabi".to_string(),
-            features: "+v7,+thumb2,+soft-float,-neon".to_string(),
+            abi: "eabi".into(),
+            features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}mcount".to_string(),
+            mcount: "\u{1}mcount".into(),
             ..super::linux_musl_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs
index 67ff799..ba83964 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs
@@ -7,18 +7,18 @@
         // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
         // uses it to determine the calling convention and float ABI, and LLVM
         // doesn't support the "musleabihf" value.
-        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
+        llvm_target: "armv7-unknown-linux-gnueabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
         // target.
         options: TargetOptions {
-            abi: "eabihf".to_string(),
-            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
+            abi: "eabihf".into(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}mcount".to_string(),
+            mcount: "\u{1}mcount".into(),
             ..super::linux_musl_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs
index 7faa8ed..171f670 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs
@@ -6,17 +6,17 @@
 pub fn target() -> Target {
     let base = super::linux_uclibc_base::opts();
     Target {
-        llvm_target: "armv7-unknown-linux-gnueabi".to_string(),
+        llvm_target: "armv7-unknown-linux-gnueabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            features: "+v7,+thumb2,+soft-float,-neon".to_string(),
-            cpu: "generic".to_string(),
+            features: "+v7,+thumb2,+soft-float,-neon".into(),
+            cpu: "generic".into(),
             max_atomic_width: Some(64),
-            mcount: "_mcount".to_string(),
-            abi: "eabi".to_string(),
+            mcount: "_mcount".into(),
+            abi: "eabi".into(),
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs
index d230f77..d3e95a6 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs
@@ -6,18 +6,18 @@
 pub fn target() -> Target {
     let base = super::linux_uclibc_base::opts();
     Target {
-        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
+        llvm_target: "armv7-unknown-linux-gnueabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
-            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
-            cpu: "generic".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
+            cpu: "generic".into(),
             max_atomic_width: Some(64),
-            mcount: "_mcount".to_string(),
-            abi: "eabihf".to_string(),
+            mcount: "_mcount".into(),
+            abi: "eabihf".into(),
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs
index 60a552b..c89ae24 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs
@@ -2,17 +2,17 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7-unknown-netbsdelf-eabihf".to_string(),
+        llvm_target: "armv7-unknown-netbsdelf-eabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             // FIXME: remove env when cfg_target_abi becomes stable
-            env: "eabihf".to_string(),
-            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
+            env: "eabihf".into(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
             max_atomic_width: Some(64),
-            mcount: "__mcount".to_string(),
+            mcount: "__mcount".into(),
             ..super::netbsd_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs
index 27d404b..c1ab901 100644
--- a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs
@@ -2,14 +2,14 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
+        llvm_target: "armv7-unknown-linux-gnueabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
-            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
             max_atomic_width: Some(64),
             ..super::vxworks_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs
index 344c480..b49dc65 100644
--- a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs
@@ -3,13 +3,13 @@
 pub fn target() -> Target {
     let base = super::solid_base::opts("asp3");
     Target {
-        llvm_target: "armv7a-none-eabi".to_string(),
+        llvm_target: "armv7a-none-eabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            linker: Some("arm-kmc-eabi-gcc".to_owned()),
-            features: "+v7,+soft-float,+thumb2,-neon".to_string(),
+            linker: Some("arm-kmc-eabi-gcc".into()),
+            features: "+v7,+soft-float,+thumb2,-neon".into(),
             relocation_model: RelocModel::Static,
             disable_redzone: true,
             max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs
index 3755024..7d30238 100644
--- a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs
@@ -3,13 +3,13 @@
 pub fn target() -> Target {
     let base = super::solid_base::opts("asp3");
     Target {
-        llvm_target: "armv7a-none-eabihf".to_string(),
+        llvm_target: "armv7a-none-eabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            linker: Some("arm-kmc-eabi-gcc".to_owned()),
-            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
+            linker: Some("arm-kmc-eabi-gcc".into()),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
             relocation_model: RelocModel::Static,
             disable_redzone: true,
             max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
index 88040f4..ff64943 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
@@ -18,10 +18,10 @@
 
 pub fn target() -> Target {
     let opts = TargetOptions {
-        abi: "eabi".to_string(),
+        abi: "eabi".into(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-        linker: Some("rust-lld".to_owned()),
-        features: "+v7,+thumb2,+soft-float,-neon,+strict-align".to_string(),
+        linker: Some("rust-lld".into()),
+        features: "+v7,+thumb2,+soft-float,-neon,+strict-align".into(),
         executables: true,
         relocation_model: RelocModel::Static,
         disable_redzone: true,
@@ -32,10 +32,10 @@
         ..Default::default()
     };
     Target {
-        llvm_target: "armv7a-none-eabi".to_string(),
+        llvm_target: "armv7a-none-eabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: opts,
     }
 }
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
index af32484..c0321d0 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
@@ -9,10 +9,10 @@
 
 pub fn target() -> Target {
     let opts = TargetOptions {
-        abi: "eabihf".to_string(),
+        abi: "eabihf".into(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-        linker: Some("rust-lld".to_owned()),
-        features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".to_string(),
+        linker: Some("rust-lld".into()),
+        features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".into(),
         executables: true,
         relocation_model: RelocModel::Static,
         disable_redzone: true,
@@ -24,10 +24,10 @@
         ..Default::default()
     };
     Target {
-        llvm_target: "armv7a-none-eabihf".to_string(),
+        llvm_target: "armv7a-none-eabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: opts,
     }
 }
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
index c0e9709..2c3f79c 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
@@ -5,16 +5,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7r-unknown-none-eabi".to_string(),
+        llvm_target: "armv7r-unknown-none-eabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            abi: "eabi".to_string(),
+            abi: "eabi".into(),
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
-            linker: Some("rust-lld".to_owned()),
+            linker: Some("rust-lld".into()),
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
index b126887..5c82e76 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
@@ -5,19 +5,19 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7r-unknown-none-eabihf".to_string(),
+        llvm_target: "armv7r-unknown-none-eabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
-            linker: Some("rust-lld".to_owned()),
+            linker: Some("rust-lld".into()),
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
-            features: "+vfp3,-d32,-fp16".to_string(),
+            features: "+vfp3,-d32,-fp16".into(),
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
             // GCC and Clang default to 8 for arm-none here
diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
index 2a48e7b..cc17265 100644
--- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
@@ -3,12 +3,12 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7s-apple-ios".to_string(),
+        llvm_target: "armv7s-apple-ios".into(),
         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(),
+        data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            features: "+v7,+vfp4,+neon".to_string(),
+            features: "+v7,+vfp4,+neon".into(),
             max_atomic_width: Some(64),
             ..opts("ios", Arch::Armv7s)
         },
diff --git a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs
index b1adefe..a90c7b7 100644
--- a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs
+++ b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs
@@ -6,6 +6,6 @@
         .post_link_args
         .entry(LinkerFlavor::Em)
         .or_default()
-        .extend(vec!["-s".to_string(), "WASM=0".to_string()]);
+        .extend(vec!["-s".into(), "WASM=0".into()]);
     target
 }
diff --git a/compiler/rustc_target/src/spec/avr_gnu_base.rs b/compiler/rustc_target/src/spec/avr_gnu_base.rs
index a6c1b34..c288e8b 100644
--- a/compiler/rustc_target/src/spec/avr_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/avr_gnu_base.rs
@@ -3,24 +3,24 @@
 /// A base target for AVR devices using the GNU toolchain.
 ///
 /// Requires GNU avr-gcc and avr-binutils on the host system.
-pub fn target(target_cpu: String) -> Target {
+pub fn target(target_cpu: &'static str) -> Target {
     Target {
-        arch: "avr".to_string(),
-        data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".to_string(),
-        llvm_target: "avr-unknown-unknown".to_string(),
+        arch: "avr".into(),
+        data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
+        llvm_target: "avr-unknown-unknown".into(),
         pointer_width: 16,
         options: TargetOptions {
-            c_int_width: "16".to_string(),
-            cpu: target_cpu.clone(),
-            exe_suffix: ".elf".to_string(),
+            c_int_width: "16".into(),
+            cpu: target_cpu.into(),
+            exe_suffix: ".elf".into(),
 
-            linker: Some("avr-gcc".to_owned()),
+            linker: Some("avr-gcc".into()),
             executables: true,
             eh_frame_header: false,
-            pre_link_args: [(LinkerFlavor::Gcc, vec![format!("-mmcu={}", target_cpu)])]
+            pre_link_args: [(LinkerFlavor::Gcc, vec![format!("-mmcu={}", target_cpu).into()])]
                 .into_iter()
                 .collect(),
-            late_link_args: [(LinkerFlavor::Gcc, vec!["-lgcc".to_owned()])].into_iter().collect(),
+            late_link_args: [(LinkerFlavor::Gcc, vec!["-lgcc".into()])].into_iter().collect(),
             max_atomic_width: Some(0),
             atomic_cas: false,
             ..TargetOptions::default()
diff --git a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs
index 7e63ae9..6871ca0 100644
--- a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs
+++ b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs
@@ -1,5 +1,5 @@
 use crate::spec::Target;
 
 pub fn target() -> Target {
-    super::avr_gnu_base::target("atmega328".to_owned())
+    super::avr_gnu_base::target("atmega328")
 }
diff --git a/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs
index a45da82..174ddfa 100644
--- a/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs
@@ -3,10 +3,10 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "bpfeb".to_string(),
-        data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".to_string(),
+        llvm_target: "bpfeb".into(),
+        data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         pointer_width: 64,
-        arch: "bpf".to_string(),
+        arch: "bpf".into(),
         options: bpf_base::opts(Endian::Big),
     }
 }
diff --git a/compiler/rustc_target/src/spec/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/bpfel_unknown_none.rs
index 6c9afdf..7625e7b 100644
--- a/compiler/rustc_target/src/spec/bpfel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/bpfel_unknown_none.rs
@@ -3,10 +3,10 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "bpfel".to_string(),
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".to_string(),
+        llvm_target: "bpfel".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         pointer_width: 64,
-        arch: "bpf".to_string(),
+        arch: "bpf".into(),
         options: bpf_base::opts(Endian::Little),
     }
 }
diff --git a/compiler/rustc_target/src/spec/crt_objects.rs b/compiler/rustc_target/src/spec/crt_objects.rs
index 2fc9ab2..51f392a 100644
--- a/compiler/rustc_target/src/spec/crt_objects.rs
+++ b/compiler/rustc_target/src/spec/crt_objects.rs
@@ -42,16 +42,17 @@
 
 use crate::spec::LinkOutputKind;
 use rustc_serialize::json::{Json, ToJson};
+use std::borrow::Cow;
 use std::collections::BTreeMap;
 use std::str::FromStr;
 
-pub type CrtObjects = BTreeMap<LinkOutputKind, Vec<String>>;
+pub type CrtObjects = BTreeMap<LinkOutputKind, Vec<Cow<'static, str>>>;
 
-pub(super) fn new(obj_table: &[(LinkOutputKind, &[&str])]) -> CrtObjects {
-    obj_table.iter().map(|(z, k)| (*z, k.iter().map(|b| b.to_string()).collect())).collect()
+pub(super) fn new(obj_table: &[(LinkOutputKind, &[&'static str])]) -> CrtObjects {
+    obj_table.iter().map(|(z, k)| (*z, k.iter().map(|b| (*b).into()).collect())).collect()
 }
 
-pub(super) fn all(obj: &str) -> CrtObjects {
+pub(super) fn all(obj: &'static str) -> CrtObjects {
     new(&[
         (LinkOutputKind::DynamicNoPicExe, &[obj]),
         (LinkOutputKind::DynamicPicExe, &[obj]),
diff --git a/compiler/rustc_target/src/spec/dragonfly_base.rs b/compiler/rustc_target/src/spec/dragonfly_base.rs
index e13a640..b59322d 100644
--- a/compiler/rustc_target/src/spec/dragonfly_base.rs
+++ b/compiler/rustc_target/src/spec/dragonfly_base.rs
@@ -1,11 +1,11 @@
-use crate::spec::{RelroLevel, TargetOptions};
+use crate::spec::{cvs, RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        os: "dragonfly".to_string(),
+        os: "dragonfly".into(),
         dynamic_linking: true,
         executables: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         has_rpath: true,
         position_independent_executables: true,
         relro_level: RelroLevel::Full,
diff --git a/compiler/rustc_target/src/spec/freebsd_base.rs b/compiler/rustc_target/src/spec/freebsd_base.rs
index f2ec6aa..a7e0f9f 100644
--- a/compiler/rustc_target/src/spec/freebsd_base.rs
+++ b/compiler/rustc_target/src/spec/freebsd_base.rs
@@ -1,11 +1,11 @@
-use crate::spec::{RelroLevel, TargetOptions};
+use crate::spec::{cvs, RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        os: "freebsd".to_string(),
+        os: "freebsd".into(),
         dynamic_linking: true,
         executables: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         has_rpath: true,
         position_independent_executables: true,
         relro_level: RelroLevel::Full,
diff --git a/compiler/rustc_target/src/spec/fuchsia_base.rs b/compiler/rustc_target/src/spec/fuchsia_base.rs
index 4a7686a..04e30ff 100644
--- a/compiler/rustc_target/src/spec/fuchsia_base.rs
+++ b/compiler/rustc_target/src/spec/fuchsia_base.rs
@@ -1,31 +1,33 @@
-use crate::spec::{crt_objects, LinkArgs, LinkOutputKind, LinkerFlavor, LldFlavor, TargetOptions};
+use crate::spec::{
+    crt_objects, cvs, LinkArgs, LinkOutputKind, LinkerFlavor, LldFlavor, TargetOptions,
+};
 
 pub fn opts() -> TargetOptions {
     let mut pre_link_args = LinkArgs::new();
     pre_link_args.insert(
         LinkerFlavor::Lld(LldFlavor::Ld),
         vec![
-            "--build-id".to_string(),
-            "--hash-style=gnu".to_string(),
-            "-z".to_string(),
-            "max-page-size=4096".to_string(),
-            "-z".to_string(),
-            "now".to_string(),
-            "-z".to_string(),
-            "rodynamic".to_string(),
-            "-z".to_string(),
-            "separate-loadable-segments".to_string(),
-            "--pack-dyn-relocs=relr".to_string(),
+            "--build-id".into(),
+            "--hash-style=gnu".into(),
+            "-z".into(),
+            "max-page-size=4096".into(),
+            "-z".into(),
+            "now".into(),
+            "-z".into(),
+            "rodynamic".into(),
+            "-z".into(),
+            "separate-loadable-segments".into(),
+            "--pack-dyn-relocs=relr".into(),
         ],
     );
 
     TargetOptions {
-        os: "fuchsia".to_string(),
+        os: "fuchsia".into(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-        linker: Some("rust-lld".to_owned()),
+        linker: Some("rust-lld".into()),
         dynamic_linking: true,
         executables: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         is_like_fuchsia: true,
         pre_link_args,
         pre_link_objects: crt_objects::new(&[
diff --git a/compiler/rustc_target/src/spec/haiku_base.rs b/compiler/rustc_target/src/spec/haiku_base.rs
index 2b95523..61c05a2 100644
--- a/compiler/rustc_target/src/spec/haiku_base.rs
+++ b/compiler/rustc_target/src/spec/haiku_base.rs
@@ -1,11 +1,11 @@
-use crate::spec::{RelroLevel, TargetOptions};
+use crate::spec::{cvs, RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        os: "haiku".to_string(),
+        os: "haiku".into(),
         dynamic_linking: true,
         executables: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         relro_level: RelroLevel::Full,
         ..Default::default()
     }
diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/hermit_base.rs
index b0b1d80..7cbd424 100644
--- a/compiler/rustc_target/src/spec/hermit_base.rs
+++ b/compiler/rustc_target/src/spec/hermit_base.rs
@@ -4,13 +4,13 @@
     let mut pre_link_args = LinkArgs::new();
     pre_link_args.insert(
         LinkerFlavor::Lld(LldFlavor::Ld),
-        vec!["--build-id".to_string(), "--hash-style=gnu".to_string(), "--Bstatic".to_string()],
+        vec!["--build-id".into(), "--hash-style=gnu".into(), "--Bstatic".into()],
     );
 
     TargetOptions {
-        os: "hermit".to_string(),
+        os: "hermit".into(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-        linker: Some("rust-lld".to_owned()),
+        linker: Some("rust-lld".into()),
         executables: true,
         has_thread_local: true,
         pre_link_args,
diff --git a/compiler/rustc_target/src/spec/hermit_kernel_base.rs b/compiler/rustc_target/src/spec/hermit_kernel_base.rs
deleted file mode 100644
index ce3dad2..0000000
--- a/compiler/rustc_target/src/spec/hermit_kernel_base.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions};
-
-pub fn opts() -> TargetOptions {
-    let mut pre_link_args = LinkArgs::new();
-    pre_link_args.insert(
-        LinkerFlavor::Lld(LldFlavor::Ld),
-        vec!["--build-id".to_string(), "--hash-style=gnu".to_string(), "--Bstatic".to_string()],
-    );
-
-    TargetOptions {
-        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-        disable_redzone: true,
-        linker: Some("rust-lld".to_owned()),
-        executables: true,
-        pre_link_args,
-        panic_strategy: PanicStrategy::Abort,
-        position_independent_executables: true,
-        static_position_independent_executables: true,
-        ..Default::default()
-    }
-}
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 27d306c..80cf095 100644
--- a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
@@ -2,10 +2,10 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.cpu = "hexagonv60".to_string();
+    base.cpu = "hexagonv60".into();
     base.max_atomic_width = Some(32);
     // FIXME: HVX length defaults are per-CPU
-    base.features = "-small-data,+hvx-length128b".to_string();
+    base.features = "-small-data,+hvx-length128b".into();
 
     base.crt_static_default = false;
     base.has_rpath = true;
@@ -16,7 +16,7 @@
     base.c_enum_min_bits = 8;
 
     Target {
-        llvm_target: "hexagon-unknown-linux-musl".to_string(),
+        llvm_target: "hexagon-unknown-linux-musl".into(),
         pointer_width: 32,
         data_layout: concat!(
             "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32",
@@ -24,8 +24,8 @@
             ":32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048",
             ":2048:2048"
         )
-        .to_string(),
-        arch: "hexagon".to_string(),
+        .into(),
+        arch: "hexagon".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs
index 4419dfe..8b6266c 100644
--- a/compiler/rustc_target/src/spec/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs
@@ -3,13 +3,15 @@
 
 pub fn target() -> Target {
     let base = opts("ios", Arch::I386);
+    let llvm_target = super::apple_base::ios_sim_llvm_target("i386");
+
     Target {
-        llvm_target: super::apple_base::ios_sim_llvm_target("i386"),
+        llvm_target: llvm_target.into(),
         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"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: TargetOptions {
             max_atomic_width: Some(64),
             // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
diff --git a/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
index f329b2d..801a889 100644
--- a/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
@@ -2,7 +2,7 @@
 
 pub fn target() -> Target {
     let mut base = super::i686_unknown_linux_gnu::target();
-    base.cpu = "i386".to_string();
-    base.llvm_target = "i386-unknown-linux-gnu".to_string();
+    base.cpu = "i386".into();
+    base.llvm_target = "i386-unknown-linux-gnu".into();
     base
 }
diff --git a/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
index 5d96a55..a11fbec 100644
--- a/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
@@ -2,7 +2,7 @@
 
 pub fn target() -> Target {
     let mut base = super::i686_unknown_linux_gnu::target();
-    base.cpu = "i486".to_string();
-    base.llvm_target = "i486-unknown-linux-gnu".to_string();
+    base.cpu = "i486".into();
+    base.llvm_target = "i486-unknown-linux-gnu".into();
     base
 }
diff --git a/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs
index 4a7779a..befb0f8 100644
--- a/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs
@@ -2,7 +2,7 @@
 
 pub fn target() -> Target {
     let mut base = super::i686_pc_windows_msvc::target();
-    base.cpu = "pentium".to_string();
-    base.llvm_target = "i586-pc-windows-msvc".to_string();
+    base.cpu = "pentium".into();
+    base.llvm_target = "i586-pc-windows-msvc".into();
     base
 }
diff --git a/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs
index 7c92dda..b699a7a 100644
--- a/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs
@@ -2,7 +2,7 @@
 
 pub fn target() -> Target {
     let mut base = super::i686_unknown_linux_gnu::target();
-    base.cpu = "pentium".to_string();
-    base.llvm_target = "i586-unknown-linux-gnu".to_string();
+    base.cpu = "pentium".into();
+    base.llvm_target = "i586-unknown-linux-gnu".into();
     base
 }
diff --git a/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs
index 1fea02b..55a26eb 100644
--- a/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs
@@ -2,7 +2,7 @@
 
 pub fn target() -> Target {
     let mut base = super::i686_unknown_linux_musl::target();
-    base.cpu = "pentium".to_string();
-    base.llvm_target = "i586-unknown-linux-musl".to_string();
+    base.cpu = "pentium".into();
+    base.llvm_target = "i586-unknown-linux-musl".into();
     base
 }
diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs
index f2635f0..ad716a6 100644
--- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs
@@ -2,10 +2,10 @@
 
 pub fn target() -> Target {
     let mut base = super::apple_base::opts("macos");
-    base.cpu = "yonah".to_string();
+    base.cpu = "yonah".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
-    base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".into()]);
+    base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.frame_pointer = FramePointer::Always;
@@ -17,12 +17,12 @@
     let llvm_target = super::apple_base::macos_llvm_target(&arch);
 
     Target {
-        llvm_target,
+        llvm_target: llvm_target.into(),
         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"
-            .to_string(),
-        arch: "x86".to_string(),
-        options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base },
+            .into(),
+        arch: "x86".into(),
+        options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_linux_android.rs b/compiler/rustc_target/src/spec/i686_linux_android.rs
index 640f9e4..bdaf5c9 100644
--- a/compiler/rustc_target/src/spec/i686_linux_android.rs
+++ b/compiler/rustc_target/src/spec/i686_linux_android.rs
@@ -1,4 +1,4 @@
-use crate::spec::{StackProbeType, Target};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions};
 
 // See https://developer.android.com/ndk/guides/abis.html#x86
 // for target ABI requirements.
@@ -9,18 +9,18 @@
     base.max_atomic_width = Some(64);
 
     // https://developer.android.com/ndk/guides/abis.html#x86
-    base.cpu = "pentiumpro".to_string();
-    base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".to_string();
+    base.cpu = "pentiumpro".into();
+    base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".into();
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "i686-linux-android".to_string(),
+        llvm_target: "i686-linux-android".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:32-n8:16:32-S128"
-            .to_string(),
-        arch: "x86".to_string(),
-        options: base,
+            .into(),
+        arch: "x86".into(),
+        options: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
index 92c3a15..554b0f3 100644
--- a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
@@ -2,27 +2,26 @@
 
 pub fn target() -> Target {
     let mut base = super::windows_gnu_base::opts();
-    base.cpu = "pentium4".to_string();
-    base.pre_link_args
-        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
+    base.cpu = "pentium4".into();
+    base.pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pe".into()]);
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
-    base.linker = Some("i686-w64-mingw32-gcc".to_string());
+    base.linker = Some("i686-w64-mingw32-gcc".into());
 
     // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
     // space available to x86 Windows binaries on x86_64.
     base.pre_link_args
         .entry(LinkerFlavor::Gcc)
         .or_default()
-        .push("-Wl,--large-address-aware".to_string());
+        .push("-Wl,--large-address-aware".into());
 
     Target {
-        llvm_target: "i686-pc-windows-gnu".to_string(),
+        llvm_target: "i686-pc-windows-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-f80:32-n8:16:32-a:0:32-S32"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
index 1742948..fb0cb6a 100644
--- a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
@@ -2,31 +2,33 @@
 
 pub fn target() -> Target {
     let mut base = super::windows_msvc_base::opts();
-    base.cpu = "pentium4".to_string();
+    base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
 
     let pre_link_args_msvc = vec![
         // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
         // space available to x86 Windows binaries on x86_64.
-        "/LARGEADDRESSAWARE".to_string(),
+        "/LARGEADDRESSAWARE".into(),
         // Ensure the linker will only produce an image if it can also produce a table of
         // the image's safe exception handlers.
         // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers
-        "/SAFESEH".to_string(),
+        "/SAFESEH".into(),
     ];
     base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone());
     base.pre_link_args
         .entry(LinkerFlavor::Lld(LldFlavor::Link))
         .or_default()
         .extend(pre_link_args_msvc);
+    // Workaround for #95429
+    base.has_thread_local = false;
 
     Target {
-        llvm_target: "i686-pc-windows-msvc".to_string(),
+        llvm_target: "i686-pc-windows-msvc".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-f80:128-n8:16:32-a:0:32-S32"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
index d8e37e7..9f0cb04 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
@@ -2,21 +2,21 @@
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
-    base.cpu = "pentium4".to_string();
+    base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     let pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default();
-    pre_link_args.push("-m32".to_string());
-    pre_link_args.push("-Wl,-znotext".to_string());
+    pre_link_args.push("-m32".into());
+    pre_link_args.push("-Wl,-znotext".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "i686-unknown-freebsd".to_string(),
+        llvm_target: "i686-unknown-freebsd".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:32-n8:16:32-S128"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
index e4c01db..d1af163 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
@@ -2,19 +2,19 @@
 
 pub fn target() -> Target {
     let mut base = super::haiku_base::opts();
-    base.cpu = "pentium4".to_string();
+    base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".into()]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "i686-unknown-haiku".to_string(),
+        llvm_target: "i686-unknown-haiku".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:32-n8:16:32-S128"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
index 165505e..0998c61 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
@@ -2,19 +2,19 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.cpu = "pentium4".to_string();
+    base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "i686-unknown-linux-gnu".to_string(),
+        llvm_target: "i686-unknown-linux-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:32-n8:16:32-S128"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
index d95cb6a..a697f29 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
@@ -2,10 +2,10 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.cpu = "pentium4".to_string();
+    base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-Wl,-melf_i386".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-Wl,-melf_i386".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
@@ -24,12 +24,12 @@
     base.frame_pointer = FramePointer::Always;
 
     Target {
-        llvm_target: "i686-unknown-linux-musl".to_string(),
+        llvm_target: "i686-unknown-linux-musl".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:32-n8:16:32-S128"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
index 989e3fb..2807d32 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
@@ -2,19 +2,19 @@
 
 pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
-    base.cpu = "pentium4".to_string();
+    base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "i686-unknown-netbsdelf".to_string(),
+        llvm_target: "i686-unknown-netbsdelf".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:32-n8:16:32-S128"
-            .to_string(),
-        arch: "x86".to_string(),
-        options: TargetOptions { mcount: "__mcount".to_string(), ..base },
+            .into(),
+        arch: "x86".into(),
+        options: TargetOptions { mcount: "__mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
index 7ff7996..78462eb 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
@@ -2,20 +2,20 @@
 
 pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
-    base.cpu = "pentium4".to_string();
+    base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-fuse-ld=lld".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-fuse-ld=lld".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "i686-unknown-openbsd".to_string(),
+        llvm_target: "i686-unknown-openbsd".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:32-n8:16:32-S128"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/i686_unknown_uefi.rs
index 5af3a6b..a2e42c5 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_uefi.rs
@@ -9,7 +9,7 @@
 
 pub fn target() -> Target {
     let mut base = super::uefi_msvc_base::opts();
-    base.cpu = "pentium4".to_string();
+    base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
 
     // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
@@ -21,7 +21,7 @@
     // far.
     // If you initialize FP units yourself, you can override these flags with custom linker
     // arguments, thus giving you access to full MMX/SSE acceleration.
-    base.features = "-mmx,-sse,+soft-float".to_string();
+    base.features = "-mmx,-sse,+soft-float".into();
 
     // Use -GNU here, because of the reason below:
     // Background and Problem:
@@ -49,7 +49,7 @@
     //        setLibcallCallingConv(RTLIB::UREM_I64, CallingConv::X86_StdCall);
     //        setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::X86_StdCall);
     //      }
-    //   The compiler intrisics should be implemented by compiler-builtins.
+    //   The compiler intrinsics should be implemented by compiler-builtins.
     //   Unfortunately, compiler-builtins has not provided those intrinsics yet. Such as:
     //      i386/divdi3.S
     //      i386/lshrdi3.S
@@ -64,7 +64,7 @@
     //   2. Implement Intrinsics.
     //   We evaluated all options.
     //   #2 is hard because we need implement the intrinsics (_aulldiv) generated
-    //   from the other intrinscis (__udivdi3) implementation with the same
+    //   from the other intrinsics (__udivdi3) implementation with the same
     //   functionality (udivmod_inner). If we let _aulldiv() call udivmod_inner!(),
     //   then we are in loop. We may have to find another way to implement udivmod_inner!().
     //   #1.2 may break the existing usage.
@@ -73,16 +73,16 @@
     //   It uses cdecl, EAX/ECX/EDX as volatile register, and EAX/EDX as return value.
     //   We also checked the LLVM X86TargetLowering, the differences between -gnu and -msvc
     //   is fmodf(f32), longjmp() and TLS. None of them impacts the UEFI code.
-    // As a result, we choose -gnu for i686 version before those intrisics are implemented in
+    // As a result, we choose -gnu for i686 version before those intrinsics are implemented in
     // compiler-builtins. After compiler-builtins implements all required intrinsics, we may
     // remove -gnu and use the default one.
     Target {
-        llvm_target: "i686-unknown-windows-gnu".to_string(),
+        llvm_target: "i686-unknown-windows-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-f80:32-n8:16:32-a:0:32-S32"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
 
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
index 27a0ac5..75f7a220 100644
--- a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
@@ -2,9 +2,8 @@
 
 pub fn target() -> Target {
     let mut base = super::windows_uwp_gnu_base::opts();
-    base.cpu = "pentium4".to_string();
-    base.pre_link_args
-        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
+    base.cpu = "pentium4".into();
+    base.pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pe".into()]);
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
 
@@ -13,15 +12,15 @@
     base.pre_link_args
         .entry(LinkerFlavor::Gcc)
         .or_default()
-        .push("-Wl,--large-address-aware".to_string());
+        .push("-Wl,--large-address-aware".into());
 
     Target {
-        llvm_target: "i686-pc-windows-gnu".to_string(),
+        llvm_target: "i686-pc-windows-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-f80:32-n8:16:32-a:0:32-S32"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs
index e2f65e7..4c657fe 100644
--- a/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs
@@ -2,16 +2,16 @@
 
 pub fn target() -> Target {
     let mut base = super::windows_uwp_msvc_base::opts();
-    base.cpu = "pentium4".to_string();
+    base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "i686-pc-windows-msvc".to_string(),
+        llvm_target: "i686-pc-windows-msvc".into(),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-f80:128-n8:16:32-a:0:32-S32"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
index c7963db..d51ed7c 100644
--- a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
@@ -2,19 +2,19 @@
 
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
-    base.cpu = "pentium4".to_string();
+    base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "i686-unknown-linux-gnu".to_string(),
+        llvm_target: "i686-unknown-linux-gnu".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:32-n8:16:32-S128"
-            .to_string(),
-        arch: "x86".to_string(),
+            .into(),
+        arch: "x86".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/illumos_base.rs b/compiler/rustc_target/src/spec/illumos_base.rs
index aeb40f7..ef8f90a 100644
--- a/compiler/rustc_target/src/spec/illumos_base.rs
+++ b/compiler/rustc_target/src/spec/illumos_base.rs
@@ -1,5 +1,4 @@
-use crate::spec::{FramePointer, LinkArgs, LinkerFlavor, TargetOptions};
-use std::default::Default;
+use crate::spec::{cvs, FramePointer, LinkArgs, LinkerFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let mut late_link_args = LinkArgs::new();
@@ -16,22 +15,22 @@
             // FIXME: This should be replaced by a more complete and generic
             // mechanism for controlling the order of library arguments passed
             // to the linker.
-            "-lc".to_string(),
+            "-lc".into(),
             // LLVM will insert calls to the stack protector functions
             // "__stack_chk_fail" and "__stack_chk_guard" into code in native
             // object files.  Some platforms include these symbols directly in
             // libc, but at least historically these have been provided in
             // libssp.so on illumos and Solaris systems.
-            "-lssp".to_string(),
+            "-lssp".into(),
         ],
     );
 
     TargetOptions {
-        os: "illumos".to_string(),
+        os: "illumos".into(),
         dynamic_linking: true,
         executables: true,
         has_rpath: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         is_like_solaris: true,
         linker_is_gnu: false,
         limit_rdylib_exports: false, // Linker doesn't support this
@@ -54,8 +53,8 @@
         //
         // We want XPG6 behavior from libc and libm.  See standards(5)
         //pre_link_objects_exe: vec![
-        //    "/usr/lib/amd64/values-Xc.o".to_string(),
-        //    "/usr/lib/amd64/values-xpg6.o".to_string(),
+        //    "/usr/lib/amd64/values-Xc.o".into(),
+        //    "/usr/lib/amd64/values-xpg6.o".into(),
         //],
         ..Default::default()
     }
diff --git a/compiler/rustc_target/src/spec/l4re_base.rs b/compiler/rustc_target/src/spec/l4re_base.rs
index 9e7973f..7a05153 100644
--- a/compiler/rustc_target/src/spec/l4re_base.rs
+++ b/compiler/rustc_target/src/spec/l4re_base.rs
@@ -1,16 +1,15 @@
-use crate::spec::{LinkerFlavor, PanicStrategy, TargetOptions};
-use std::default::Default;
+use crate::spec::{cvs, LinkerFlavor, PanicStrategy, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        os: "l4re".to_string(),
-        env: "uclibc".to_string(),
+        os: "l4re".into(),
+        env: "uclibc".into(),
         linker_flavor: LinkerFlavor::L4Bender,
         executables: true,
         panic_strategy: PanicStrategy::Abort,
-        linker: Some("l4-bender".to_string()),
+        linker: Some("l4-bender".into()),
         linker_is_gnu: false,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         ..Default::default()
     }
 }
diff --git a/compiler/rustc_target/src/spec/linux_base.rs b/compiler/rustc_target/src/spec/linux_base.rs
index e53d465..0f79ada0 100644
--- a/compiler/rustc_target/src/spec/linux_base.rs
+++ b/compiler/rustc_target/src/spec/linux_base.rs
@@ -1,11 +1,11 @@
-use crate::spec::{RelroLevel, TargetOptions};
+use crate::spec::{cvs, RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        os: "linux".to_string(),
+        os: "linux".into(),
         dynamic_linking: true,
         executables: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         has_rpath: true,
         position_independent_executables: true,
         relro_level: RelroLevel::Full,
diff --git a/compiler/rustc_target/src/spec/linux_gnu_base.rs b/compiler/rustc_target/src/spec/linux_gnu_base.rs
index 3d940ce..8d6b3f1 100644
--- a/compiler/rustc_target/src/spec/linux_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/linux_gnu_base.rs
@@ -1,5 +1,5 @@
 use crate::spec::TargetOptions;
 
 pub fn opts() -> TargetOptions {
-    TargetOptions { env: "gnu".to_string(), ..super::linux_base::opts() }
+    TargetOptions { env: "gnu".into(), ..super::linux_base::opts() }
 }
diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs
index a332e3b..0f5d852 100644
--- a/compiler/rustc_target/src/spec/linux_kernel_base.rs
+++ b/compiler/rustc_target/src/spec/linux_kernel_base.rs
@@ -3,7 +3,7 @@
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        env: "gnu".to_string(),
+        env: "gnu".into(),
         disable_redzone: true,
         panic_strategy: PanicStrategy::Abort,
         // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
diff --git a/compiler/rustc_target/src/spec/linux_musl_base.rs b/compiler/rustc_target/src/spec/linux_musl_base.rs
index 5038a96..207a87a 100644
--- a/compiler/rustc_target/src/spec/linux_musl_base.rs
+++ b/compiler/rustc_target/src/spec/linux_musl_base.rs
@@ -4,7 +4,7 @@
 pub fn opts() -> TargetOptions {
     let mut base = super::linux_base::opts();
 
-    base.env = "musl".to_string();
+    base.env = "musl".into();
     base.pre_link_objects_fallback = crt_objects::pre_musl_fallback();
     base.post_link_objects_fallback = crt_objects::post_musl_fallback();
     base.crt_objects_fallback = Some(CrtObjectsFallback::Musl);
diff --git a/compiler/rustc_target/src/spec/linux_uclibc_base.rs b/compiler/rustc_target/src/spec/linux_uclibc_base.rs
index ef6d506..4ba480f 100644
--- a/compiler/rustc_target/src/spec/linux_uclibc_base.rs
+++ b/compiler/rustc_target/src/spec/linux_uclibc_base.rs
@@ -1,5 +1,5 @@
 use crate::spec::TargetOptions;
 
 pub fn opts() -> TargetOptions {
-    TargetOptions { env: "uclibc".to_string(), ..super::linux_base::opts() }
+    TargetOptions { env: "uclibc".into(), ..super::linux_base::opts() }
 }
diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
index 5671b59..ebd7401 100644
--- a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
@@ -6,10 +6,10 @@
     base.max_atomic_width = Some(32);
 
     Target {
-        llvm_target: "m68k-unknown-linux-gnu".to_string(),
+        llvm_target: "m68k-unknown-linux-gnu".into(),
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16".to_string(),
-        arch: "m68k".to_string(),
-        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
+        data_layout: "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16".into(),
+        arch: "m68k".into(),
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs
index 5991cd8..3c6ef52 100644
--- a/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs
@@ -5,21 +5,21 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.cpu = "mips64r2".to_string();
-    base.features = "+mips64r2,+soft-float".to_string();
+    base.cpu = "mips64r2".into();
+    base.features = "+mips64r2,+soft-float".into();
     base.max_atomic_width = Some(64);
     base.crt_static_default = false;
 
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
-        llvm_target: "mips64-unknown-linux-musl".to_string(),
+        llvm_target: "mips64-unknown-linux-musl".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
-        arch: "mips64".to_string(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        arch: "mips64".into(),
         options: TargetOptions {
-            abi: "abi64".to_string(),
+            abi: "abi64".into(),
             endian: Endian::Big,
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
index 161a27a..fc5dbd1 100644
--- a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
@@ -3,18 +3,18 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mips64-unknown-linux-gnuabi64".to_string(),
+        llvm_target: "mips64-unknown-linux-gnuabi64".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
-        arch: "mips64".to_string(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        arch: "mips64".into(),
         options: TargetOptions {
-            abi: "abi64".to_string(),
+            abi: "abi64".into(),
             endian: Endian::Big,
             // NOTE(mips64r2) matches C toolchain
-            cpu: "mips64r2".to_string(),
-            features: "+mips64r2".to_string(),
+            cpu: "mips64r2".into(),
+            features: "+mips64r2".into(),
             max_atomic_width: Some(64),
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
 
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
index a898464..465e97a 100644
--- a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
@@ -3,19 +3,19 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.cpu = "mips64r2".to_string();
-    base.features = "+mips64r2".to_string();
+    base.cpu = "mips64r2".into();
+    base.features = "+mips64r2".into();
     base.max_atomic_width = Some(64);
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
-        llvm_target: "mips64-unknown-linux-musl".to_string(),
+        llvm_target: "mips64-unknown-linux-musl".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
-        arch: "mips64".to_string(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        arch: "mips64".into(),
         options: TargetOptions {
-            abi: "abi64".to_string(),
+            abi: "abi64".into(),
             endian: Endian::Big,
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
index 2f58560d..e0d5f6f 100644
--- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
@@ -2,17 +2,17 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mips64el-unknown-linux-gnuabi64".to_string(),
+        llvm_target: "mips64el-unknown-linux-gnuabi64".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
-        arch: "mips64".to_string(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        arch: "mips64".into(),
         options: TargetOptions {
-            abi: "abi64".to_string(),
+            abi: "abi64".into(),
             // NOTE(mips64r2) matches C toolchain
-            cpu: "mips64r2".to_string(),
-            features: "+mips64r2".to_string(),
+            cpu: "mips64r2".into(),
+            features: "+mips64r2".into(),
             max_atomic_width: Some(64),
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
 
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs
index 01c34bc..75575eb 100644
--- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.cpu = "mips64r2".to_string();
-    base.features = "+mips64r2".to_string();
+    base.cpu = "mips64r2".into();
+    base.features = "+mips64r2".into();
     base.max_atomic_width = Some(64);
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
-        llvm_target: "mips64el-unknown-linux-musl".to_string(),
+        llvm_target: "mips64el-unknown-linux-musl".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
-        arch: "mips64".to_string(),
-        options: TargetOptions { abi: "abi64".to_string(), mcount: "_mcount".to_string(), ..base },
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        arch: "mips64".into(),
+        options: TargetOptions { abi: "abi64".into(), mcount: "_mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
index b41b28cb..8df8b0b 100644
--- a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
@@ -3,16 +3,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mips-unknown-linux-gnu".to_string(),
+        llvm_target: "mips-unknown-linux-gnu".into(),
         pointer_width: 32,
-        data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
-        arch: "mips".to_string(),
+        data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
         options: TargetOptions {
             endian: Endian::Big,
-            cpu: "mips32r2".to_string(),
-            features: "+mips32r2,+fpxx,+nooddspreg".to_string(),
+            cpu: "mips32r2".into(),
+            features: "+mips32r2,+fpxx,+nooddspreg".into(),
             max_atomic_width: Some(32),
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
 
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
index 3713af4..c284631 100644
--- a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
@@ -3,15 +3,15 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.cpu = "mips32r2".to_string();
-    base.features = "+mips32r2,+soft-float".to_string();
+    base.cpu = "mips32r2".into();
+    base.features = "+mips32r2,+soft-float".into();
     base.max_atomic_width = Some(32);
     base.crt_static_default = false;
     Target {
-        llvm_target: "mips-unknown-linux-musl".to_string(),
+        llvm_target: "mips-unknown-linux-musl".into(),
         pointer_width: 32,
-        data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
-        arch: "mips".to_string(),
-        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
+        data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
index 042ec91..c59bb5f 100644
--- a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
@@ -3,16 +3,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mips-unknown-linux-uclibc".to_string(),
+        llvm_target: "mips-unknown-linux-uclibc".into(),
         pointer_width: 32,
-        data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
-        arch: "mips".to_string(),
+        data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
         options: TargetOptions {
             endian: Endian::Big,
-            cpu: "mips32r2".to_string(),
-            features: "+mips32r2,+soft-float".to_string(),
+            cpu: "mips32r2".into(),
+            features: "+mips32r2,+soft-float".into(),
             max_atomic_width: Some(32),
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
 
             ..super::linux_uclibc_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
index dc14e4b..45966b9 100644
--- a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
+++ b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
@@ -1,35 +1,35 @@
+use crate::spec::{cvs, Target, TargetOptions};
 use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel};
-use crate::spec::{Target, TargetOptions};
 
 // The PSP has custom linker requirements.
 const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");
 
 pub fn target() -> Target {
     let mut pre_link_args = LinkArgs::new();
-    pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["--emit-relocs".to_string()]);
+    pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["--emit-relocs".into()]);
 
     Target {
-        llvm_target: "mipsel-sony-psp".to_string(),
+        llvm_target: "mipsel-sony-psp".into(),
         pointer_width: 32,
-        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
-        arch: "mips".to_string(),
+        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
 
         options: TargetOptions {
-            os: "psp".to_string(),
-            vendor: "sony".to_string(),
+            os: "psp".into(),
+            vendor: "sony".into(),
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-            cpu: "mips2".to_string(),
+            cpu: "mips2".into(),
             executables: true,
-            linker: Some("rust-lld".to_owned()),
+            linker: Some("rust-lld".into()),
             relocation_model: RelocModel::Static,
 
             // PSP FPU only supports single precision floats.
-            features: "+single-float".to_string(),
+            features: "+single-float".into(),
 
             // PSP does not support trap-on-condition instructions.
-            llvm_args: vec!["-mno-check-zero-division".to_string()],
+            llvm_args: cvs!["-mno-check-zero-division"],
             pre_link_args,
-            link_script: Some(LINKER_SCRIPT.to_string()),
+            link_script: Some(LINKER_SCRIPT.into()),
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs
index 9cb2a13..01346e7 100644
--- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs
@@ -2,16 +2,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mipsel-unknown-linux-gnu".to_string(),
+        llvm_target: "mipsel-unknown-linux-gnu".into(),
         pointer_width: 32,
-        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
-        arch: "mips".to_string(),
+        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
 
         options: TargetOptions {
-            cpu: "mips32r2".to_string(),
-            features: "+mips32r2,+fpxx,+nooddspreg".to_string(),
+            cpu: "mips32r2".into(),
+            features: "+mips32r2,+fpxx,+nooddspreg".into(),
             max_atomic_width: Some(32),
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
 
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs
index 3374cdd..0e8f1a2 100644
--- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.cpu = "mips32r2".to_string();
-    base.features = "+mips32r2,+soft-float".to_string();
+    base.cpu = "mips32r2".into();
+    base.features = "+mips32r2,+soft-float".into();
     base.max_atomic_width = Some(32);
     base.crt_static_default = false;
     Target {
-        llvm_target: "mipsel-unknown-linux-musl".to_string(),
+        llvm_target: "mipsel-unknown-linux-musl".into(),
         pointer_width: 32,
-        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
-        arch: "mips".to_string(),
-        options: TargetOptions { mcount: "_mcount".to_string(), ..base },
+        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
+        options: TargetOptions { mcount: "_mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs
index 0831eb7a..8342074 100644
--- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs
@@ -2,16 +2,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mipsel-unknown-linux-uclibc".to_string(),
+        llvm_target: "mipsel-unknown-linux-uclibc".into(),
         pointer_width: 32,
-        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
-        arch: "mips".to_string(),
+        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
 
         options: TargetOptions {
-            cpu: "mips32r2".to_string(),
-            features: "+mips32r2,+soft-float".to_string(),
+            cpu: "mips32r2".into(),
+            features: "+mips32r2,+soft-float".into(),
             max_atomic_width: Some(32),
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
 
             ..super::linux_uclibc_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
index 5955baa..736af15 100644
--- a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
@@ -7,18 +7,18 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mipsel-unknown-none".to_string(),
+        llvm_target: "mipsel-unknown-none".into(),
         pointer_width: 32,
-        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
-        arch: "mips".to_string(),
+        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
 
         options: TargetOptions {
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-            cpu: "mips32r2".to_string(),
-            features: "+mips32r2,+soft-float,+noabicalls".to_string(),
+            cpu: "mips32r2".into(),
+            features: "+mips32r2,+soft-float,+noabicalls".into(),
             max_atomic_width: Some(32),
             executables: true,
-            linker: Some("rust-lld".to_owned()),
+            linker: Some("rust-lld".into()),
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
diff --git a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
index a81c90f..1e066b2 100644
--- a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
@@ -3,16 +3,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mipsisa32r6-unknown-linux-gnu".to_string(),
+        llvm_target: "mipsisa32r6-unknown-linux-gnu".into(),
         pointer_width: 32,
-        data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
-        arch: "mips".to_string(),
+        data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
         options: TargetOptions {
             endian: Endian::Big,
-            cpu: "mips32r6".to_string(),
-            features: "+mips32r6".to_string(),
+            cpu: "mips32r6".into(),
+            features: "+mips32r6".into(),
             max_atomic_width: Some(32),
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
 
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs
index 06a5f40..4785929 100644
--- a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs
@@ -2,16 +2,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mipsisa32r6el-unknown-linux-gnu".to_string(),
+        llvm_target: "mipsisa32r6el-unknown-linux-gnu".into(),
         pointer_width: 32,
-        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
-        arch: "mips".to_string(),
+        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+        arch: "mips".into(),
 
         options: TargetOptions {
-            cpu: "mips32r6".to_string(),
-            features: "+mips32r6".to_string(),
+            cpu: "mips32r6".into(),
+            features: "+mips32r6".into(),
             max_atomic_width: Some(32),
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
 
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
index 80a155a..766ac76 100644
--- a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -3,18 +3,18 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".to_string(),
+        llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
-        arch: "mips64".to_string(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        arch: "mips64".into(),
         options: TargetOptions {
-            abi: "abi64".to_string(),
+            abi: "abi64".into(),
             endian: Endian::Big,
             // NOTE(mips64r6) matches C toolchain
-            cpu: "mips64r6".to_string(),
-            features: "+mips64r6".to_string(),
+            cpu: "mips64r6".into(),
+            features: "+mips64r6".into(),
             max_atomic_width: Some(64),
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
 
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
index 58f9862..d2b07c6 100644
--- a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
@@ -2,17 +2,17 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".to_string(),
+        llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
-        arch: "mips64".to_string(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        arch: "mips64".into(),
         options: TargetOptions {
-            abi: "abi64".to_string(),
+            abi: "abi64".into(),
             // NOTE(mips64r6) matches C toolchain
-            cpu: "mips64r6".to_string(),
-            features: "+mips64r6".to_string(),
+            cpu: "mips64r6".into(),
+            features: "+mips64r6".into(),
             max_atomic_width: Some(64),
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
 
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 92678ae..bd5b712 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -40,6 +40,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_serialize::json::{Json, ToJson};
 use rustc_span::symbol::{sym, Symbol};
+use std::borrow::Cow;
 use std::collections::BTreeMap;
 use std::convert::TryFrom;
 use std::iter::FromIterator;
@@ -63,7 +64,6 @@
 mod fuchsia_base;
 mod haiku_base;
 mod hermit_base;
-mod hermit_kernel_base;
 mod illumos_base;
 mod l4re_base;
 mod linux_base;
@@ -186,12 +186,16 @@
         }
     }
 
-    pub fn desc_symbol(&self) -> Symbol {
+    pub const fn desc_symbol(&self) -> Symbol {
         match *self {
             PanicStrategy::Unwind => sym::unwind,
             PanicStrategy::Abort => sym::abort,
         }
     }
+
+    pub const fn all() -> [Symbol; 2] {
+        [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
+    }
 }
 
 impl ToJson for PanicStrategy {
@@ -455,7 +459,7 @@
     }
 }
 
-pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>;
+pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
 
 #[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
 pub enum SplitDebuginfo {
@@ -614,7 +618,7 @@
     /// Return sanitizer's name
     ///
     /// Returns none if the flags is a set of sanitizers numbering not exactly one.
-    fn as_str(self) -> Option<&'static str> {
+    pub fn as_str(self) -> Option<&'static str> {
         Some(match self {
             SanitizerSet::ADDRESS => "address",
             SanitizerSet::CFI => "cfi",
@@ -967,10 +971,8 @@
     ("aarch64-unknown-hermit", aarch64_unknown_hermit),
     ("x86_64-unknown-hermit", x86_64_unknown_hermit),
 
-    ("aarch64-unknown-none-hermitkernel", aarch64_unknown_none_hermitkernel),
-    ("x86_64-unknown-none-hermitkernel", x86_64_unknown_none_hermitkernel),
-
     ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
+    ("riscv32im-unknown-none-elf", riscv32im_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),
@@ -1025,6 +1027,22 @@
     ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
 }
 
+/// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
+macro_rules! cvs {
+    () => {
+        ::std::borrow::Cow::Borrowed(&[])
+    };
+    ($($x:expr),+ $(,)?) => {
+        ::std::borrow::Cow::Borrowed(&[
+            $(
+                ::std::borrow::Cow::Borrowed($x),
+            )*
+        ])
+    };
+}
+
+pub(crate) use cvs;
+
 /// Warnings encountered when parsing the target `json`.
 ///
 /// Includes fields that weren't recognized and fields that don't have the expected type.
@@ -1063,14 +1081,14 @@
 #[derive(PartialEq, Clone, Debug)]
 pub struct Target {
     /// Target triple to pass to LLVM.
-    pub llvm_target: String,
+    pub llvm_target: StaticCow<str>,
     /// Number of bits in a pointer. Influences the `target_pointer_width` `cfg` variable.
     pub pointer_width: u32,
     /// Architecture to use for ABI considerations. Valid options include: "x86",
     /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others.
-    pub arch: String,
+    pub arch: StaticCow<str>,
     /// [Data layout](https://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
-    pub data_layout: String,
+    pub data_layout: StaticCow<str>,
     /// Optional settings with defaults.
     pub options: TargetOptions,
 }
@@ -1086,6 +1104,8 @@
     }
 }
 
+type StaticCow<T> = Cow<'static, T>;
+
 /// Optional aspects of a target specification.
 ///
 /// This has an implementation of `Default`, see each field for what the default is. In general,
@@ -1102,25 +1122,25 @@
     /// Used as the `target_endian` `cfg` variable. Defaults to little endian.
     pub endian: Endian,
     /// Width of c_int type. Defaults to "32".
-    pub c_int_width: String,
+    pub c_int_width: StaticCow<str>,
     /// OS name to use for conditional compilation (`target_os`). Defaults to "none".
     /// "none" implies a bare metal target without `std` library.
     /// A couple of targets having `std` also use "unknown" as an `os` value,
     /// but they are exceptions.
-    pub os: String,
+    pub os: StaticCow<str>,
     /// Environment name to use for conditional compilation (`target_env`). Defaults to "".
-    pub env: String,
+    pub env: StaticCow<str>,
     /// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance, `"eabi"`
     /// or `"eabihf"`. Defaults to "".
-    pub abi: String,
+    pub abi: StaticCow<str>,
     /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
-    pub vendor: String,
+    pub vendor: StaticCow<str>,
     /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
     /// on the command line. Defaults to `LinkerFlavor::Gcc`.
     pub linker_flavor: LinkerFlavor,
 
     /// Linker to invoke
-    pub linker: Option<String>,
+    pub linker: Option<StaticCow<str>>,
 
     /// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker
     /// without clarifying its flavor in any way.
@@ -1146,7 +1166,7 @@
     /// Linker arguments used in addition to `late_link_args` if at least one
     /// Rust dependency is dynamically linked.
     pub late_link_args_dynamic: LinkArgs,
-    /// Linker arguments used in addition to `late_link_args` if aall Rust
+    /// Linker arguments used in addition to `late_link_args` if all Rust
     /// dependencies are statically linked.
     pub late_link_args_static: LinkArgs,
     /// Linker arguments that are unconditionally passed *after* any
@@ -1155,23 +1175,23 @@
     /// Optional link script applied to `dylib` and `executable` crate types.
     /// This is a string containing the script, not a path. Can only be applied
     /// to linkers where `linker_is_gnu` is true.
-    pub link_script: Option<String>,
+    pub link_script: Option<StaticCow<str>>,
 
     /// Environment variables to be set for the linker invocation.
-    pub link_env: Vec<(String, String)>,
+    pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
     /// Environment variables to be removed for the linker invocation.
-    pub link_env_remove: Vec<String>,
+    pub link_env_remove: StaticCow<[StaticCow<str>]>,
 
     /// Extra arguments to pass to the external assembler (when used)
-    pub asm_args: Vec<String>,
+    pub asm_args: StaticCow<[StaticCow<str>]>,
 
     /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults
     /// to "generic".
-    pub cpu: String,
+    pub cpu: StaticCow<str>,
     /// Default target features to pass to LLVM. These features will *always* be
     /// passed, and cannot be disabled even via `-C`. Corresponds to `llc
     /// -mattr=$features`.
-    pub features: String,
+    pub features: StaticCow<str>,
     /// Whether dynamic linking is available on this target. Defaults to false.
     pub dynamic_linking: bool,
     /// If dynamic linking is available, whether only cdylibs are supported.
@@ -1195,21 +1215,21 @@
     /// Emit each function in its own section. Defaults to true.
     pub function_sections: bool,
     /// String to prepend to the name of every dynamic library. Defaults to "lib".
-    pub dll_prefix: String,
+    pub dll_prefix: StaticCow<str>,
     /// String to append to the name of every dynamic library. Defaults to ".so".
-    pub dll_suffix: String,
+    pub dll_suffix: StaticCow<str>,
     /// String to append to the name of every executable.
-    pub exe_suffix: String,
+    pub exe_suffix: StaticCow<str>,
     /// String to prepend to the name of every static library. Defaults to "lib".
-    pub staticlib_prefix: String,
+    pub staticlib_prefix: StaticCow<str>,
     /// String to append to the name of every static library. Defaults to ".a".
-    pub staticlib_suffix: String,
+    pub staticlib_suffix: StaticCow<str>,
     /// Values of the `target_family` cfg set for this target.
     ///
     /// Common options are: "unix", "windows". Defaults to no families.
     ///
     /// See <https://doc.rust-lang.org/reference/conditional-compilation.html#target_family>.
-    pub families: Vec<String>,
+    pub families: StaticCow<[StaticCow<str>]>,
     /// Whether the target toolchain's ABI supports returning small structs as an integer.
     pub abi_return_struct_as_int: bool,
     /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS,
@@ -1281,7 +1301,7 @@
     /// LLVM to assemble an archive or fall back to the system linker, and
     /// currently only "gnu" is used to fall into LLVM. Unknown strings cause
     /// the system linker to be used.
-    pub archive_format: String,
+    pub archive_format: StaticCow<str>,
     /// Is asm!() allowed? Defaults to true.
     pub allow_asm: bool,
     /// Whether the runtime startup code requires the `main` function be passed
@@ -1297,7 +1317,7 @@
     /// Whether the target requires that emitted object code includes bitcode.
     pub forces_embed_bitcode: bool,
     /// Content of the LLVM cmdline section associated with embedded bitcode.
-    pub bitcode_llvm_cmdline: String,
+    pub bitcode_llvm_cmdline: StaticCow<str>,
 
     /// Don't use this field; instead use the `.min_atomic_width()` method.
     pub min_atomic_width: Option<u64>,
@@ -1369,7 +1389,7 @@
 
     /// If set, have the linker export exactly these symbols, instead of using
     /// the usual logic to figure this out from the crate itself.
-    pub override_export_symbols: Option<Vec<String>>,
+    pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
 
     /// Determines how or whether the MergeFunctions LLVM pass should run for
     /// this target. Either "disabled", "trampolines", or "aliases".
@@ -1380,16 +1400,16 @@
     pub merge_functions: MergeFunctions,
 
     /// Use platform dependent mcount function
-    pub mcount: String,
+    pub mcount: StaticCow<str>,
 
     /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
-    pub llvm_abiname: String,
+    pub llvm_abiname: StaticCow<str>,
 
     /// Whether or not RelaxElfRelocation flag will be passed to the linker
     pub relax_elf_relocations: bool,
 
     /// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
-    pub llvm_args: Vec<String>,
+    pub llvm_args: StaticCow<[StaticCow<str>]>,
 
     /// Whether to use legacy .ctors initialization hooks rather than .init_array. Defaults
     /// to false (uses .init_array).
@@ -1436,20 +1456,20 @@
         TargetOptions {
             is_builtin: false,
             endian: Endian::Little,
-            c_int_width: "32".to_string(),
-            os: "none".to_string(),
-            env: String::new(),
-            abi: String::new(),
-            vendor: "unknown".to_string(),
+            c_int_width: "32".into(),
+            os: "none".into(),
+            env: "".into(),
+            abi: "".into(),
+            vendor: "unknown".into(),
             linker_flavor: LinkerFlavor::Gcc,
-            linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
+            linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
             lld_flavor: LldFlavor::Ld,
             pre_link_args: LinkArgs::new(),
             post_link_args: LinkArgs::new(),
             link_script: None,
-            asm_args: Vec::new(),
-            cpu: "generic".to_string(),
-            features: String::new(),
+            asm_args: cvs![],
+            cpu: "generic".into(),
+            features: "".into(),
             dynamic_linking: false,
             only_cdylib: false,
             executables: false,
@@ -1459,12 +1479,12 @@
             disable_redzone: false,
             frame_pointer: FramePointer::MayOmit,
             function_sections: true,
-            dll_prefix: "lib".to_string(),
-            dll_suffix: ".so".to_string(),
-            exe_suffix: String::new(),
-            staticlib_prefix: "lib".to_string(),
-            staticlib_suffix: ".a".to_string(),
-            families: Vec::new(),
+            dll_prefix: "lib".into(),
+            dll_suffix: ".so".into(),
+            exe_suffix: "".into(),
+            staticlib_prefix: "lib".into(),
+            staticlib_suffix: ".a".into(),
+            families: cvs![],
             abi_return_struct_as_int: false,
             is_like_osx: false,
             is_like_solaris: false,
@@ -1490,15 +1510,15 @@
             late_link_args: LinkArgs::new(),
             late_link_args_dynamic: LinkArgs::new(),
             late_link_args_static: LinkArgs::new(),
-            link_env: Vec::new(),
-            link_env_remove: Vec::new(),
-            archive_format: "gnu".to_string(),
+            link_env: cvs![],
+            link_env_remove: cvs![],
+            archive_format: "gnu".into(),
             main_needs_argc_argv: true,
             allow_asm: true,
             has_thread_local: false,
             obj_is_bitcode: false,
             forces_embed_bitcode: false,
-            bitcode_llvm_cmdline: String::new(),
+            bitcode_llvm_cmdline: "".into(),
             min_atomic_width: None,
             max_atomic_width: None,
             atomic_cas: true,
@@ -1521,10 +1541,10 @@
             limit_rdylib_exports: true,
             override_export_symbols: None,
             merge_functions: MergeFunctions::Aliases,
-            mcount: "mcount".to_string(),
-            llvm_abiname: "".to_string(),
+            mcount: "mcount".into(),
+            llvm_abiname: "".into(),
             relax_elf_relocations: false,
-            llvm_args: vec![],
+            llvm_args: cvs![],
             use_ctors_section: false,
             eh_frame_header: true,
             has_thumb_interworking: false,
@@ -1670,12 +1690,12 @@
         };
 
         let mut base = Target {
-            llvm_target: get_req_field("llvm-target")?,
+            llvm_target: get_req_field("llvm-target")?.into(),
             pointer_width: get_req_field("target-pointer-width")?
                 .parse::<u32>()
                 .map_err(|_| "target-pointer-width must be an integer".to_string())?,
-            data_layout: get_req_field("data-layout")?,
-            arch: get_req_field("arch")?,
+            data_layout: get_req_field("data-layout")?.into(),
+            arch: get_req_field("arch")?.into(),
             options: Default::default(),
         };
 
@@ -1684,13 +1704,13 @@
         macro_rules! key {
             ($key_name:ident) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string)) {
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string).map(Cow::from)) {
                     base.$key_name = s;
                 }
             } );
             ($key_name:ident = $json_name:expr) => ( {
                 let name = $json_name;
-                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string)) {
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string).map(Cow::from)) {
                     base.$key_name = s;
                 }
             } );
@@ -1710,7 +1730,7 @@
                 let name = (stringify!($key_name)).replace("_", "-");
                 if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
                     if s < 1 || s > 5 {
-                        return Err("Not a valid DWARF version number".to_string());
+                        return Err("Not a valid DWARF version number".into());
                     }
                     base.$key_name = Some(s as u32);
                 }
@@ -1812,7 +1832,7 @@
                 if let Some(j) = obj.remove_key(&name){
                     if let Some(v) = Json::as_array(&j) {
                         base.$key_name = v.iter()
-                            .map(|a| a.as_string().unwrap().to_string())
+                            .map(|a| a.as_string().unwrap().to_string().into())
                             .collect();
                     } else {
                         incorrect_type.push(name)
@@ -1824,7 +1844,7 @@
                 if let Some(j) = obj.remove_key(&name) {
                     if let Some(v) = Json::as_array(&j) {
                         base.$key_name = Some(v.iter()
-                            .map(|a| a.as_string().unwrap().to_string())
+                            .map(|a| a.as_string().unwrap().to_string().into())
                             .collect());
                     } else {
                         incorrect_type.push(name)
@@ -1836,7 +1856,7 @@
                 if let Some(o) = obj.remove_key(&name[..]) {
                     base.$key_name = o
                         .as_string()
-                        .map(|s| s.to_string() );
+                        .map(|s| s.to_string().into());
                 }
             } );
             ($key_name:ident, LldFlavor) => ( {
@@ -1930,7 +1950,7 @@
                             .map(|(i,s)| {
                                 let s = s.as_string().ok_or_else(||
                                     format!("{}.{}[{}]: expected a JSON string", name, k, i))?;
-                                Ok(s.to_owned())
+                                Ok(s.to_string().into())
                             })
                             .collect::<Result<Vec<_>, String>>()?;
 
@@ -1957,7 +1977,7 @@
                             .map(|(i,s)| {
                                 let s = s.as_string().ok_or_else(||
                                     format!("{}.{}[{}]: expected a JSON string", name, k, i))?;
-                                Ok(s.to_owned())
+                                Ok(s.to_string().into())
                             })
                             .collect::<Result<Vec<_>, String>>()?;
 
@@ -1976,7 +1996,7 @@
                                 if p.len() == 2 {
                                     let k = p[0].to_string();
                                     let v = p[1].to_string();
-                                    base.$key_name.push((k, v));
+                                    base.$key_name.to_mut().push((k.into(), v.into()));
                                 }
                             }
                         }
@@ -1999,10 +2019,10 @@
                 if let Some(value) = obj.remove_key("target-family") {
                     if let Some(v) = Json::as_array(&value) {
                         base.$key_name = v.iter()
-                            .map(|a| a.as_string().unwrap().to_string())
+                            .map(|a| a.as_string().unwrap().to_string().into())
                             .collect();
                     } else if let Some(v) = Json::as_string(&value) {
-                        base.$key_name = vec![v.to_string()];
+                        base.$key_name = vec![v.to_string().into()].into();
                     }
                 }
             } );
@@ -2012,7 +2032,7 @@
             if let Some(s) = Json::as_string(&j) {
                 base.endian = s.parse()?;
             } else {
-                incorrect_type.push("target-endian".to_string())
+                incorrect_type.push("target-endian".into())
             }
         }
 
@@ -2022,7 +2042,7 @@
                     .parse()
                     .map_err(|()| format!("'{}' is not a valid value for frame-pointer", s))?;
             } else {
-                incorrect_type.push("frame-pointer".to_string())
+                incorrect_type.push("frame-pointer".into())
             }
         }
 
@@ -2127,7 +2147,7 @@
 
         if base.is_builtin {
             // This can cause unfortunate ICEs later down the line.
-            return Err("may not set is_builtin for targets not built-in".to_string());
+            return Err("may not set is_builtin for targets not built-in".into());
         }
         // 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();
@@ -2137,6 +2157,18 @@
         ))
     }
 
+    /// Load a built-in target
+    pub fn expect_builtin(target_triple: &TargetTriple) -> Target {
+        match *target_triple {
+            TargetTriple::TargetTriple(ref target_triple) => {
+                load_builtin(target_triple).expect("built-in target")
+            }
+            TargetTriple::TargetPath(..) => {
+                panic!("built-in targets doens't support target-paths")
+            }
+        }
+    }
+
     /// Search for a JSON file specifying the given target triple.
     ///
     /// If none is found in `$RUST_TARGET_PATH`, look for a file called `target.json` inside the
@@ -2219,7 +2251,7 @@
             }};
             ($attr:ident, $key_name:expr) => {{
                 let name = $key_name;
-                d.insert(name.to_string(), self.$attr.to_json());
+                d.insert(name.into(), self.$attr.to_json());
             }};
         }
 
@@ -2233,7 +2265,7 @@
             ($attr:ident, $key_name:expr) => {{
                 let name = $key_name;
                 if default.$attr != self.$attr {
-                    d.insert(name.to_string(), self.$attr.to_json());
+                    d.insert(name.into(), self.$attr.to_json());
                 }
             }};
             (link_args - $attr:ident) => {{
@@ -2242,7 +2274,7 @@
                     let obj = self
                         .$attr
                         .iter()
-                        .map(|(k, v)| (k.desc().to_owned(), v.clone()))
+                        .map(|(k, v)| (k.desc().to_string(), v.clone()))
                         .collect::<BTreeMap<_, _>>();
                     d.insert(name, obj.to_json());
                 }
@@ -2253,7 +2285,7 @@
                     let obj = self
                         .$attr
                         .iter()
-                        .map(|&(ref k, ref v)| k.clone() + "=" + &v)
+                        .map(|&(ref k, ref v)| format!("{k}={v}"))
                         .collect::<Vec<_>>();
                     d.insert(name, obj.to_json());
                 }
@@ -2366,7 +2398,7 @@
         target_option_val!(supports_stack_protector);
 
         if let Some(abi) = self.default_adjusted_cabi {
-            d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json());
+            d.insert("default-adjusted-cabi".into(), Abi::name(abi).to_json());
         }
 
         Json::Object(d)
@@ -2383,7 +2415,7 @@
 impl TargetTriple {
     /// Creates a target triple from the passed target triple string.
     pub fn from_triple(triple: &str) -> Self {
-        TargetTriple::TargetTriple(triple.to_string())
+        TargetTriple::TargetTriple(triple.into())
     }
 
     /// Creates a target triple from the passed target path.
@@ -2421,7 +2453,7 @@
             let hash = hasher.finish();
             format!("{}-{}", triple, hash)
         } else {
-            triple.to_owned()
+            triple.into()
         }
     }
 }
diff --git a/compiler/rustc_target/src/spec/msp430_none_elf.rs b/compiler/rustc_target/src/spec/msp430_none_elf.rs
index 6e3a241..cedacb6 100644
--- a/compiler/rustc_target/src/spec/msp430_none_elf.rs
+++ b/compiler/rustc_target/src/spec/msp430_none_elf.rs
@@ -1,22 +1,22 @@
-use crate::spec::{PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{cvs, PanicStrategy, RelocModel, Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "msp430-none-elf".to_string(),
+        llvm_target: "msp430-none-elf".into(),
         pointer_width: 16,
-        data_layout: "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16".to_string(),
-        arch: "msp430".to_string(),
+        data_layout: "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16".into(),
+        arch: "msp430".into(),
 
         options: TargetOptions {
-            c_int_width: "16".to_string(),
+            c_int_width: "16".into(),
             executables: true,
 
             // The LLVM backend currently can't generate object files. To
             // workaround this LLVM generates assembly files which then we feed
             // to gcc to get object files. For this reason we have a hard
             // dependency on this specific gcc.
-            asm_args: vec!["-mcpu=msp430".to_string()],
-            linker: Some("msp430-elf-gcc".to_string()),
+            asm_args: cvs!["-mcpu=msp430"],
+            linker: Some("msp430-elf-gcc".into()),
             linker_is_gnu: false,
 
             // There are no atomic CAS instructions available in the MSP430
diff --git a/compiler/rustc_target/src/spec/msvc_base.rs b/compiler/rustc_target/src/spec/msvc_base.rs
index f1ed4c1..00cc962 100644
--- a/compiler/rustc_target/src/spec/msvc_base.rs
+++ b/compiler/rustc_target/src/spec/msvc_base.rs
@@ -4,7 +4,7 @@
     let pre_link_args_msvc = vec![
         // Suppress the verbose logo and authorship debugging output, which would needlessly
         // clog any log files.
-        "/NOLOGO".to_string(),
+        "/NOLOGO".into(),
     ];
     let mut pre_link_args = LinkArgs::new();
     pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone());
diff --git a/compiler/rustc_target/src/spec/netbsd_base.rs b/compiler/rustc_target/src/spec/netbsd_base.rs
index 6bb6083..69016d7 100644
--- a/compiler/rustc_target/src/spec/netbsd_base.rs
+++ b/compiler/rustc_target/src/spec/netbsd_base.rs
@@ -1,11 +1,11 @@
-use crate::spec::{RelroLevel, TargetOptions};
+use crate::spec::{cvs, RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        os: "netbsd".to_string(),
+        os: "netbsd".into(),
         dynamic_linking: true,
         executables: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         no_default_libraries: false,
         has_rpath: true,
         position_independent_executables: true,
diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
index ba32a31..9d94ed8 100644
--- a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
+++ b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
@@ -2,21 +2,21 @@
 
 pub fn target() -> Target {
     Target {
-        arch: "nvptx64".to_string(),
-        data_layout: "e-i64:64-i128:128-v16:16-v32:32-n16:32:64".to_string(),
-        llvm_target: "nvptx64-nvidia-cuda".to_string(),
+        arch: "nvptx64".into(),
+        data_layout: "e-i64:64-i128:128-v16:16-v32:32-n16:32:64".into(),
+        llvm_target: "nvptx64-nvidia-cuda".into(),
         pointer_width: 64,
 
         options: TargetOptions {
-            os: "cuda".to_string(),
-            vendor: "nvidia".to_string(),
+            os: "cuda".into(),
+            vendor: "nvidia".into(),
             linker_flavor: LinkerFlavor::PtxLinker,
             // The linker can be installed from `crates.io`.
-            linker: Some("rust-ptx-linker".to_string()),
+            linker: Some("rust-ptx-linker".into()),
             linker_is_gnu: false,
 
             // With `ptx-linker` approach, it can be later overridden via link flags.
-            cpu: "sm_30".to_string(),
+            cpu: "sm_30".into(),
 
             // FIXME: create tests for the atomics.
             max_atomic_width: Some(64),
@@ -36,9 +36,9 @@
             obj_is_bitcode: true,
 
             // Convenient and predicable naming scheme.
-            dll_prefix: "".to_string(),
-            dll_suffix: ".ptx".to_string(),
-            exe_suffix: ".ptx".to_string(),
+            dll_prefix: "".into(),
+            dll_suffix: ".ptx".into(),
+            exe_suffix: ".ptx".into(),
 
             // Disable MergeFunctions LLVM optimisation pass because it can
             // produce kernel functions that call other kernel functions.
diff --git a/compiler/rustc_target/src/spec/openbsd_base.rs b/compiler/rustc_target/src/spec/openbsd_base.rs
index 70e9e4a..bbd322b 100644
--- a/compiler/rustc_target/src/spec/openbsd_base.rs
+++ b/compiler/rustc_target/src/spec/openbsd_base.rs
@@ -1,11 +1,11 @@
-use crate::spec::{FramePointer, RelroLevel, TargetOptions};
+use crate::spec::{cvs, FramePointer, RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        os: "openbsd".to_string(),
+        os: "openbsd".into(),
         dynamic_linking: true,
         executables: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         has_rpath: true,
         abi_return_struct_as_int: true,
         position_independent_executables: true,
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
index b3d6b7c..595769c 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
@@ -3,15 +3,15 @@
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
-    base.cpu = "ppc64".to_string();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.cpu = "ppc64".into();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "powerpc64-unknown-freebsd".to_string(),
+        llvm_target: "powerpc64-unknown-freebsd".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64".to_string(),
-        arch: "powerpc64".to_string(),
-        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
+        data_layout: "E-m:e-i64:64-n32:64".into(),
+        arch: "powerpc64".into(),
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
     }
 }
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 f10d4d4..24d5d18 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
@@ -3,8 +3,8 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.cpu = "ppc64".to_string();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.cpu = "ppc64".into();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     base.max_atomic_width = Some(64);
 
     // ld.so in at least RHEL6 on ppc64 has a bug related to BIND_NOW, so only enable partial RELRO
@@ -12,10 +12,10 @@
     base.relro_level = RelroLevel::Partial;
 
     Target {
-        llvm_target: "powerpc64-unknown-linux-gnu".to_string(),
+        llvm_target: "powerpc64-unknown-linux-gnu".into(),
         pointer_width: 64,
-        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 },
+        data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+        arch: "powerpc64".into(),
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..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 6116217..0f465cc 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
@@ -3,15 +3,15 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.cpu = "ppc64".to_string();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.cpu = "ppc64".into();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "powerpc64-unknown-linux-musl".to_string(),
+        llvm_target: "powerpc64-unknown-linux-musl".into(),
         pointer_width: 64,
-        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 },
+        data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+        arch: "powerpc64".into(),
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
index 9c63997..491d344 100644
--- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
@@ -3,15 +3,15 @@
 
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
-    base.cpu = "ppc64".to_string();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.cpu = "ppc64".into();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "powerpc64-unknown-linux-gnu".to_string(),
+        llvm_target: "powerpc64-unknown-linux-gnu".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".to_string(),
-        arch: "powerpc64".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+        arch: "powerpc64".into(),
         options: TargetOptions { endian: Endian::Big, ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
index 283e9f7..b198e66 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
-    base.cpu = "ppc64le".to_string();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.cpu = "ppc64le".into();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "powerpc64le-unknown-freebsd".to_string(),
+        llvm_target: "powerpc64le-unknown-freebsd".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-i64:64-n32:64".to_string(),
-        arch: "powerpc64".to_string(),
-        options: TargetOptions { mcount: "_mcount".to_string(), ..base },
+        data_layout: "e-m:e-i64:64-n32:64".into(),
+        arch: "powerpc64".into(),
+        options: TargetOptions { mcount: "_mcount".into(), ..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 f645ece..09e3936 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.cpu = "ppc64le".to_string();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.cpu = "ppc64le".into();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "powerpc64le-unknown-linux-gnu".to_string(),
+        llvm_target: "powerpc64le-unknown-linux-gnu".into(),
         pointer_width: 64,
-        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 },
+        data_layout: "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+        arch: "powerpc64".into(),
+        options: TargetOptions { mcount: "_mcount".into(), ..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 934371f..8a947b0 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.cpu = "ppc64le".to_string();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.cpu = "ppc64le".into();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "powerpc64le-unknown-linux-musl".to_string(),
+        llvm_target: "powerpc64le-unknown-linux-musl".into(),
         pointer_width: 64,
-        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 },
+        data_layout: "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+        arch: "powerpc64".into(),
+        options: TargetOptions { mcount: "_mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
index e113180..c27b847 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
@@ -3,24 +3,24 @@
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
     // 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());
+        .push("--target=powerpc-unknown-freebsd13.0".into());
     base.max_atomic_width = Some(32);
 
     Target {
-        llvm_target: "powerpc-unknown-freebsd13.0".to_string(),
+        llvm_target: "powerpc-unknown-freebsd13.0".into(),
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
-        arch: "powerpc".to_string(),
+        data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+        arch: "powerpc".into(),
         options: TargetOptions {
             endian: Endian::Big,
-            features: "+secure-plt".to_string(),
+            features: "+secure-plt".into(),
             relocation_model: RelocModel::Pic,
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
index 21ffdd2..88f6150 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
@@ -3,14 +3,14 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
     base.max_atomic_width = Some(32);
 
     Target {
-        llvm_target: "powerpc-unknown-linux-gnu".to_string(),
+        llvm_target: "powerpc-unknown-linux-gnu".into(),
         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, mcount: "_mcount".to_string(), ..base },
+        data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+        arch: "powerpc".into(),
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
index 362d8a1..3ee5487 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
@@ -3,18 +3,18 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".into());
     base.max_atomic_width = Some(32);
 
     Target {
-        llvm_target: "powerpc-unknown-linux-gnuspe".to_string(),
+        llvm_target: "powerpc-unknown-linux-gnuspe".into(),
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
-        arch: "powerpc".to_string(),
+        data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+        arch: "powerpc".into(),
         options: TargetOptions {
-            abi: "spe".to_string(),
+            abi: "spe".into(),
             endian: Endian::Big,
-            mcount: "_mcount".to_string(),
+            mcount: "_mcount".into(),
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
index 9633705..ce33c78 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
@@ -3,14 +3,14 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
     base.max_atomic_width = Some(32);
 
     Target {
-        llvm_target: "powerpc-unknown-linux-musl".to_string(),
+        llvm_target: "powerpc-unknown-linux-musl".into(),
         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, mcount: "_mcount".to_string(), ..base },
+        data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+        arch: "powerpc".into(),
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
index 4cc5224..998225f 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
@@ -3,14 +3,14 @@
 
 pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
     base.max_atomic_width = Some(32);
 
     Target {
-        llvm_target: "powerpc-unknown-netbsd".to_string(),
+        llvm_target: "powerpc-unknown-netbsd".into(),
         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, mcount: "__mcount".to_string(), ..base },
+        data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+        arch: "powerpc".into(),
+        options: TargetOptions { endian: Endian::Big, mcount: "__mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
index c17183f..ad2c3d40 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
@@ -7,10 +7,10 @@
     base.max_atomic_width = Some(32);
 
     Target {
-        llvm_target: "powerpc-unknown-openbsd".to_string(),
+        llvm_target: "powerpc-unknown-openbsd".into(),
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
-        arch: "powerpc".to_string(),
+        data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+        arch: "powerpc".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
index 2f0a6ca..76709ce 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
@@ -3,15 +3,15 @@
 
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".into());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".into());
     base.max_atomic_width = Some(32);
 
     Target {
-        llvm_target: "powerpc-unknown-linux-gnu".to_string(),
+        llvm_target: "powerpc-unknown-linux-gnu".into(),
         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(), ..base },
+        data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+        arch: "powerpc".into(),
+        options: TargetOptions { endian: Endian::Big, features: "+secure-plt".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
index a2b85f7..7b5d124 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
@@ -3,20 +3,20 @@
 
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".to_string());
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mspe".into());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("--secure-plt".into());
     base.max_atomic_width = Some(32);
 
     Target {
-        llvm_target: "powerpc-unknown-linux-gnuspe".to_string(),
+        llvm_target: "powerpc-unknown-linux-gnuspe".into(),
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
-        arch: "powerpc".to_string(),
+        data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+        arch: "powerpc".into(),
         options: TargetOptions {
-            abi: "spe".to_string(),
+            abi: "spe".into(),
             endian: Endian::Big,
             // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2
-            features: "+secure-plt,+msync".to_string(),
+            features: "+secure-plt,+msync".into(),
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/redox_base.rs b/compiler/rustc_target/src/spec/redox_base.rs
index bcb536b..1878cc3 100644
--- a/compiler/rustc_target/src/spec/redox_base.rs
+++ b/compiler/rustc_target/src/spec/redox_base.rs
@@ -1,12 +1,12 @@
-use crate::spec::{RelroLevel, TargetOptions};
+use crate::spec::{cvs, RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        os: "redox".to_string(),
-        env: "relibc".to_string(),
+        os: "redox".into(),
+        env: "relibc".into(),
         dynamic_linking: true,
         executables: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         has_rpath: true,
         position_independent_executables: true,
         relro_level: RelroLevel::Full,
diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs
index a9cdad1..bffd377 100644
--- a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "riscv32-unknown-linux-gnu".to_string(),
+        llvm_target: "riscv32-unknown-linux-gnu".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
-        arch: "riscv32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+        arch: "riscv32".into(),
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
-            cpu: "generic-rv32".to_string(),
-            features: "+m,+a,+f,+d,+c".to_string(),
-            llvm_abiname: "ilp32d".to_string(),
+            cpu: "generic-rv32".into(),
+            features: "+m,+a,+f,+d,+c".into(),
+            llvm_abiname: "ilp32d".into(),
             max_atomic_width: Some(32),
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs
index a64a82d..c9f3acf 100644
--- a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "riscv32-unknown-linux-musl".to_string(),
+        llvm_target: "riscv32-unknown-linux-musl".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
-        arch: "riscv32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+        arch: "riscv32".into(),
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
-            cpu: "generic-rv32".to_string(),
-            features: "+m,+a,+f,+d,+c".to_string(),
-            llvm_abiname: "ilp32d".to_string(),
+            cpu: "generic-rv32".into(),
+            features: "+m,+a,+f,+d,+c".into(),
+            llvm_abiname: "ilp32d".into(),
             max_atomic_width: Some(32),
             ..super::linux_musl_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs
index 16d3721..7124e2d 100644
--- a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs
@@ -3,15 +3,15 @@
 
 pub fn target() -> Target {
     Target {
-        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
-        llvm_target: "riscv32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+        llvm_target: "riscv32".into(),
         pointer_width: 32,
-        arch: "riscv32".to_string(),
+        arch: "riscv32".into(),
 
         options: TargetOptions {
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-            linker: Some("rust-lld".to_string()),
-            cpu: "generic-rv32".to_string(),
+            linker: Some("rust-lld".into()),
+            cpu: "generic-rv32".into(),
             max_atomic_width: Some(0),
             atomic_cas: false,
             executables: true,
diff --git a/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs
new file mode 100644
index 0000000..508982ee
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs
@@ -0,0 +1,26 @@
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+        llvm_target: "riscv32".into(),
+        pointer_width: 32,
+        arch: "riscv32".into(),
+
+        options: TargetOptions {
+            linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+            linker: Some("rust-lld".into()),
+            cpu: "generic-rv32".into(),
+            max_atomic_width: Some(0),
+            atomic_cas: false,
+            features: "+m".into(),
+            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/riscv32imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs
index b53bae6..f2bd624 100644
--- a/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs
@@ -3,17 +3,17 @@
 
 pub fn target() -> Target {
     Target {
-        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
-        llvm_target: "riscv32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+        llvm_target: "riscv32".into(),
         pointer_width: 32,
-        arch: "riscv32".to_string(),
+        arch: "riscv32".into(),
 
         options: TargetOptions {
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-            linker: Some("rust-lld".to_string()),
-            cpu: "generic-rv32".to_string(),
+            linker: Some("rust-lld".into()),
+            cpu: "generic-rv32".into(),
             max_atomic_width: Some(32),
-            features: "+m,+a,+c".to_string(),
+            features: "+m,+a,+c".into(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
index fb084af..0200862 100644
--- a/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
@@ -1,31 +1,31 @@
+use crate::spec::{cvs, Target, TargetOptions};
 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(),
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+        llvm_target: "riscv32".into(),
         pointer_width: 32,
-        arch: "riscv32".to_string(),
+        arch: "riscv32".into(),
 
         options: TargetOptions {
-            families: vec!["unix".to_string()],
-            os: "espidf".to_string(),
-            env: "newlib".to_string(),
-            vendor: "espressif".to_string(),
+            families: cvs!["unix"],
+            os: "espidf".into(),
+            env: "newlib".into(),
+            vendor: "espressif".into(),
             linker_flavor: LinkerFlavor::Gcc,
-            linker: Some("riscv32-esp-elf-gcc".to_string()),
-            cpu: "generic-rv32".to_string(),
+            linker: Some("riscv32-esp-elf-gcc".into()),
+            cpu: "generic-rv32".into(),
 
             // 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)`
+            // the __atomic* and __sync* GCC builtins, so setting `max_atomic_width` to `Some(64)`
             // 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),
+            max_atomic_width: Some(64),
             atomic_cas: true,
 
-            features: "+m,+c".to_string(),
+            features: "+m,+c".into(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs
index 9a23def..4216968 100644
--- a/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs
@@ -3,18 +3,18 @@
 
 pub fn target() -> Target {
     Target {
-        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
-        llvm_target: "riscv32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+        llvm_target: "riscv32".into(),
         pointer_width: 32,
-        arch: "riscv32".to_string(),
+        arch: "riscv32".into(),
 
         options: TargetOptions {
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-            linker: Some("rust-lld".to_string()),
-            cpu: "generic-rv32".to_string(),
+            linker: Some("rust-lld".into()),
+            cpu: "generic-rv32".into(),
             max_atomic_width: Some(0),
             atomic_cas: false,
-            features: "+m,+c".to_string(),
+            features: "+m,+c".into(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs
index 1ea1b9b..0539eca6 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "riscv64-unknown-freebsd".to_string(),
+        llvm_target: "riscv64-unknown-freebsd".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
-        arch: "riscv64".to_string(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        arch: "riscv64".into(),
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
-            cpu: "generic-rv64".to_string(),
-            features: "+m,+a,+f,+d,+c".to_string(),
-            llvm_abiname: "lp64d".to_string(),
+            cpu: "generic-rv64".into(),
+            features: "+m,+a,+f,+d,+c".into(),
+            llvm_abiname: "lp64d".into(),
             max_atomic_width: Some(64),
             ..super::freebsd_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs
index 02d44b5..7d1bf22 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "riscv64-unknown-linux-gnu".to_string(),
+        llvm_target: "riscv64-unknown-linux-gnu".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
-        arch: "riscv64".to_string(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        arch: "riscv64".into(),
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
-            cpu: "generic-rv64".to_string(),
-            features: "+m,+a,+f,+d,+c".to_string(),
-            llvm_abiname: "lp64d".to_string(),
+            cpu: "generic-rv64".into(),
+            features: "+m,+a,+f,+d,+c".into(),
+            llvm_abiname: "lp64d".into(),
             max_atomic_width: Some(64),
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
index 3754750..f04f8a4 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "riscv64-unknown-linux-musl".to_string(),
+        llvm_target: "riscv64-unknown-linux-musl".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
-        arch: "riscv64".to_string(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        arch: "riscv64".into(),
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
-            cpu: "generic-rv64".to_string(),
-            features: "+m,+a,+f,+d,+c".to_string(),
-            llvm_abiname: "lp64d".to_string(),
+            cpu: "generic-rv64".into(),
+            features: "+m,+a,+f,+d,+c".into(),
+            llvm_abiname: "lp64d".into(),
             max_atomic_width: Some(64),
             ..super::linux_musl_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
index f527a6c..2a93459e 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
@@ -3,18 +3,18 @@
 
 pub fn target() -> Target {
     Target {
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
-        llvm_target: "riscv64".to_string(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        llvm_target: "riscv64".into(),
         pointer_width: 64,
-        arch: "riscv64".to_string(),
+        arch: "riscv64".into(),
 
         options: TargetOptions {
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-            linker: Some("rust-lld".to_string()),
-            llvm_abiname: "lp64d".to_string(),
-            cpu: "generic-rv64".to_string(),
+            linker: Some("rust-lld".into()),
+            llvm_abiname: "lp64d".into(),
+            cpu: "generic-rv64".into(),
             max_atomic_width: Some(64),
-            features: "+m,+a,+f,+d,+c".to_string(),
+            features: "+m,+a,+f,+d,+c".into(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
index 8b1ba88..6a8d8a9 100644
--- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
@@ -3,17 +3,17 @@
 
 pub fn target() -> Target {
     Target {
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
-        llvm_target: "riscv64".to_string(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        llvm_target: "riscv64".into(),
         pointer_width: 64,
-        arch: "riscv64".to_string(),
+        arch: "riscv64".into(),
 
         options: TargetOptions {
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-            linker: Some("rust-lld".to_string()),
-            cpu: "generic-rv64".to_string(),
+            linker: Some("rust-lld".into()),
+            cpu: "generic-rv64".into(),
             max_atomic_width: Some(64),
-            features: "+m,+a,+c".to_string(),
+            features: "+m,+a,+c".into(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
index 4eeea9b..8757bbe 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
@@ -5,19 +5,19 @@
     let mut base = super::linux_gnu_base::opts();
     base.endian = Endian::Big;
     // z10 is the oldest CPU supported by LLVM
-    base.cpu = "z10".to_string();
+    base.cpu = "z10".into();
     // FIXME: The data_layout string below and the ABI implementation in
     // cabi_s390x.rs are for now hard-coded to assume the no-vector ABI.
     // Pass the -vector feature string to LLVM to respect this assumption.
-    base.features = "-vector".to_string();
+    base.features = "-vector".into();
     base.max_atomic_width = Some(64);
     base.min_global_align = Some(16);
 
     Target {
-        llvm_target: "s390x-unknown-linux-gnu".to_string(),
+        llvm_target: "s390x-unknown-linux-gnu".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".to_string(),
-        arch: "s390x".to_string(),
+        data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".into(),
+        arch: "s390x".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
index 4f811ce..4c85527 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
@@ -5,20 +5,20 @@
     let mut base = super::linux_musl_base::opts();
     base.endian = Endian::Big;
     // z10 is the oldest CPU supported by LLVM
-    base.cpu = "z10".to_string();
+    base.cpu = "z10".into();
     // FIXME: The data_layout string below and the ABI implementation in
     // cabi_s390x.rs are for now hard-coded to assume the no-vector ABI.
     // Pass the -vector feature string to LLVM to respect this assumption.
-    base.features = "-vector".to_string();
+    base.features = "-vector".into();
     base.max_atomic_width = Some(64);
     base.min_global_align = Some(16);
     base.static_position_independent_executables = true;
 
     Target {
-        llvm_target: "s390x-unknown-linux-musl".to_string(),
+        llvm_target: "s390x-unknown-linux-musl".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".to_string(),
-        arch: "s390x".to_string(),
+        data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".into(),
+        arch: "s390x".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/solaris_base.rs b/compiler/rustc_target/src/spec/solaris_base.rs
index bc32b50..d61e1b2 100644
--- a/compiler/rustc_target/src/spec/solaris_base.rs
+++ b/compiler/rustc_target/src/spec/solaris_base.rs
@@ -1,12 +1,12 @@
-use crate::spec::TargetOptions;
+use crate::spec::{cvs, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        os: "solaris".to_string(),
+        os: "solaris".into(),
         dynamic_linking: true,
         executables: true,
         has_rpath: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         is_like_solaris: true,
         linker_is_gnu: false,
         limit_rdylib_exports: false, // Linker doesn't support this
diff --git a/compiler/rustc_target/src/spec/solid_base.rs b/compiler/rustc_target/src/spec/solid_base.rs
index 421cfc4..c5602a4 100644
--- a/compiler/rustc_target/src/spec/solid_base.rs
+++ b/compiler/rustc_target/src/spec/solid_base.rs
@@ -3,8 +3,8 @@
 
 pub fn opts(kernel: &str) -> TargetOptions {
     TargetOptions {
-        os: format!("solid_{}", kernel),
-        vendor: "kmc".to_string(),
+        os: format!("solid_{}", kernel).into(),
+        vendor: "kmc".into(),
         frame_pointer: FramePointer::NonLeaf,
         has_thread_local: true,
         ..Default::default()
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
index e1aa488..39efd8f 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
@@ -4,14 +4,14 @@
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.endian = Endian::Big;
-    base.cpu = "v9".to_string();
+    base.cpu = "v9".into();
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "sparc64-unknown-linux-gnu".to_string(),
+        llvm_target: "sparc64-unknown-linux-gnu".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
-        arch: "sparc64".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+        arch: "sparc64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
index b4286df..718303a 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
@@ -3,15 +3,15 @@
 
 pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
-    base.cpu = "v9".to_string();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.cpu = "v9".into();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "sparc64-unknown-netbsd".to_string(),
+        llvm_target: "sparc64-unknown-netbsd".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
-        arch: "sparc64".to_string(),
-        options: TargetOptions { endian: Endian::Big, mcount: "__mcount".to_string(), ..base },
+        data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+        arch: "sparc64".into(),
+        options: TargetOptions { endian: Endian::Big, mcount: "__mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
index 9732983..2aaa0ca 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
@@ -4,15 +4,15 @@
 pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
     base.endian = Endian::Big;
-    base.cpu = "v9".to_string();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.cpu = "v9".into();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "sparc64-unknown-openbsd".to_string(),
+        llvm_target: "sparc64-unknown-openbsd".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
-        arch: "sparc64".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+        arch: "sparc64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
index 1fd4cad..71d3de0 100644
--- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
@@ -4,15 +4,15 @@
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.endian = Endian::Big;
-    base.cpu = "v9".to_string();
+    base.cpu = "v9".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mv8plus".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mv8plus".into());
 
     Target {
-        llvm_target: "sparc-unknown-linux-gnu".to_string(),
+        llvm_target: "sparc-unknown-linux-gnu".into(),
         pointer_width: 32,
-        data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".to_string(),
-        arch: "sparc".to_string(),
+        data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(),
+        arch: "sparc".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
index abc46a8..79ae54a 100644
--- a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
@@ -4,21 +4,21 @@
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
     base.endian = Endian::Big;
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]);
     // llvm calls this "v9"
-    base.cpu = "v9".to_string();
-    base.vendor = "sun".to_string();
+    base.cpu = "v9".into();
+    base.vendor = "sun".into();
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "sparcv9-sun-solaris".to_string(),
+        llvm_target: "sparcv9-sun-solaris".into(),
         pointer_width: 64,
-        data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128".into(),
         // Use "sparc64" instead of "sparcv9" here, since the former is already
         // used widely in the source base.  If we ever needed ABI
         // differentiation from the sparc64, we could, but that would probably
         // just be confusing.
-        arch: "sparc64".to_string(),
+        arch: "sparc64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs
index e2e5285..ef6038e 100644
--- a/compiler/rustc_target/src/spec/thumb_base.rs
+++ b/compiler/rustc_target/src/spec/thumb_base.rs
@@ -36,7 +36,7 @@
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
         executables: true,
         // In most cases, LLD is good enough
-        linker: Some("rust-lld".to_string()),
+        linker: Some("rust-lld".into()),
         // Because these devices have very little resources having an unwinder is too onerous so we
         // default to "abort" because the "unwind" strategy is very rare.
         panic_strategy: PanicStrategy::Abort,
diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
index f86efd5..8d6130a 100644
--- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
@@ -8,13 +8,13 @@
 //!
 //! **Important:** This target profile **does not** specify a linker script. You just get the default link script when you build a binary for this target. The default link script is very likely wrong, so you should use `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
 
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{cvs, LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "thumbv4t-none-eabi".to_string(),
+        llvm_target: "thumbv4t-none-eabi".into(),
         pointer_width: 32,
-        arch: "arm".to_string(),
+        arch: "arm".into(),
         /* Data layout args are '-' separated:
          * little endian
          * stack is 64-bit aligned (EABI)
@@ -24,24 +24,20 @@
          * native integers are 32-bit
          * All other elements are default
          */
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
+            abi: "eabi".into(),
             linker_flavor: LinkerFlavor::Ld,
-            linker: Some("arm-none-eabi-ld".to_string()),
+            linker: Some("arm-none-eabi-ld".into()),
 
             // extra args passed to the external assembler (assuming `arm-none-eabi-as`):
             // * activate t32/a32 interworking
             // * use arch ARMv4T
             // * use little-endian
-            asm_args: vec![
-                "-mthumb-interwork".to_string(),
-                "-march=armv4t".to_string(),
-                "-mlittle-endian".to_string(),
-            ],
+            asm_args: cvs!["-mthumb-interwork", "-march=armv4t", "-mlittle-endian",],
 
             // minimum extra features, these cannot be disabled via -C
-            features: "+soft-float,+strict-align".to_string(),
+            features: "+soft-float,+strict-align".into(),
 
             main_needs_argc_argv: false,
 
diff --git a/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs
index 40e3281..2546ab9 100644
--- a/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs
@@ -4,16 +4,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "thumbv6m-none-eabi".to_string(),
+        llvm_target: "thumbv6m-none-eabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            abi: "eabi".to_string(),
+            abi: "eabi".into(),
             // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them
             // with +strict-align.
-            features: "+strict-align".to_string(),
+            features: "+strict-align".into(),
             // There are no atomic CAS instructions available in the instruction set of the ARMv6-M
             // architecture
             atomic_cas: false,
diff --git a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
index 369e6cd..f6cbbd3 100644
--- a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
@@ -9,20 +9,20 @@
     // should be smart enough to insert branch islands only
     // where necessary, but this is not the observed behavior.
     // Disabling the LBR optimization works around the issue.
-    let pre_link_args_msvc = "/OPT:NOLBR".to_string();
-    base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().push(pre_link_args_msvc.clone());
+    let pre_link_args_msvc = "/OPT:NOLBR";
+    base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().push(pre_link_args_msvc.into());
     base.pre_link_args
         .entry(LinkerFlavor::Lld(LldFlavor::Link))
         .or_default()
-        .push(pre_link_args_msvc);
+        .push(pre_link_args_msvc.into());
 
     Target {
-        llvm_target: "thumbv7a-pc-windows-msvc".to_string(),
+        llvm_target: "thumbv7a-pc-windows-msvc".into(),
         pointer_width: 32,
-        data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            features: "+vfp3,+neon".to_string(),
+            features: "+vfp3,+neon".into(),
             max_atomic_width: Some(64),
             // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
             // implemented for windows/arm in LLVM
diff --git a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs
index 72d39ef..65c2f5a 100644
--- a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs
@@ -2,12 +2,12 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "thumbv7a-pc-windows-msvc".to_string(),
+        llvm_target: "thumbv7a-pc-windows-msvc".into(),
         pointer_width: 32,
-        data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            features: "+vfp3,+neon".to_string(),
+            features: "+vfp3,+neon".into(),
             max_atomic_width: Some(64),
             // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
             // implemented for windows/arm in LLVM
diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs
index 107474a..000e5f2 100644
--- a/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs
@@ -13,13 +13,13 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "thumbv7em-none-eabi".to_string(),
+        llvm_target: "thumbv7em-none-eabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            abi: "eabi".to_string(),
+            abi: "eabi".into(),
             max_atomic_width: Some(32),
             ..super::thumb_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs b/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs
index 65fc0db..39a7256 100644
--- a/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs
@@ -12,13 +12,13 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "thumbv7em-none-eabihf".to_string(),
+        llvm_target: "thumbv7em-none-eabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
             // Cortex-M7 (vfp5)
             // `-d32` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
@@ -28,7 +28,7 @@
             //
             // Reference:
             // ARMv7-M Architecture Reference Manual - A2.5 The optional floating-point extension
-            features: "+vfp4,-d32,-fp64".to_string(),
+            features: "+vfp4,-d32,-fp64".into(),
             max_atomic_width: Some(32),
             ..super::thumb_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs
index ff93934..ab25cde 100644
--- a/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs
@@ -4,13 +4,13 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "thumbv7m-none-eabi".to_string(),
+        llvm_target: "thumbv7m-none-eabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            abi: "eabi".to_string(),
+            abi: "eabi".into(),
             max_atomic_width: Some(32),
             ..super::thumb_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
index fcb7b5d..9a3e8b5 100644
--- a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
@@ -10,15 +10,15 @@
 
 pub fn target() -> Target {
     let mut base = super::android_base::opts();
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".into());
     Target {
-        llvm_target: "armv7-none-linux-android".to_string(),
+        llvm_target: "armv7-none-linux-android".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabi".to_string(),
-            features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(),
+            abi: "eabi".into(),
+            features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(),
             max_atomic_width: Some(64),
             ..base
         },
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs
index 9d34d9a..28c8134 100644
--- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs
@@ -8,14 +8,14 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
+        llvm_target: "armv7-unknown-linux-gnueabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
-            features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(),
+            features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(),
             max_atomic_width: Some(64),
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs
index 4e339cb..2c375ab 100644
--- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs
@@ -11,18 +11,18 @@
         // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
         // uses it to determine the calling convention and float ABI, and LLVM
         // doesn't support the "musleabihf" value.
-        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
+        llvm_target: "armv7-unknown-linux-gnueabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         // Most of these settings are copied from the thumbv7neon_unknown_linux_gnueabihf
         // target.
         options: TargetOptions {
-            abi: "eabihf".to_string(),
-            features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(),
+            abi: "eabihf".into(),
+            features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(),
             max_atomic_width: Some(64),
-            mcount: "\u{1}mcount".to_string(),
+            mcount: "\u{1}mcount".into(),
             ..super::linux_musl_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs
index ef0f52d..756b183 100644
--- a/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs
@@ -4,16 +4,16 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "thumbv8m.base-none-eabi".to_string(),
+        llvm_target: "thumbv8m.base-none-eabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            abi: "eabi".to_string(),
+            abi: "eabi".into(),
             // ARMv8-M baseline doesn't support unaligned loads/stores so we disable them
             // with +strict-align.
-            features: "+strict-align".to_string(),
+            features: "+strict-align".into(),
             max_atomic_width: Some(32),
             ..super::thumb_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs
index dbd184d..4b62685 100644
--- a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs
@@ -5,13 +5,13 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "thumbv8m.main-none-eabi".to_string(),
+        llvm_target: "thumbv8m.main-none-eabi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            abi: "eabi".to_string(),
+            abi: "eabi".into(),
             max_atomic_width: Some(32),
             ..super::thumb_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs
index 3caf705..86c25f9 100644
--- a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs
@@ -5,19 +5,19 @@
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "thumbv8m.main-none-eabihf".to_string(),
+        llvm_target: "thumbv8m.main-none-eabihf".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
-        arch: "arm".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
 
         options: TargetOptions {
-            abi: "eabihf".to_string(),
+            abi: "eabihf".into(),
             // If the Floating Point extension is implemented in the Cortex-M33
             // processor, the Cortex-M33 Technical Reference Manual states that
             // the FPU uses the FPv5 architecture, single-precision instructions
             // and 16 D registers.
             // These parameters map to the following LLVM features.
-            features: "+fp-armv8,-fp64,-d32".to_string(),
+            features: "+fp-armv8,-fp64,-d32".into(),
             max_atomic_width: Some(32),
             ..super::thumb_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/uefi_msvc_base.rs
index 6b6b601..bc7244b 100644
--- a/compiler/rustc_target/src/spec/uefi_msvc_base.rs
+++ b/compiler/rustc_target/src/spec/uefi_msvc_base.rs
@@ -18,7 +18,7 @@
         // Non-standard subsystems have no default entry-point in PE+ files. We have to define
         // one. "efi_main" seems to be a common choice amongst other implementations and the
         // spec.
-        "/entry:efi_main".to_string(),
+        "/entry:efi_main".into(),
         // COFF images have a "Subsystem" field in their header, which defines what kind of
         // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION,
         // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION,
@@ -28,7 +28,7 @@
         // regions the application is loaded into (runtime-drivers need to be put into
         // reserved areas), as well as whether a return from the entry-point is treated as
         // exit (default for applications).
-        "/subsystem:efi_application".to_string(),
+        "/subsystem:efi_application".into(),
     ];
     base.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone());
     base.pre_link_args
@@ -37,17 +37,17 @@
         .extend(pre_link_args_msvc);
 
     TargetOptions {
-        os: "uefi".to_string(),
+        os: "uefi".into(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
         disable_redzone: true,
-        exe_suffix: ".efi".to_string(),
+        exe_suffix: ".efi".into(),
         allows_weak_linkage: false,
         panic_strategy: PanicStrategy::Abort,
         // LLVM does not emit inline assembly because the LLVM target does not get considered as…
         // "Windows".
         stack_probes: StackProbeType::Call,
         singlethread: true,
-        linker: Some("rust-lld".to_string()),
+        linker: Some("rust-lld".into()),
         ..base
     }
 }
diff --git a/compiler/rustc_target/src/spec/vxworks_base.rs b/compiler/rustc_target/src/spec/vxworks_base.rs
index 3f709e7..2beb279 100644
--- a/compiler/rustc_target/src/spec/vxworks_base.rs
+++ b/compiler/rustc_target/src/spec/vxworks_base.rs
@@ -1,22 +1,22 @@
-use crate::spec::TargetOptions;
+use crate::spec::{cvs, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        os: "vxworks".to_string(),
-        env: "gnu".to_string(),
-        vendor: "wrs".to_string(),
-        linker: Some("wr-c++".to_string()),
-        exe_suffix: ".vxe".to_string(),
+        os: "vxworks".into(),
+        env: "gnu".into(),
+        vendor: "wrs".into(),
+        linker: Some("wr-c++".into()),
+        exe_suffix: ".vxe".into(),
         dynamic_linking: true,
         executables: true,
-        families: vec!["unix".to_string()],
+        families: cvs!["unix"],
         has_rpath: true,
         has_thread_local: true,
         crt_static_default: true,
         crt_static_respected: true,
         crt_static_allows_dylibs: true,
         // VxWorks needs to implement this to support profiling
-        mcount: "_mcount".to_string(),
+        mcount: "_mcount".into(),
         ..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 8fcdbc1..b34cac4 100644
--- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
@@ -1,4 +1,4 @@
-use super::wasm_base;
+use super::{cvs, wasm_base};
 use super::{LinkArgs, LinkerFlavor, PanicStrategy, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,41 +11,40 @@
     // however it does have the side effect of automatically exporting a lot
     // of symbols, which approximates what people want when compiling for
     // wasm32-unknown-unknown expect, so use it for now.
-    clang_args.push("--export-dynamic".to_string());
+    clang_args.push("--export-dynamic".into());
 
     let mut post_link_args = LinkArgs::new();
     post_link_args.insert(
         LinkerFlavor::Em,
         vec![
-            "-s".to_string(),
-            "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
-            "-s".to_string(),
-            "ASSERTIONS=1".to_string(),
-            "-s".to_string(),
-            "ABORTING_MALLOC=0".to_string(),
-            "-Wl,--fatal-warnings".to_string(),
+            "-s".into(),
+            "ERROR_ON_UNDEFINED_SYMBOLS=1".into(),
+            "-s".into(),
+            "ASSERTIONS=1".into(),
+            "-s".into(),
+            "ABORTING_MALLOC=0".into(),
+            "-Wl,--fatal-warnings".into(),
         ],
     );
 
     let opts = TargetOptions {
-        os: "emscripten".to_string(),
+        os: "emscripten".into(),
         linker_flavor: LinkerFlavor::Em,
         // emcc emits two files - a .js file to instantiate the wasm and supply platform
         // functionality, and a .wasm file.
-        exe_suffix: ".js".to_string(),
+        exe_suffix: ".js".into(),
         linker: None,
         is_like_emscripten: true,
         panic_strategy: PanicStrategy::Unwind,
         post_link_args,
-        families: vec!["unix".to_string(), "wasm".to_string()],
+        families: cvs!["unix", "wasm"],
         ..options
     };
     Target {
-        llvm_target: "wasm32-unknown-emscripten".to_string(),
+        llvm_target: "wasm32-unknown-emscripten".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20"
-            .to_string(),
-        arch: "wasm32".to_string(),
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20".into(),
+        arch: "wasm32".into(),
         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 e50cf97..214b5fc 100644
--- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
@@ -16,7 +16,7 @@
 
 pub fn target() -> Target {
     let mut options = wasm_base::options();
-    options.os = "unknown".to_string();
+    options.os = "unknown".into();
     options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
 
     // This is a default for backwards-compatibility with the original
@@ -33,29 +33,29 @@
 
     // Make sure clang uses LLD as its linker and is configured appropriately
     // otherwise
-    clang_args.push("--target=wasm32-unknown-unknown".to_string());
+    clang_args.push("--target=wasm32-unknown-unknown".into());
 
     // For now this target just never has an entry symbol no matter the output
     // type, so unconditionally pass this.
-    clang_args.push("-Wl,--no-entry".to_string());
+    clang_args.push("-Wl,--no-entry".into());
 
     // Rust really needs a way for users to specify exports and imports in
     // the source code. --export-dynamic isn't the right tool for this job,
     // however it does have the side effect of automatically exporting a lot
     // of symbols, which approximates what people want when compiling for
     // wasm32-unknown-unknown expect, so use it for now.
-    clang_args.push("-Wl,--export-dynamic".to_string());
+    clang_args.push("-Wl,--export-dynamic".into());
 
     // Add the flags to wasm-ld's args too.
     let lld_args = options.pre_link_args.entry(LinkerFlavor::Lld(LldFlavor::Wasm)).or_default();
-    lld_args.push("--no-entry".to_string());
-    lld_args.push("--export-dynamic".to_string());
+    lld_args.push("--no-entry".into());
+    lld_args.push("--export-dynamic".into());
 
     Target {
-        llvm_target: "wasm32-unknown-unknown".to_string(),
+        llvm_target: "wasm32-unknown-unknown".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".to_string(),
-        arch: "wasm32".to_string(),
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+        arch: "wasm32".into(),
         options,
     }
 }
diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs
index a4b81c9..10eb78e 100644
--- a/compiler/rustc_target/src/spec/wasm32_wasi.rs
+++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs
@@ -78,13 +78,13 @@
 pub fn target() -> Target {
     let mut options = wasm_base::options();
 
-    options.os = "wasi".to_string();
+    options.os = "wasi".into();
     options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
     options
         .pre_link_args
         .entry(LinkerFlavor::Gcc)
         .or_insert(Vec::new())
-        .push("--target=wasm32-wasi".to_string());
+        .push("--target=wasm32-wasi".into());
 
     options.pre_link_objects_fallback = crt_objects::pre_wasi_fallback();
     options.post_link_objects_fallback = crt_objects::post_wasi_fallback();
@@ -107,10 +107,10 @@
     options.main_needs_argc_argv = false;
 
     Target {
-        llvm_target: "wasm32-wasi".to_string(),
+        llvm_target: "wasm32-wasi".into(),
         pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".to_string(),
-        arch: "wasm32".to_string(),
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+        arch: "wasm32".into(),
         options,
     }
 }
diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
index 6b7dfbb..609b7d4 100644
--- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
@@ -12,32 +12,32 @@
 
 pub fn target() -> Target {
     let mut options = wasm_base::options();
-    options.os = "unknown".to_string();
+    options.os = "unknown".into();
     options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
     let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap();
 
     // Make sure clang uses LLD as its linker and is configured appropriately
     // otherwise
-    clang_args.push("--target=wasm64-unknown-unknown".to_string());
+    clang_args.push("--target=wasm64-unknown-unknown".into());
 
     // For now this target just never has an entry symbol no matter the output
     // type, so unconditionally pass this.
-    clang_args.push("-Wl,--no-entry".to_string());
+    clang_args.push("-Wl,--no-entry".into());
 
     let lld_args = options.pre_link_args.get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)).unwrap();
-    lld_args.push("--no-entry".to_string());
-    lld_args.push("-mwasm64".to_string());
+    lld_args.push("--no-entry".into());
+    lld_args.push("-mwasm64".into());
 
     // Any engine that implements wasm64 will surely implement the rest of these
     // features since they were all merged into the official spec by the time
     // wasm64 was designed.
-    options.features = "+bulk-memory,+mutable-globals,+sign-ext,+nontrapping-fptoint".to_string();
+    options.features = "+bulk-memory,+mutable-globals,+sign-ext,+nontrapping-fptoint".into();
 
     Target {
-        llvm_target: "wasm64-unknown-unknown".to_string(),
+        llvm_target: "wasm64-unknown-unknown".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128-ni:1:10:20".to_string(),
-        arch: "wasm64".to_string(),
+        data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128-ni:1:10:20".into(),
+        arch: "wasm64".into(),
         options,
     }
 }
diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs
index 71aa279..de7b737 100644
--- a/compiler/rustc_target/src/spec/wasm_base.rs
+++ b/compiler/rustc_target/src/spec/wasm_base.rs
@@ -1,13 +1,13 @@
 use super::crt_objects::CrtObjectsFallback;
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel};
+use super::{cvs, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel};
 use std::collections::BTreeMap;
 
 pub fn options() -> TargetOptions {
     let mut lld_args = Vec::new();
     let mut clang_args = Vec::new();
-    let mut arg = |arg: &str| {
-        lld_args.push(arg.to_string());
-        clang_args.push(format!("-Wl,{}", arg));
+    let mut arg = |arg: &'static str| {
+        lld_args.push(arg.into());
+        clang_args.push(format!("-Wl,{}", arg).into());
     };
 
     // By default LLD only gives us one page of stack (64k) which is a
@@ -61,7 +61,7 @@
 
     TargetOptions {
         is_like_wasm: true,
-        families: vec!["wasm".to_string()],
+        families: cvs!["wasm"],
 
         // we allow dynamic linking, but only cdylibs. Basically we allow a
         // final library artifact that exports some symbols (a wasm module) but
@@ -73,9 +73,9 @@
         executables: true,
 
         // relatively self-explanatory!
-        exe_suffix: ".wasm".to_string(),
-        dll_prefix: String::new(),
-        dll_suffix: ".wasm".to_string(),
+        exe_suffix: ".wasm".into(),
+        dll_prefix: "".into(),
+        dll_suffix: ".wasm".into(),
         eh_frame_header: false,
 
         max_atomic_width: Some(64),
@@ -100,7 +100,7 @@
         limit_rdylib_exports: false,
 
         // we use the LLD shipped with the Rust toolchain by default
-        linker: Some("rust-lld".to_owned()),
+        linker: Some("rust-lld".into()),
         lld_flavor: LldFlavor::Wasm,
         linker_is_gnu: false,
 
@@ -109,7 +109,7 @@
         crt_objects_fallback: Some(CrtObjectsFallback::Wasm),
 
         // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when
-        // PIC code is implemented this has quite a drastric effect if it stays
+        // PIC code is implemented this has quite a drastic effect if it stays
         // at the default, `pic`. In an effort to keep wasm binaries as minimal
         // as possible we're defaulting to `static` for now, but the hope is
         // that eventually we can ship a `pic`-compatible standard library which
diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs
index 35a5289..d11f1f7 100644
--- a/compiler/rustc_target/src/spec/windows_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs
@@ -1,5 +1,5 @@
 use crate::spec::crt_objects::{self, CrtObjectsFallback};
-use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
+use crate::spec::{cvs, LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let mut pre_link_args = LinkArgs::new();
@@ -8,11 +8,11 @@
         vec![
             // Tell GCC to avoid linker plugins, because we are not bundling
             // them with Windows installer, and Rust does its own LTO anyways.
-            "-fno-use-linker-plugin".to_string(),
+            "-fno-use-linker-plugin".into(),
             // Enable ASLR
-            "-Wl,--dynamicbase".to_string(),
+            "-Wl,--dynamicbase".into(),
             // ASLR will rebase it anyway so leaving that option enabled only leads to confusion
-            "-Wl,--disable-auto-image-base".to_string(),
+            "-Wl,--disable-auto-image-base".into(),
         ],
     );
 
@@ -22,10 +22,10 @@
     // Order of `late_link_args*` was found through trial and error to work with various
     // mingw-w64 versions (not tested on the CI). It's expected to change from time to time.
     let mingw_libs = vec![
-        "-lmsvcrt".to_string(),
-        "-lmingwex".to_string(),
-        "-lmingw32".to_string(),
-        "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
+        "-lmsvcrt".into(),
+        "-lmingwex".into(),
+        "-lmingw32".into(),
+        "-lgcc".into(), // alas, mingw* libraries above depend on libgcc
         // mingw's msvcrt is a weird hybrid import library and static library.
         // And it seems that the linker fails to use import symbols from msvcrt
         // that are required from functions in msvcrt in certain cases. For example
@@ -33,9 +33,9 @@
         // The library is purposely listed twice to fix that.
         //
         // See https://github.com/rust-lang/rust/pull/47483 for some more details.
-        "-lmsvcrt".to_string(),
-        "-luser32".to_string(),
-        "-lkernel32".to_string(),
+        "-lmsvcrt".into(),
+        "-luser32".into(),
+        "-lkernel32".into(),
     ];
     late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone());
     late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs);
@@ -43,7 +43,7 @@
         // If any of our crates are dynamically linked then we need to use
         // the shared libgcc_s-dw2-1.dll. This is required to support
         // unwinding across DLL boundaries.
-        "-lgcc_s".to_string(),
+        "-lgcc_s".into(),
     ];
     late_link_args_dynamic.insert(LinkerFlavor::Gcc, dynamic_unwind_libs.clone());
     late_link_args_dynamic.insert(LinkerFlavor::Lld(LldFlavor::Ld), dynamic_unwind_libs);
@@ -53,25 +53,25 @@
         // binaries to be redistributed without the libgcc_s-dw2-1.dll
         // dependency, but unfortunately break unwinding across DLL
         // boundaries when unwinding across FFI boundaries.
-        "-lgcc_eh".to_string(),
-        "-l:libpthread.a".to_string(),
+        "-lgcc_eh".into(),
+        "-l:libpthread.a".into(),
     ];
     late_link_args_static.insert(LinkerFlavor::Gcc, static_unwind_libs.clone());
     late_link_args_static.insert(LinkerFlavor::Lld(LldFlavor::Ld), static_unwind_libs);
 
     TargetOptions {
-        os: "windows".to_string(),
-        env: "gnu".to_string(),
-        vendor: "pc".to_string(),
+        os: "windows".into(),
+        env: "gnu".into(),
+        vendor: "pc".into(),
         // FIXME(#13846) this should be enabled for windows
         function_sections: false,
-        linker: Some("gcc".to_string()),
+        linker: Some("gcc".into()),
         dynamic_linking: true,
         executables: true,
-        dll_prefix: String::new(),
-        dll_suffix: ".dll".to_string(),
-        exe_suffix: ".exe".to_string(),
-        families: vec!["windows".to_string()],
+        dll_prefix: "".into(),
+        dll_suffix: ".dll".into(),
+        exe_suffix: ".exe".into(),
+        families: cvs!["windows"],
         is_like_windows: true,
         allows_weak_linkage: false,
         pre_link_args,
@@ -87,7 +87,6 @@
         emit_debug_gdb_scripts: false,
         requires_uwtable: true,
         eh_frame_header: false,
-
         ..Default::default()
     }
 }
diff --git a/compiler/rustc_target/src/spec/windows_msvc_base.rs b/compiler/rustc_target/src/spec/windows_msvc_base.rs
index 063b653..21062c3 100644
--- a/compiler/rustc_target/src/spec/windows_msvc_base.rs
+++ b/compiler/rustc_target/src/spec/windows_msvc_base.rs
@@ -1,19 +1,19 @@
-use crate::spec::TargetOptions;
+use crate::spec::{cvs, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let base = super::msvc_base::opts();
 
     TargetOptions {
-        os: "windows".to_string(),
-        env: "msvc".to_string(),
-        vendor: "pc".to_string(),
+        os: "windows".into(),
+        env: "msvc".into(),
+        vendor: "pc".into(),
         dynamic_linking: true,
-        dll_prefix: String::new(),
-        dll_suffix: ".dll".to_string(),
-        exe_suffix: ".exe".to_string(),
-        staticlib_prefix: String::new(),
-        staticlib_suffix: ".lib".to_string(),
-        families: vec!["windows".to_string()],
+        dll_prefix: "".into(),
+        dll_suffix: ".dll".into(),
+        exe_suffix: ".exe".into(),
+        staticlib_prefix: "".into(),
+        staticlib_suffix: ".lib".into(),
+        families: cvs!["windows"],
         crt_static_allows_dylibs: true,
         crt_static_respected: true,
         requires_uwtable: true,
diff --git a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
index 86df816..1196839 100644
--- a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
@@ -9,24 +9,24 @@
     let late_link_args_dynamic = LinkArgs::new();
     let late_link_args_static = LinkArgs::new();
     let mingw_libs = vec![
-        //"-lwinstorecompat".to_string(),
-        //"-lmingwex".to_string(),
-        //"-lwinstorecompat".to_string(),
-        "-lwinstorecompat".to_string(),
-        "-lruntimeobject".to_string(),
-        "-lsynchronization".to_string(),
-        "-lvcruntime140_app".to_string(),
-        "-lucrt".to_string(),
-        "-lwindowsapp".to_string(),
-        "-lmingwex".to_string(),
-        "-lmingw32".to_string(),
+        //"-lwinstorecompat".into(),
+        //"-lmingwex".into(),
+        //"-lwinstorecompat".into(),
+        "-lwinstorecompat".into(),
+        "-lruntimeobject".into(),
+        "-lsynchronization".into(),
+        "-lvcruntime140_app".into(),
+        "-lucrt".into(),
+        "-lwindowsapp".into(),
+        "-lmingwex".into(),
+        "-lmingw32".into(),
     ];
     late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone());
     late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs);
 
     TargetOptions {
-        abi: "uwp".to_string(),
-        vendor: "uwp".to_string(),
+        abi: "uwp".into(),
+        vendor: "uwp".into(),
         executables: false,
         limit_rdylib_exports: false,
         late_link_args,
diff --git a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
index 7b56b46..d6b065b 100644
--- a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
+++ b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
@@ -3,9 +3,9 @@
 pub fn opts() -> TargetOptions {
     let mut opts = super::windows_msvc_base::opts();
 
-    opts.abi = "uwp".to_string();
-    opts.vendor = "uwp".to_string();
-    let pre_link_args_msvc = vec!["/APPCONTAINER".to_string(), "mincore.lib".to_string()];
+    opts.abi = "uwp".into();
+    opts.vendor = "uwp".into();
+    let pre_link_args_msvc = vec!["/APPCONTAINER".into(), "mincore.lib".into()];
     opts.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone());
     opts.pre_link_args
         .entry(LinkerFlavor::Lld(LldFlavor::Link))
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
index 22fdaab..51d14f0 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
@@ -3,14 +3,12 @@
 
 pub fn target() -> Target {
     let mut base = super::apple_base::opts("macos");
-    base.cpu = "core2".to_string();
+    base.cpu = "core2".into();
     base.max_atomic_width = Some(128); // core2 support cmpxchg16b
     base.frame_pointer = FramePointer::Always;
-    base.pre_link_args.insert(
-        LinkerFlavor::Gcc,
-        vec!["-m64".to_string(), "-arch".to_string(), "x86_64".to_string()],
-    );
-    base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
+    base.pre_link_args
+        .insert(LinkerFlavor::Gcc, vec!["-m64".into(), "-arch".into(), "x86_64".into()]);
+    base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.supported_sanitizers =
@@ -23,11 +21,11 @@
     let llvm_target = super::apple_base::macos_llvm_target(&arch);
 
     Target {
-        llvm_target,
+        llvm_target: llvm_target.into(),
         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(),
-        arch: arch.to_string(),
-        options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base },
+            .into(),
+        arch: arch.into(),
+        options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
     }
 }
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 6e20bd2..5e64ed0 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
@@ -3,12 +3,14 @@
 
 pub fn target() -> Target {
     let base = opts("ios", Arch::X86_64);
+    let llvm_target = super::apple_base::ios_sim_llvm_target("x86_64");
+
     Target {
-        llvm_target: super::apple_base::ios_sim_llvm_target("x86_64"),
+        llvm_target: llvm_target.into(),
         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(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: TargetOptions {
             max_atomic_width: Some(64),
             // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
index c228e42..c756325 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
@@ -4,11 +4,11 @@
 pub fn target() -> Target {
     let base = opts("ios", Arch::X86_64_macabi);
     Target {
-        llvm_target: "x86_64-apple-ios13.0-macabi".to_string(),
+        llvm_target: "x86_64-apple-ios13.0-macabi".into(),
         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(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: TargetOptions {
             max_atomic_width: Some(64),
             // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
index e3a5de4..a848c5a 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
@@ -4,10 +4,10 @@
 pub fn target() -> Target {
     let base = opts("tvos", Arch::X86_64);
     Target {
-        llvm_target: "x86_64-apple-tvos".to_string(),
+        llvm_target: "x86_64-apple-tvos".into(),
         pointer_width: 64,
-        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
-        arch: "x86_64".to_string(),
+        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".into(),
+        arch: "x86_64".into(),
         options: TargetOptions {
             max_atomic_width: Some(64),
             // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
index 59cd56e..47c7051 100644
--- a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
@@ -1,4 +1,6 @@
-use std::iter;
+use std::{borrow::Cow, iter};
+
+use crate::spec::cvs;
 
 use super::{LinkerFlavor, LldFlavor, Target, TargetOptions};
 
@@ -58,18 +60,18 @@
         abi: "fortanix".into(),
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
         executables: true,
-        linker: Some("rust-lld".to_owned()),
+        linker: Some("rust-lld".into()),
         max_atomic_width: Some(64),
         cpu: "x86-64".into(),
         features: "+rdrnd,+rdseed,+lvi-cfi,+lvi-load-hardening".into(),
-        llvm_args: vec!["--x86-experimental-lvi-inline-asm-hardening".into()],
+        llvm_args: cvs!["--x86-experimental-lvi-inline-asm-hardening"],
         position_independent_executables: true,
         pre_link_args: iter::once((
             LinkerFlavor::Lld(LldFlavor::Ld),
-            PRE_LINK_ARGS.iter().cloned().map(String::from).collect(),
+            PRE_LINK_ARGS.iter().cloned().map(Cow::from).collect(),
         ))
         .collect(),
-        override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()),
+        override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(Cow::from).collect()),
         relax_elf_relocations: true,
         ..Default::default()
     };
diff --git a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs
index c253c0c..4f88fc3 100644
--- a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs
@@ -2,18 +2,18 @@
 
 pub fn target() -> Target {
     let mut base = super::fuchsia_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     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 | SanitizerSet::CFI;
 
     Target {
-        llvm_target: "x86_64-fuchsia".to_string(),
+        llvm_target: "x86_64-fuchsia".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/x86_64_linux_android.rs
index 9065283..049cab0 100644
--- a/compiler/rustc_target/src/spec/x86_64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/x86_64_linux_android.rs
@@ -1,21 +1,21 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::android_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     // https://developer.android.com/ndk/guides/abis.html#86-64
-    base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".to_string();
+    base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "x86_64-linux-android".to_string(),
+        llvm_target: "x86_64-linux-android".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
-        options: base,
+            .into(),
+        arch: "x86_64".into(),
+        options: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base },
     }
 }
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 6aa0728..2a697da 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
@@ -2,20 +2,20 @@
 
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
-    base.cpu = "x86-64".to_string();
-    base.vendor = "pc".to_string();
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]);
+    base.cpu = "x86-64".into();
+    base.vendor = "pc".into();
     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 | SanitizerSet::CFI;
 
     Target {
-        llvm_target: "x86_64-pc-solaris".to_string(),
+        llvm_target: "x86_64-pc-solaris".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
index 26a81a4..0fa4348 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
@@ -2,22 +2,22 @@
 
 pub fn target() -> Target {
     let mut base = super::windows_gnu_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default();
-    gcc_pre_link_args.push("-m64".to_string());
+    gcc_pre_link_args.push("-m64".into());
     // Use high-entropy 64 bit address space for ASLR
-    gcc_pre_link_args.push("-Wl,--high-entropy-va".to_string());
+    gcc_pre_link_args.push("-Wl,--high-entropy-va".into());
     base.pre_link_args
-        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pep".to_string()]);
+        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pep".into()]);
     base.max_atomic_width = Some(64);
-    base.linker = Some("x86_64-w64-mingw32-gcc".to_string());
+    base.linker = Some("x86_64-w64-mingw32-gcc".into());
 
     Target {
-        llvm_target: "x86_64-pc-windows-gnu".to_string(),
+        llvm_target: "x86_64-pc-windows-gnu".into(),
         pointer_width: 64,
         data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs
index 1c4cceb..081806a 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     let mut base = super::windows_msvc_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "x86_64-pc-windows-msvc".to_string(),
+        llvm_target: "x86_64-pc-windows-msvc".into(),
         pointer_width: 64,
         data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
index 2fa5347..a020182 100644
--- a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
@@ -2,19 +2,19 @@
 
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
-    base.cpu = "x86-64".to_string();
-    base.vendor = "sun".to_string();
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]);
+    base.cpu = "x86-64".into();
+    base.vendor = "sun".into();
     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;
 
     Target {
-        llvm_target: "x86_64-pc-solaris".to_string(),
+        llvm_target: "x86_64-pc-solaris".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
index d69830f..1f2b998 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
@@ -2,18 +2,18 @@
 
 pub fn target() -> Target {
     let mut base = super::dragonfly_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "x86_64-unknown-dragonfly".to_string(),
+        llvm_target: "x86_64-unknown-dragonfly".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
index 24cc7ae..c9aedd6 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
@@ -2,20 +2,20 @@
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     // 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::CFI | SanitizerSet::MEMORY | SanitizerSet::THREAD;
 
     Target {
-        llvm_target: "x86_64-unknown-freebsd".to_string(),
+        llvm_target: "x86_64-unknown-freebsd".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
index fcd96dd..aebbd18 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
@@ -2,20 +2,20 @@
 
 pub fn target() -> Target {
     let mut base = super::haiku_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into()]);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     // This option is required to build executables on Haiku x86_64
     base.position_independent_executables = true;
 
     Target {
-        llvm_target: "x86_64-unknown-haiku".to_string(),
+        llvm_target: "x86_64-unknown-haiku".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
index 1ef24b6..d315301 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
@@ -2,18 +2,18 @@
 
 pub fn target() -> Target {
     let mut base = super::hermit_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.features = "+rdrnd,+rdseed".to_string();
+    base.features = "+rdrnd,+rdseed".into();
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "x86_64-unknown-hermit".to_string(),
+        llvm_target: "x86_64-unknown-hermit".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
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 79ccf63..9529fa9 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
@@ -2,19 +2,19 @@
 
 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.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".into(), "-std=c99".into()]);
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
 
     Target {
         // LLVM does not currently have a separate illumos target,
         // so we still pass Solaris to it
-        llvm_target: "x86_64-pc-solaris".to_string(),
+        llvm_target: "x86_64-pc-solaris".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs
index 64c7c1c..78189a0 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs
@@ -2,18 +2,18 @@
 
 pub fn target() -> Target {
     let mut base = super::l4re_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
     base.crt_static_allows_dylibs = false;
     base.dynamic_linking = false;
     base.panic_strategy = PanicStrategy::Abort;
 
     Target {
-        llvm_target: "x86_64-unknown-l4re-uclibc".to_string(),
+        llvm_target: "x86_64-unknown-l4re-uclibc".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
index aefbb39..e525cfdd 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
@@ -2,9 +2,9 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.static_position_independent_executables = true;
@@ -15,11 +15,11 @@
         | SanitizerSet::THREAD;
 
     Target {
-        llvm_target: "x86_64-unknown-linux-gnu".to_string(),
+        llvm_target: "x86_64-unknown-linux-gnu".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
index 109f86d..863b416 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
@@ -2,10 +2,10 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.cpu = "x86-64".to_string();
-    base.abi = "x32".to_string();
+    base.cpu = "x86-64".into();
+    base.abi = "x32".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mx32".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mx32".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.has_thread_local = false;
@@ -14,12 +14,12 @@
     base.needs_plt = true;
 
     Target {
-        llvm_target: "x86_64-unknown-linux-gnux32".to_string(),
+        llvm_target: "x86_64-unknown-linux-gnux32".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
index a5e7980..8678f06 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
@@ -2,9 +2,9 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.static_position_independent_executables = true;
@@ -15,11 +15,11 @@
         | SanitizerSet::THREAD;
 
     Target {
-        llvm_target: "x86_64-unknown-linux-musl".to_string(),
+        llvm_target: "x86_64-unknown-linux-musl".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
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 bdb2be4..a7115da 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
@@ -2,9 +2,9 @@
 
 pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     // 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
@@ -14,11 +14,11 @@
         | SanitizerSet::THREAD;
 
     Target {
-        llvm_target: "x86_64-unknown-netbsd".to_string(),
+        llvm_target: "x86_64-unknown-netbsd".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
-        options: TargetOptions { mcount: "__mcount".to_string(), ..base },
+            .into(),
+        arch: "x86_64".into(),
+        options: TargetOptions { mcount: "__mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
index 722409d..0c510df 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
@@ -11,7 +11,7 @@
 
 pub fn target() -> Target {
     let opts = TargetOptions {
-        cpu: "x86-64".to_string(),
+        cpu: "x86-64".into(),
         max_atomic_width: Some(64),
         // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
         stack_probes: StackProbeType::Call,
@@ -20,10 +20,10 @@
         relro_level: RelroLevel::Full,
         relocation_model: RelocModel::Pic,
         linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-        linker: Some("rust-lld".to_owned()),
+        linker: Some("rust-lld".into()),
         features:
             "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
-                .to_string(),
+                .into(),
         executables: true,
         disable_redzone: true,
         panic_strategy: PanicStrategy::Abort,
@@ -31,11 +31,11 @@
         ..Default::default()
     };
     Target {
-        llvm_target: "x86_64-unknown-none-elf".to_string(),
+        llvm_target: "x86_64-unknown-none-elf".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: opts,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs
deleted file mode 100644
index 359cb0f..0000000
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-use crate::spec::{StackProbeType, Target};
-
-pub fn target() -> Target {
-    let mut base = super::hermit_kernel_base::opts();
-    base.cpu = "x86-64".to_string();
-    base.max_atomic_width = Some(64);
-    base.features =
-        "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
-            .to_string();
-    // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
-    base.stack_probes = StackProbeType::Call;
-
-    Target {
-        llvm_target: "x86_64-unknown-hermit".to_string(),
-        pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
-        options: base,
-    }
-}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
index fa6f255..0db88d6 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
@@ -5,24 +5,23 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_kernel_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
     base.features =
-        "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
-            .to_string();
+        "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float".into();
     base.code_model = Some(CodeModel::Kernel);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
 
     Target {
         // FIXME: Some dispute, the linux-on-clang folks think this should use
         // "Linux". We disagree because running *on* Linux is nothing like
         // running *as" linux, and historically the "os" component as has always
         // been used to mean the "on" part.
-        llvm_target: "x86_64-unknown-none-elf".to_string(),
+        llvm_target: "x86_64-unknown-none-elf".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
 
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
index 4eb3f34..11e9cc4 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
@@ -2,18 +2,18 @@
 
 pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "x86_64-unknown-openbsd".to_string(),
+        llvm_target: "x86_64-unknown-openbsd".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
index b8269ec..af8b967 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
@@ -2,18 +2,18 @@
 
 pub fn target() -> Target {
     let mut base = super::redox_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "x86_64-unknown-redox".to_string(),
+        llvm_target: "x86_64-unknown-redox".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
index be0e62b..a7ae178 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
@@ -9,7 +9,7 @@
 
 pub fn target() -> Target {
     let mut base = super::uefi_msvc_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
 
     // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
@@ -22,14 +22,14 @@
     //
     // If you initialize FP units yourself, you can override these flags with custom linker
     // arguments, thus giving you access to full MMX/SSE acceleration.
-    base.features = "-mmx,-sse,+soft-float".to_string();
+    base.features = "-mmx,-sse,+soft-float".into();
 
     Target {
-        llvm_target: "x86_64-unknown-windows".to_string(),
+        llvm_target: "x86_64-unknown-windows".into(),
         pointer_width: 64,
         data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
 
         options: base,
     }
diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
index a5425e1..a94bbbf 100644
--- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
@@ -2,21 +2,21 @@
 
 pub fn target() -> Target {
     let mut base = super::windows_uwp_gnu_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     let gcc_pre_link_args = base.pre_link_args.entry(LinkerFlavor::Gcc).or_default();
-    gcc_pre_link_args.push("-m64".to_string());
+    gcc_pre_link_args.push("-m64".into());
     // Use high-entropy 64 bit address space for ASLR
-    gcc_pre_link_args.push("-Wl,--high-entropy-va".to_string());
+    gcc_pre_link_args.push("-Wl,--high-entropy-va".into());
     base.pre_link_args
-        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pep".to_string()]);
+        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".into(), "i386pep".into()]);
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "x86_64-pc-windows-gnu".to_string(),
+        llvm_target: "x86_64-pc-windows-gnu".into(),
         pointer_width: 64,
         data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs
index 06ccc27..b276935 100644
--- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs
@@ -2,15 +2,15 @@
 
 pub fn target() -> Target {
     let mut base = super::windows_uwp_msvc_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
 
     Target {
-        llvm_target: "x86_64-pc-windows-msvc".to_string(),
+        llvm_target: "x86_64-pc-windows-msvc".into(),
         pointer_width: 64,
         data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
index f9f7750..16d2975 100644
--- a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
@@ -2,19 +2,19 @@
 
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
-    base.cpu = "x86-64".to_string();
+    base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
-    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".into());
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
     base.disable_redzone = true;
 
     Target {
-        llvm_target: "x86_64-unknown-linux-gnu".to_string(),
+        llvm_target: "x86_64-unknown-linux-gnu".into(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
+            .into(),
+        arch: "x86_64".into(),
         options: base,
     }
 }