summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_target/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
commitc23a457e72abe608715ac76f076f47dc42af07a5 (patch)
tree2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /compiler/rustc_target/src
parentReleasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz
rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_target/src')
-rw-r--r--compiler/rustc_target/src/abi/call/loongarch.rs11
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs162
-rw-r--r--compiler/rustc_target/src/abi/call/riscv.rs11
-rw-r--r--compiler/rustc_target/src/abi/call/wasm.rs4
-rw-r--r--compiler/rustc_target/src/abi/call/x86.rs6
-rw-r--r--compiler/rustc_target/src/abi/mod.rs42
-rw-r--r--compiler/rustc_target/src/json.rs4
-rw-r--r--compiler/rustc_target/src/lib.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs3
-rw-r--r--compiler/rustc_target/src/spec/abi.rs46
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs99
-rw-r--r--compiler/rustc_target/src/spec/armv7_apple_ios.rs21
-rw-r--r--compiler/rustc_target/src/spec/armv7s_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/hurd_base.rs15
-rw-r--r--compiler/rustc_target/src/spec/hurd_gnu_base.rs5
-rw-r--r--compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs26
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs19
-rw-r--r--compiler/rustc_target/src/spec/mod.rs15
-rw-r--r--compiler/rustc_target/src/spec/riscv64_linux_android.rs2
-rw-r--r--compiler/rustc_target/src/spec/uefi_msvc_base.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs3
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs3
23 files changed, 391 insertions, 115 deletions
diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/abi/call/loongarch.rs
index 247256f07..e649d58bb 100644
--- a/compiler/rustc_target/src/abi/call/loongarch.rs
+++ b/compiler/rustc_target/src/abi/call/loongarch.rs
@@ -83,6 +83,17 @@ where
}
FieldsShape::Union(_) => {
if !arg_layout.is_zst() {
+ if arg_layout.is_transparent() {
+ let non_1zst_elem = arg_layout.non_1zst_field(cx).expect("not exactly one non-1-ZST field in non-ZST repr(transparent) union").1;
+ return should_use_fp_conv_helper(
+ cx,
+ &non_1zst_elem,
+ xlen,
+ flen,
+ field1_kind,
+ field2_kind,
+ );
+ }
return Err(CannotUseFpConv);
}
}
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 8fab13d5d..5efd171b9 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -2,6 +2,7 @@ use crate::abi::{self, Abi, Align, FieldsShape, Size};
use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout};
use crate::spec::{self, HasTargetSpec};
use rustc_span::Symbol;
+use std::fmt;
use std::str::FromStr;
mod aarch64;
@@ -36,23 +37,52 @@ pub enum PassMode {
Ignore,
/// Pass the argument directly.
///
- /// The argument has a layout abi of `Scalar`, `Vector` or in rare cases `Aggregate`.
+ /// The argument has a layout abi of `Scalar` or `Vector`.
+ /// Unfortunately due to past mistakes, in rare cases on wasm, it can also be `Aggregate`.
+ /// This is bad since it leaks LLVM implementation details into the ABI.
+ /// (Also see <https://github.com/rust-lang/rust/issues/115666>.)
Direct(ArgAttributes),
/// Pass a pair's elements directly in two arguments.
///
/// The argument has a layout abi of `ScalarPair`.
Pair(ArgAttributes, ArgAttributes),
- /// Pass the argument after casting it, to either a single uniform or a
- /// pair of registers. The bool indicates if a `Reg::i32()` dummy argument
- /// is emitted before the real argument.
- Cast(Box<CastTarget>, bool),
+ /// Pass the argument after casting it. See the `CastTarget` docs for details. The bool
+ /// indicates if a `Reg::i32()` dummy argument is emitted before the real argument.
+ Cast { pad_i32: bool, cast: Box<CastTarget> },
/// Pass the argument indirectly via a hidden pointer.
- /// The `extra_attrs` value, if any, is for the extra data (vtable or length)
- /// which indicates that it refers to an unsized rvalue.
- /// `on_stack` defines that the value should be passed at a fixed
- /// stack offset in accordance to the ABI rather than passed using a
- /// pointer. This corresponds to the `byval` LLVM argument attribute.
- Indirect { attrs: ArgAttributes, extra_attrs: Option<ArgAttributes>, on_stack: bool },
+ /// The `meta_attrs` value, if any, is for the metadata (vtable or length) of an unsized
+ /// argument. (This is the only mode that supports unsized arguments.)
+ /// `on_stack` defines that the value should be passed at a fixed stack offset in accordance to
+ /// the ABI rather than passed using a pointer. This corresponds to the `byval` LLVM argument
+ /// attribute (using the Rust type of this argument). `on_stack` cannot be true for unsized
+ /// arguments, i.e., when `meta_attrs` is `Some`.
+ Indirect { attrs: ArgAttributes, meta_attrs: Option<ArgAttributes>, on_stack: bool },
+}
+
+impl PassMode {
+ /// Checks if these two `PassMode` are equal enough to be considered "the same for all
+ /// function call ABIs". However, the `Layout` can also impact ABI decisions,
+ /// so that needs to be compared as well!
+ pub fn eq_abi(&self, other: &Self) -> bool {
+ match (self, other) {
+ (PassMode::Ignore, PassMode::Ignore) => true,
+ (PassMode::Direct(a1), PassMode::Direct(a2)) => a1.eq_abi(a2),
+ (PassMode::Pair(a1, b1), PassMode::Pair(a2, b2)) => a1.eq_abi(a2) && b1.eq_abi(b2),
+ (
+ PassMode::Cast { cast: c1, pad_i32: pad1 },
+ PassMode::Cast { cast: c2, pad_i32: pad2 },
+ ) => c1.eq_abi(c2) && pad1 == pad2,
+ (
+ PassMode::Indirect { attrs: a1, meta_attrs: None, on_stack: s1 },
+ PassMode::Indirect { attrs: a2, meta_attrs: None, on_stack: s2 },
+ ) => a1.eq_abi(a2) && s1 == s2,
+ (
+ PassMode::Indirect { attrs: a1, meta_attrs: Some(e1), on_stack: s1 },
+ PassMode::Indirect { attrs: a2, meta_attrs: Some(e2), on_stack: s2 },
+ ) => a1.eq_abi(a2) && e1.eq_abi(e2) && s1 == s2,
+ _ => false,
+ }
+ }
}
// Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
@@ -127,6 +157,24 @@ impl ArgAttributes {
pub fn contains(&self, attr: ArgAttribute) -> bool {
self.regular.contains(attr)
}
+
+ /// Checks if these two `ArgAttributes` are equal enough to be considered "the same for all
+ /// function call ABIs".
+ pub fn eq_abi(&self, other: &Self) -> bool {
+ // There's only one regular attribute that matters for the call ABI: InReg.
+ // Everything else is things like noalias, dereferenceable, nonnull, ...
+ // (This also applies to pointee_size, pointee_align.)
+ if self.regular.contains(ArgAttribute::InReg) != other.regular.contains(ArgAttribute::InReg)
+ {
+ return false;
+ }
+ // We also compare the sign extension mode -- this could let the callee make assumptions
+ // about bits that conceptually were not even passed.
+ if self.arg_ext != other.arg_ext {
+ return false;
+ }
+ return true;
+ }
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
@@ -211,6 +259,13 @@ impl Uniform {
}
}
+/// Describes the type used for `PassMode::Cast`.
+///
+/// Passing arguments in this mode works as follows: the registers in the `prefix` (the ones that
+/// are `Some`) get laid out one after the other (using `repr(C)` layout rules). Then the
+/// `rest.unit` register type gets repeated often enough to cover `rest.size`. This describes the
+/// actual type used for the call; the Rust type of the argument is then transmuted to this ABI type
+/// (and all data in the padding between the registers is dropped).
#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub struct CastTarget {
pub prefix: [Option<Reg>; 8],
@@ -272,6 +327,14 @@ impl CastTarget {
acc.max(align)
})
}
+
+ /// Checks if these two `CastTarget` are equal enough to be considered "the same for all
+ /// function call ABIs".
+ pub fn eq_abi(&self, other: &Self) -> bool {
+ let CastTarget { prefix: prefix_l, rest: rest_l, attrs: attrs_l } = self;
+ let CastTarget { prefix: prefix_r, rest: rest_r, attrs: attrs_r } = other;
+ prefix_l == prefix_r && rest_l == rest_r && attrs_l.eq_abi(attrs_r)
+ }
}
/// Return value from the `homogeneous_aggregate` test function.
@@ -330,8 +393,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
/// only a single type (e.g., `(u32, u32)`). Such aggregates are often
/// special-cased in ABIs.
///
- /// Note: We generally ignore fields of zero-sized type when computing
- /// this value (see #56877).
+ /// Note: We generally ignore 1-ZST fields when computing this value (see #56877).
///
/// This is public so that it can be used in unit tests, but
/// should generally only be relevant to the ABI details of
@@ -389,12 +451,18 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
let mut total = start;
for i in 0..layout.fields.count() {
+ let field = layout.field(cx, i);
+ if field.is_1zst() {
+ // No data here and no impact on layout, can be ignored.
+ // (We might be able to also ignore all aligned ZST but that's less clear.)
+ continue;
+ }
+
if !is_union && total != layout.fields.offset(i) {
+ // This field isn't just after the previous one we considered, abort.
return Err(Heterogeneous);
}
- let field = layout.field(cx, i);
-
result = result.merge(field.homogeneous_aggregate(cx)?)?;
// Keep track of the offset (without padding).
@@ -458,13 +526,22 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
/// Information about how to pass an argument to,
/// or return a value from, a function, under some ABI.
-#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)]
pub struct ArgAbi<'a, Ty> {
pub layout: TyAndLayout<'a, Ty>,
pub mode: PassMode,
}
+// Needs to be a custom impl because of the bounds on the `TyAndLayout` debug impl.
+impl<'a, Ty: fmt::Display> fmt::Debug for ArgAbi<'a, Ty> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let ArgAbi { layout, mode } = self;
+ f.debug_struct("ArgAbi").field("layout", layout).field("mode", mode).finish()
+ }
+}
+
impl<'a, Ty> ArgAbi<'a, Ty> {
+ /// This defines the "default ABI" for that type, that is then later adjusted in `fn_abi_adjust_for_abi`.
pub fn new(
cx: &impl HasDataLayout,
layout: TyAndLayout<'a, Ty>,
@@ -478,6 +555,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
scalar_attrs(&layout, b, a.size(cx).align_to(b.align(cx).abi)),
),
Abi::Vector { .. } => PassMode::Direct(ArgAttributes::new()),
+ // The `Aggregate` ABI should always be adjusted later.
Abi::Aggregate { .. } => PassMode::Direct(ArgAttributes::new()),
};
ArgAbi { layout, mode }
@@ -497,15 +575,15 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
attrs.pointee_size = layout.size;
attrs.pointee_align = Some(layout.align.abi);
- let extra_attrs = layout.is_unsized().then_some(ArgAttributes::new());
+ let meta_attrs = layout.is_unsized().then_some(ArgAttributes::new());
- PassMode::Indirect { attrs, extra_attrs, on_stack: false }
+ PassMode::Indirect { attrs, meta_attrs, on_stack: false }
}
pub fn make_indirect(&mut self) {
match self.mode {
PassMode::Direct(_) | PassMode::Pair(_, _) => {}
- PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: false } => return,
+ PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: false } => return,
_ => panic!("Tried to make {:?} indirect", self.mode),
}
@@ -515,7 +593,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
pub fn make_indirect_byval(&mut self, byval_align: Option<Align>) {
self.make_indirect();
match self.mode {
- PassMode::Indirect { ref mut attrs, extra_attrs: _, ref mut on_stack } => {
+ PassMode::Indirect { ref mut attrs, meta_attrs: _, ref mut on_stack } => {
*on_stack = true;
// Some platforms, like 32-bit x86, change the alignment of the type when passing
@@ -548,11 +626,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
}
pub fn cast_to<T: Into<CastTarget>>(&mut self, target: T) {
- self.mode = PassMode::Cast(Box::new(target.into()), false);
+ self.mode = PassMode::Cast { cast: Box::new(target.into()), pad_i32: false };
}
pub fn cast_to_and_pad_i32<T: Into<CastTarget>>(&mut self, target: T, pad_i32: bool) {
- self.mode = PassMode::Cast(Box::new(target.into()), pad_i32);
+ self.mode = PassMode::Cast { cast: Box::new(target.into()), pad_i32 };
}
pub fn is_indirect(&self) -> bool {
@@ -560,16 +638,24 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
}
pub fn is_sized_indirect(&self) -> bool {
- matches!(self.mode, PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ })
+ matches!(self.mode, PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ })
}
pub fn is_unsized_indirect(&self) -> bool {
- matches!(self.mode, PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ })
+ matches!(self.mode, PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ })
}
pub fn is_ignore(&self) -> bool {
matches!(self.mode, PassMode::Ignore)
}
+
+ /// Checks if these two `ArgAbi` are equal enough to be considered "the same for all
+ /// function call ABIs".
+ pub fn eq_abi(&self, other: &Self) -> bool {
+ // Ideally we'd just compare the `mode`, but that is not enough -- for some modes LLVM will look
+ // at the type.
+ self.layout.eq_abi(&other.layout) && self.mode.eq_abi(&other.mode)
+ }
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
@@ -579,10 +665,9 @@ pub enum Conv {
C,
Rust,
- /// For things unlikely to be called, where smaller caller codegen is
- /// preferred over raw speed.
- /// Stronger than just `#[cold]` because `fn` pointers might be incompatible.
- RustCold,
+ Cold,
+ PreserveMost,
+ PreserveAll,
// Target-specific calling conventions.
ArmAapcs,
@@ -605,9 +690,7 @@ pub enum Conv {
AvrInterrupt,
AvrNonBlockingInterrupt,
- RiscvInterrupt {
- kind: RiscvInterruptKind,
- },
+ RiscvInterrupt { kind: RiscvInterruptKind },
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
@@ -630,7 +713,7 @@ impl RiscvInterruptKind {
///
/// I will do my best to describe this structure, but these
/// comments are reverse-engineered and may be inaccurate. -NDM
-#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)]
pub struct FnAbi<'a, Ty> {
/// The LLVM types of each argument.
pub args: Box<[ArgAbi<'a, Ty>]>,
@@ -651,6 +734,21 @@ pub struct FnAbi<'a, Ty> {
pub can_unwind: bool,
}
+// Needs to be a custom impl because of the bounds on the `TyAndLayout` debug impl.
+impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let FnAbi { args, ret, c_variadic, fixed_count, conv, can_unwind } = self;
+ f.debug_struct("FnAbi")
+ .field("args", args)
+ .field("ret", ret)
+ .field("c_variadic", c_variadic)
+ .field("fixed_count", fixed_count)
+ .field("conv", conv)
+ .field("can_unwind", can_unwind)
+ .finish()
+ }
+}
+
/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum AdjustForForeignAbiError {
diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs
index d90dce2a0..93a204563 100644
--- a/compiler/rustc_target/src/abi/call/riscv.rs
+++ b/compiler/rustc_target/src/abi/call/riscv.rs
@@ -89,6 +89,17 @@ where
}
FieldsShape::Union(_) => {
if !arg_layout.is_zst() {
+ if arg_layout.is_transparent() {
+ let non_1zst_elem = arg_layout.non_1zst_field(cx).expect("not exactly one non-1-ZST field in non-ZST repr(transparent) union").1;
+ return should_use_fp_conv_helper(
+ cx,
+ &non_1zst_elem,
+ xlen,
+ flen,
+ field1_kind,
+ field2_kind,
+ );
+ }
return Err(CannotUseFpConv);
}
}
diff --git a/compiler/rustc_target/src/abi/call/wasm.rs b/compiler/rustc_target/src/abi/call/wasm.rs
index 0eb2309ec..796b752ff 100644
--- a/compiler/rustc_target/src/abi/call/wasm.rs
+++ b/compiler/rustc_target/src/abi/call/wasm.rs
@@ -61,6 +61,10 @@ where
/// The purpose of this ABI is for matching the WebAssembly standard. This
/// intentionally diverges from the C ABI and is specifically crafted to take
/// advantage of LLVM's support of multiple returns in WebAssembly.
+///
+/// This ABI is *bad*! It uses `PassMode::Direct` for `abi::Aggregate` types, which leaks LLVM
+/// implementation details into the ABI. It's just hard to fix because ABIs are hard to change.
+/// Also see <https://github.com/rust-lang/rust/issues/115666>.
pub fn compute_wasm_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
if !fn_abi.ret.is_ignore() {
classify_ret(&mut fn_abi.ret);
diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs
index b738c3133..afa1b70ef 100644
--- a/compiler/rustc_target/src/abi/call/x86.rs
+++ b/compiler/rustc_target/src/abi/call/x86.rs
@@ -142,13 +142,13 @@ where
for arg in fn_abi.args.iter_mut() {
let attrs = match arg.mode {
PassMode::Ignore
- | PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
+ | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
continue;
}
PassMode::Direct(ref mut attrs) => attrs,
PassMode::Pair(..)
- | PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ }
- | PassMode::Cast(..) => {
+ | PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ }
+ | PassMode::Cast { .. } => {
unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode)
}
};
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index dd435dbb0..74fe98920 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -3,6 +3,7 @@ pub use Primitive::*;
use crate::json::{Json, ToJson};
+use std::fmt;
use std::ops::Deref;
use rustc_macros::HashStable_Generic;
@@ -24,12 +25,22 @@ impl ToJson for Endian {
/// to that obtained from `layout_of(ty)`, as we need to produce
/// layouts for which Rust types do not exist, such as enum variants
/// or synthetic fields of enums (i.e., discriminants) and fat pointers.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
pub struct TyAndLayout<'a, Ty> {
pub ty: Ty,
pub layout: Layout<'a>,
}
+impl<'a, Ty: fmt::Display> fmt::Debug for TyAndLayout<'a, Ty> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Print the type in a readable way, not its debug representation.
+ f.debug_struct("TyAndLayout")
+ .field("ty", &format_args!("{}", self.ty))
+ .field("layout", &self.layout)
+ .finish()
+ }
+}
+
impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
type Target = &'a LayoutS;
fn deref(&self) -> &&'a LayoutS {
@@ -55,6 +66,7 @@ pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug {
fn is_never(this: TyAndLayout<'a, Self>) -> bool;
fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
+ fn is_transparent(this: TyAndLayout<'a, Self>) -> bool;
}
impl<'a, Ty> TyAndLayout<'a, Ty> {
@@ -125,6 +137,13 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
Ty::is_unit(self)
}
+ pub fn is_transparent<C>(self) -> bool
+ where
+ Ty: TyAbiInterface<'a, C>,
+ {
+ Ty::is_transparent(self)
+ }
+
pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
where
Ty: TyAbiInterface<'a, C>,
@@ -144,4 +163,25 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
offset
}
+
+ /// Finds the one field that is not a 1-ZST.
+ /// Returns `None` if there are multiple non-1-ZST fields or only 1-ZST-fields.
+ pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(usize, Self)>
+ where
+ Ty: TyAbiInterface<'a, C> + Copy,
+ {
+ let mut found = None;
+ for field_idx in 0..self.fields.count() {
+ let field = self.field(cx, field_idx);
+ if field.is_1zst() {
+ continue;
+ }
+ if found.is_some() {
+ // More than one non-1-ZST field.
+ return None;
+ }
+ found = Some((field_idx, field));
+ }
+ found
+ }
}
diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs
index af455b643..c61351490 100644
--- a/compiler/rustc_target/src/json.rs
+++ b/compiler/rustc_target/src/json.rs
@@ -96,7 +96,9 @@ impl ToJson for crate::abi::call::Conv {
let s = match self {
Self::C => "C",
Self::Rust => "Rust",
- Self::RustCold => "RustCold",
+ Self::Cold => "Cold",
+ Self::PreserveMost => "PreserveMost",
+ Self::PreserveAll => "PreserveAll",
Self::ArmAapcs => "ArmAapcs",
Self::CCmseNonSecureCall => "CCmseNonSecureCall",
Self::Msp430Intr => "Msp430Intr",
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index b52002b12..e838e1113 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -19,7 +19,7 @@
#![feature(step_trait)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
-#![cfg_attr(not(bootstrap), allow(internal_features))]
+#![allow(internal_features)]
use std::path::{Path, PathBuf};
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 e2df7e0bd..b29ab14e7 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -1,5 +1,5 @@
use super::apple_base::{opts, Arch};
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let llvm_target = "arm64-apple-ios14.0-macabi";
@@ -7,6 +7,7 @@ pub fn target() -> Target {
let arch = Arch::Arm64_macabi;
let mut base = opts("ios", arch);
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]);
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
Target {
llvm_target: llvm_target.into(),
diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs
index 550cdf6bd..a99cccd42 100644
--- a/compiler/rustc_target/src/spec/abi.rs
+++ b/compiler/rustc_target/src/spec/abi.rs
@@ -14,15 +14,33 @@ pub enum Abi {
// hashing tests. These are used in many places, so giving them stable values reduces test
// churn. The specific values are meaningless.
Rust,
- C { unwind: bool },
- Cdecl { unwind: bool },
- Stdcall { unwind: bool },
- Fastcall { unwind: bool },
- Vectorcall { unwind: bool },
- Thiscall { unwind: bool },
- Aapcs { unwind: bool },
- Win64 { unwind: bool },
- SysV64 { unwind: bool },
+ C {
+ unwind: bool,
+ },
+ Cdecl {
+ unwind: bool,
+ },
+ Stdcall {
+ unwind: bool,
+ },
+ Fastcall {
+ unwind: bool,
+ },
+ Vectorcall {
+ unwind: bool,
+ },
+ Thiscall {
+ unwind: bool,
+ },
+ Aapcs {
+ unwind: bool,
+ },
+ Win64 {
+ unwind: bool,
+ },
+ SysV64 {
+ unwind: bool,
+ },
PtxKernel,
Msp430Interrupt,
X86Interrupt,
@@ -32,11 +50,16 @@ pub enum Abi {
AvrNonBlockingInterrupt,
CCmseNonSecureCall,
Wasm,
- System { unwind: bool },
+ System {
+ unwind: bool,
+ },
RustIntrinsic,
RustCall,
PlatformIntrinsic,
Unadjusted,
+ /// For things unlikely to be called, where reducing register pressure in
+ /// `extern "Rust"` callers is worth paying extra cost in the callee.
+ /// Stronger than just `#[cold]` because `fn` pointers might be incompatible.
RustCold,
RiscvInterruptM,
RiscvInterruptS,
@@ -45,7 +68,7 @@ pub enum Abi {
impl Abi {
pub fn supports_varargs(self) -> bool {
// * C and Cdecl obviously support varargs.
- // * C can be based on SysV64 or Win64, so they must support varargs.
+ // * C can be based on Aapcs, SysV64 or Win64, so they must support varargs.
// * EfiApi is based on Win64 or C, so it also supports it.
//
// * Stdcall does not, because it would be impossible for the callee to clean
@@ -56,6 +79,7 @@ impl Abi {
match self {
Self::C { .. }
| Self::Cdecl { .. }
+ | Self::Aapcs { .. }
| Self::Win64 { .. }
| Self::SysV64 { .. }
| Self::EfiApi => true,
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index 8a8d1ab95..7a666eea4 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -11,7 +11,6 @@ use Arch::*;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Arch {
- Armv7,
Armv7k,
Armv7s,
Arm64,
@@ -29,7 +28,6 @@ pub enum Arch {
impl Arch {
pub fn target_name(self) -> &'static str {
match self {
- Armv7 => "armv7",
Armv7k => "armv7k",
Armv7s => "armv7s",
Arm64 | Arm64_macabi | Arm64_sim => "arm64",
@@ -43,7 +41,7 @@ impl Arch {
pub fn target_arch(self) -> Cow<'static, str> {
Cow::Borrowed(match self {
- Armv7 | Armv7k | Armv7s => "arm",
+ Armv7k | Armv7s => "arm",
Arm64 | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64",
I386 | I686 => "x86",
X86_64 | X86_64_sim | X86_64_macabi | X86_64h => "x86_64",
@@ -52,7 +50,7 @@ impl Arch {
fn target_abi(self) -> &'static str {
match self {
- Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "",
+ Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "",
X86_64_macabi | Arm64_macabi => "macabi",
// x86_64-apple-ios is a simulator target, even though it isn't
// declared that way in the target like the other ones...
@@ -62,18 +60,20 @@ impl Arch {
fn target_cpu(self) -> &'static str {
match self {
- Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
Armv7k => "cortex-a8",
- Armv7s => "cortex-a9",
+ Armv7s => "swift", // iOS 10 is only supported on iPhone 5 or higher.
Arm64 => "apple-a7",
Arm64_32 => "apple-s4",
- I386 | I686 => "yonah",
- X86_64 | X86_64_sim => "core2",
+ // Only macOS 10.12+ is supported, which means
+ // all x86_64/x86 CPUs must be running at least penryn
+ // https://github.com/llvm/llvm-project/blob/01f924d0e37a5deae51df0d77e10a15b63aa0c0f/clang/lib/Driver/ToolChains/Arch/X86.cpp#L79-L82
+ I386 | I686 => "penryn",
+ X86_64 | X86_64_sim => "penryn",
+ X86_64_macabi => "penryn",
// Note: `core-avx2` is slightly more advanced than `x86_64h`, see
// comments (and disabled features) in `x86_64h_apple_darwin` for
- // details.
+ // details. It is a higher baseline then `penryn` however.
X86_64h => "core-avx2",
- X86_64_macabi => "core2",
Arm64_macabi => "apple-a12",
Arm64_sim => "apple-a12",
}
@@ -115,21 +115,6 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
}
pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
- // Static 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
- // 10.7+, but there is a standard environment variable,
- // MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older
- // versions of macOS. For example compiling on 10.10 with
- // MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate
- // warnings about the usage of static TLS.
- //
- // Here we detect what version is being requested, defaulting to 10.7. Static
- // TLS is flagged as enabled if it looks to be supported. The architecture
- // only matters for default deployment target which is 11.0 for ARM64 and
- // 10.7 for everything else.
- let has_thread_local = os == "macos" && macos_deployment_target(Arch::X86_64) >= (10, 7);
-
let abi = arch.target_abi();
TargetOptions {
@@ -145,12 +130,17 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
pre_link_args: pre_link_args(os, arch, abi),
families: cvs!["unix"],
is_like_osx: true,
- default_dwarf_version: 2,
+ // LLVM notes that macOS 10.11+ and iOS 9+ default
+ // to v4, so we do the same.
+ // https://github.com/llvm/llvm-project/blob/378778a0d10c2f8d5df8ceff81f95b6002984a4b/clang/lib/Driver/ToolChains/Darwin.cpp#L1203
+ default_dwarf_version: 4,
frame_pointer: FramePointer::Always,
has_rpath: true,
dll_suffix: ".dylib".into(),
archive_format: "darwin".into(),
- has_thread_local,
+ // Thread locals became available with iOS 8 and macOS 10.7,
+ // and both are far below our minimum.
+ has_thread_local: true,
abi_return_struct_as_int: true,
emit_debug_gdb_scripts: false,
eh_frame_header: false,
@@ -179,20 +169,52 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
}
}
-pub fn deployment_target(target: &Target) -> Option<String> {
+pub fn sdk_version(platform: u32) -> Option<(u32, u32)> {
+ // NOTE: These values are from an arbitrary point in time but shouldn't make it into the final
+ // binary since the final link command will have the current SDK version passed to it.
+ match platform {
+ object::macho::PLATFORM_MACOS => Some((13, 1)),
+ object::macho::PLATFORM_IOS
+ | object::macho::PLATFORM_IOSSIMULATOR
+ | object::macho::PLATFORM_TVOS
+ | object::macho::PLATFORM_TVOSSIMULATOR
+ | object::macho::PLATFORM_MACCATALYST => Some((16, 2)),
+ object::macho::PLATFORM_WATCHOS | object::macho::PLATFORM_WATCHOSSIMULATOR => Some((9, 1)),
+ _ => None,
+ }
+}
+
+pub fn platform(target: &Target) -> Option<u32> {
+ Some(match (&*target.os, &*target.abi) {
+ ("macos", _) => object::macho::PLATFORM_MACOS,
+ ("ios", "macabi") => object::macho::PLATFORM_MACCATALYST,
+ ("ios", "sim") => object::macho::PLATFORM_IOSSIMULATOR,
+ ("ios", _) => object::macho::PLATFORM_IOS,
+ ("watchos", "sim") => object::macho::PLATFORM_WATCHOSSIMULATOR,
+ ("watchos", _) => object::macho::PLATFORM_WATCHOS,
+ ("tvos", "sim") => object::macho::PLATFORM_TVOSSIMULATOR,
+ ("tvos", _) => object::macho::PLATFORM_TVOS,
+ _ => return None,
+ })
+}
+
+pub fn deployment_target(target: &Target) -> Option<(u32, u32)> {
let (major, minor) = match &*target.os {
"macos" => {
// This does not need to be specific. It just needs to handle x86 vs M1.
let arch = if target.arch == "x86" || target.arch == "x86_64" { X86_64 } else { Arm64 };
macos_deployment_target(arch)
}
- "ios" => ios_deployment_target(),
+ "ios" => match &*target.abi {
+ "macabi" => mac_catalyst_deployment_target(),
+ _ => ios_deployment_target(),
+ },
"watchos" => watchos_deployment_target(),
"tvos" => tvos_deployment_target(),
_ => return None,
};
- Some(format!("{major}.{minor}"))
+ Some((major, minor))
}
fn from_set_deployment_target(var_name: &str) -> Option<(u32, u32)> {
@@ -207,9 +229,7 @@ fn macos_default_deployment_target(arch: Arch) -> (u32, u32) {
match arch {
// Note: Arm64_sim is not included since macOS has no simulator.
Arm64 | Arm64_macabi => (11, 0),
- // x86_64h-apple-darwin only supports macOS 10.8 and later
- X86_64h => (10, 8),
- _ => (10, 7),
+ _ => (10, 12),
}
}
@@ -260,8 +280,8 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]>
// Otherwise if cross-compiling for a different OS/SDK, remove any part
// of the linking environment that's wrong and reversed.
match arch {
- Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim
- | X86_64h | Arm64_sim => {
+ Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim | X86_64h
+ | Arm64_sim => {
cvs!["MACOSX_DEPLOYMENT_TARGET"]
}
X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
@@ -271,7 +291,12 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]>
fn ios_deployment_target() -> (u32, u32) {
// If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
- from_set_deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0))
+ from_set_deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((10, 0))
+}
+
+fn mac_catalyst_deployment_target() -> (u32, u32) {
+ // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
+ from_set_deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((14, 0))
}
pub fn ios_llvm_target(arch: Arch) -> String {
@@ -297,7 +322,7 @@ pub fn ios_sim_llvm_target(arch: Arch) -> String {
fn tvos_deployment_target() -> (u32, u32) {
// If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
- from_set_deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((7, 0))
+ from_set_deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((10, 0))
}
fn tvos_lld_platform_version() -> String {
diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs
deleted file mode 100644
index 3259c8547..000000000
--- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-use super::apple_base::{ios_llvm_target, opts, Arch};
-use crate::spec::{Target, TargetOptions};
-
-pub fn target() -> Target {
- let arch = Arch::Armv7;
- Target {
- // Clang automatically chooses a more specific target based on
- // IPHONEOS_DEPLOYMENT_TARGET.
- // This is required for the target to pick the right
- // MACH-O commands, so we do too.
- llvm_target: ios_llvm_target(arch).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".into(),
- arch: arch.target_arch(),
- options: TargetOptions {
- features: "+v7,+vfp3,+neon".into(),
- max_atomic_width: Some(64),
- ..opts("ios", arch)
- },
- }
-}
diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
index be4bc6758..be7f8542c 100644
--- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
@@ -1,10 +1,10 @@
-use super::apple_base::{opts, Arch};
+use super::apple_base::{ios_llvm_target, opts, Arch};
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::Armv7s;
Target {
- llvm_target: "armv7s-apple-ios".into(),
+ llvm_target: ios_llvm_target(arch).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".into(),
arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/hurd_base.rs b/compiler/rustc_target/src/spec/hurd_base.rs
new file mode 100644
index 000000000..76f8223c0
--- /dev/null
+++ b/compiler/rustc_target/src/spec/hurd_base.rs
@@ -0,0 +1,15 @@
+use crate::spec::{cvs, RelroLevel, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "hurd".into(),
+ dynamic_linking: true,
+ families: cvs!["unix"],
+ has_rpath: true,
+ position_independent_executables: true,
+ relro_level: RelroLevel::Full,
+ has_thread_local: true,
+ crt_static_respected: true,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/hurd_gnu_base.rs b/compiler/rustc_target/src/spec/hurd_gnu_base.rs
new file mode 100644
index 000000000..b9cf26d93
--- /dev/null
+++ b/compiler/rustc_target/src/spec/hurd_gnu_base.rs
@@ -0,0 +1,5 @@
+use crate::spec::TargetOptions;
+
+pub fn opts() -> TargetOptions {
+ TargetOptions { env: "gnu".into(), ..super::hurd_base::opts() }
+}
diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs
new file mode 100644
index 000000000..3154b512a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs
@@ -0,0 +1,26 @@
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target};
+
+pub fn target() -> Target {
+ let mut base = super::windows_gnullvm_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+ base.frame_pointer = FramePointer::Always; // Required for backtraces
+ base.linker = Some("i686-w64-mingw32-clang".into());
+
+ // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
+ // space available to x86 Windows binaries on x86_64.
+ base.add_pre_link_args(
+ LinkerFlavor::Gnu(Cc::No, Lld::No),
+ &["-m", "i386pe", "--large-address-aware"],
+ );
+
+ Target {
+ 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"
+ .into(),
+ arch: "x86".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs
new file mode 100644
index 000000000..29f803601
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::hurd_gnu_base::opts();
+ base.cpu = "pentiumpro".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
+ base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
+
+ Target {
+ llvm_target: "i686-unknown-hurd-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"
+ .into(),
+ arch: "x86".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 31b6961bb..1bcb1f353 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -61,6 +61,8 @@ mod aix_base;
mod android_base;
mod apple_base;
pub use apple_base::deployment_target as current_apple_deployment_target;
+pub use apple_base::platform as current_apple_platform;
+pub use apple_base::sdk_version as current_apple_sdk_version;
mod avr_gnu_base;
pub use avr_gnu_base::ef_avr_arch;
mod bpf_base;
@@ -69,6 +71,8 @@ mod freebsd_base;
mod fuchsia_base;
mod haiku_base;
mod hermit_base;
+mod hurd_base;
+mod hurd_gnu_base;
mod illumos_base;
mod l4re_base;
mod linux_base;
@@ -1365,6 +1369,8 @@ supported_targets! {
("i686-unknown-haiku", i686_unknown_haiku),
("x86_64-unknown-haiku", x86_64_unknown_haiku),
+ ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
+
("aarch64-apple-darwin", aarch64_apple_darwin),
("x86_64-apple-darwin", x86_64_apple_darwin),
("x86_64h-apple-darwin", x86_64h_apple_darwin),
@@ -1388,7 +1394,6 @@ supported_targets! {
("i386-apple-ios", i386_apple_ios),
("x86_64-apple-ios", x86_64_apple_ios),
("aarch64-apple-ios", aarch64_apple_ios),
- ("armv7-apple-ios", armv7_apple_ios),
("armv7s-apple-ios", armv7s_apple_ios),
("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
@@ -1418,6 +1423,7 @@ supported_targets! {
("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
+ ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
@@ -2276,6 +2282,13 @@ impl Target {
Abi::Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
Abi::Fastcall { unwind } | Abi::Vectorcall { unwind } => Abi::C { unwind },
+ // The Windows x64 calling convention we use for `extern "Rust"`
+ // <https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions#register-volatility-and-preservation>
+ // expects the callee to save `xmm6` through `xmm15`, but `PreserveMost`
+ // (that we use by default for `extern "rust-cold"`) doesn't save any of those.
+ // So to avoid bloating callers, just use the Rust convention here.
+ Abi::RustCold if self.is_like_windows && self.arch == "x86_64" => Abi::Rust,
+
abi => abi,
}
}
diff --git a/compiler/rustc_target/src/spec/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/riscv64_linux_android.rs
index af0d68554..91f5e562d 100644
--- a/compiler/rustc_target/src/spec/riscv64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/riscv64_linux_android.rs
@@ -9,7 +9,7 @@ pub fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+Zba,+Zbb,+Zbs".into(),
llvm_abiname: "lp64d".into(),
supported_sanitizers: SanitizerSet::ADDRESS,
max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/uefi_msvc_base.rs
index 8968d3c8f..a50a55ad7 100644
--- a/compiler/rustc_target/src/spec/uefi_msvc_base.rs
+++ b/compiler/rustc_target/src/spec/uefi_msvc_base.rs
@@ -46,6 +46,7 @@ pub fn opts() -> TargetOptions {
stack_probes: StackProbeType::Call,
singlethread: true,
linker: Some("rust-lld".into()),
+ entry_name: "efi_main".into(),
..base
}
}
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 e90bda9c9..e3f5d7321 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
@@ -5,7 +5,7 @@ use crate::spec::{StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::X86_64;
let mut base = opts("macos", arch);
- base.max_atomic_width = Some(128); // core2 supports cmpxchg16b
+ base.max_atomic_width = Some(128); // penryn+ supports cmpxchg16b
base.frame_pointer = FramePointer::Always;
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
base.stack_probes = StackProbeType::X86;
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 50f359c35..fd1926f29 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
@@ -1,5 +1,5 @@
use super::apple_base::{opts, Arch};
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let llvm_target = "x86_64-apple-ios14.0-macabi";
@@ -7,6 +7,7 @@ pub fn target() -> Target {
let arch = Arch::X86_64_macabi;
let mut base = opts("ios", arch);
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]);
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
Target {
llvm_target: llvm_target.into(),
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 67664a747..41ba76806 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
@@ -5,13 +5,14 @@
// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.
-use crate::spec::Target;
+use crate::{abi::call::Conv, spec::Target};
pub fn target() -> Target {
let mut base = super::uefi_msvc_base::opts();
base.cpu = "x86-64".into();
base.plt_by_default = false;
base.max_atomic_width = Some(64);
+ base.entry_abi = Conv::X86_64Win64;
// We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
// enable these CPU features explicitly before their first use, otherwise their instructions