about summary refs log tree commit diff
path: root/compiler/rustc_target
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_target')
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs6
-rw-r--r--compiler/rustc_target/src/abi/call/sparc64.rs6
-rw-r--r--compiler/rustc_target/src/abi/call/xtensa.rs40
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs40
-rw-r--r--compiler/rustc_target/src/spec/mod.rs76
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs5
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs3
8 files changed, 142 insertions, 40 deletions
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 082c169b210..c2826b55dc5 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -188,7 +188,7 @@ impl ArgAttributes {
         if self.arg_ext != other.arg_ext {
             return false;
         }
-        return true;
+        true
     }
 }
 
@@ -632,7 +632,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
             PassMode::Indirect { .. } => {
                 self.mode = PassMode::Direct(ArgAttributes::new());
             }
-            PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) => return, // already direct
+            PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) => {} // already direct
             _ => panic!("Tried to make {:?} direct", self.mode),
         }
     }
@@ -646,7 +646,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
             }
             PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
                 // already indirect
-                return;
             }
             _ => panic!("Tried to make {:?} indirect", self.mode),
         }
@@ -661,7 +660,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
             }
             PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
                 // already indirect
-                return;
             }
             _ => panic!("Tried to make {:?} indirect (expected `PassMode::Ignore`)", self.mode),
         }
diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs
index 2954d9642df..835353f76fc 100644
--- a/compiler/rustc_target/src/abi/call/sparc64.rs
+++ b/compiler/rustc_target/src/abi/call/sparc64.rs
@@ -66,7 +66,7 @@ where
         data.last_offset = offset + Reg::f64().size;
     }
     data.prefix_index += 1;
-    return data;
+    data
 }
 
 fn arg_scalar_pair<C>(
@@ -92,7 +92,7 @@ where
         offset += Size::from_bytes(4 - (offset.bytes() % 4));
     }
     data = arg_scalar(cx, scalar2, offset, data);
-    return data;
+    data
 }
 
 fn parse_structure<'a, Ty, C>(
@@ -128,7 +128,7 @@ where
         }
     }
 
-    return data;
+    data
 }
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size)
diff --git a/compiler/rustc_target/src/abi/call/xtensa.rs b/compiler/rustc_target/src/abi/call/xtensa.rs
index cb61bf2c56b..d7b5fe9d4cc 100644
--- a/compiler/rustc_target/src/abi/call/xtensa.rs
+++ b/compiler/rustc_target/src/abi/call/xtensa.rs
@@ -69,29 +69,27 @@ where
 
     if must_use_stack {
         arg.make_indirect_byval(None);
-    } else {
-        if is_xtensa_aggregate(arg) {
-            // Aggregates which are <= max_size will be passed in
-            // registers if possible, so coerce to integers.
+    } else if is_xtensa_aggregate(arg) {
+        // Aggregates which are <= max_size will be passed in
+        // registers if possible, so coerce to integers.
 
-            // Use a single `xlen` int if possible, 2 * `xlen` if 2 * `xlen` alignment
-            // is required, and a 2-element `xlen` array if only `xlen` alignment is
-            // required.
-            if size <= 32 {
-                arg.cast_to(Reg::i32());
-            } else {
-                let reg = if needed_align == 2 * 32 { Reg::i64() } else { Reg::i32() };
-                let total = Size::from_bits(((size + 32 - 1) / 32) * 32);
-                arg.cast_to(Uniform::new(reg, total));
-            }
+        // Use a single `xlen` int if possible, 2 * `xlen` if 2 * `xlen` alignment
+        // is required, and a 2-element `xlen` array if only `xlen` alignment is
+        // required.
+        if size <= 32 {
+            arg.cast_to(Reg::i32());
         } else {
-            // All integral types are promoted to `xlen`
-            // width.
-            //
-            // We let the LLVM backend handle integral types >= xlen.
-            if size < 32 {
-                arg.extend_integer_width_to(32);
-            }
+            let reg = if needed_align == 2 * 32 { Reg::i64() } else { Reg::i32() };
+            let total = Size::from_bits(((size + 32 - 1) / 32) * 32);
+            arg.cast_to(Uniform::new(reg, total));
+        }
+    } else {
+        // All integral types are promoted to `xlen`
+        // width.
+        //
+        // We let the LLVM backend handle integral types >= xlen.
+        if size < 32 {
+            arg.extend_integer_width_to(32);
         }
     }
 }
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index b1fe49f76ca..e78e3222115 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -168,7 +168,26 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
         ["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(),
     );
 
-    if abi != TargetAbi::MacCatalyst {
+    // We need to communicate four things to the C compiler to be able to link:
+    // - The architecture.
+    // - The operating system (and that it's an Apple platform).
+    // - The deployment target.
+    // - The environment / ABI.
+    //
+    // We'd like to use `-target` everywhere, since that can uniquely
+    // communicate all of these, but that doesn't work on GCC, and since we
+    // don't know whether the `cc` compiler is Clang, GCC, or something else,
+    // we fall back to other options that also work on GCC when compiling for
+    // macOS.
+    //
+    // Targets other than macOS are ill-supported by GCC (it doesn't even
+    // support e.g. `-miphoneos-version-min`), so in those cases we can fairly
+    // safely use `-target`. See also the following, where it is made explicit
+    // that the recommendation by LLVM developers is to use `-target`:
+    // <https://github.com/llvm/llvm-project/issues/88271>
+    if os == "macos" {
+        // `-arch` communicates the architecture.
+        //
         // CC forwards the `-arch` to the linker, so we use the same value
         // here intentionally.
         add_link_args(
@@ -176,6 +195,15 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
             LinkerFlavor::Darwin(Cc::Yes, Lld::No),
             &["-arch", arch.ld_arch()],
         );
+        // The presence of `-mmacosx-version-min` makes CC default to macOS,
+        // and it sets the deployment target.
+        let (major, minor, patch) = deployment_target(os, arch, abi);
+        let opt = format!("-mmacosx-version-min={major}.{minor}.{patch}").into();
+        add_link_args_iter(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), [opt].into_iter());
+        // macOS has no environment, so with these two, we've told CC all the
+        // desired parameters.
+        //
+        // We avoid `-m32`/`-m64`, as this is already encoded by `-arch`.
     } else {
         add_link_args_iter(
             &mut args,
@@ -323,12 +351,18 @@ fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) {
     };
 
     // On certain targets it makes sense to raise the minimum OS version.
+    //
+    // This matches what LLVM does, see:
+    // <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L1900-L1932>
     let min = match (os, arch, abi) {
-        // Use 11.0 on Aarch64 as that's the earliest version with M1 support.
         ("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0),
-        ("ios", Arch::Arm64e, _) => (14, 0, 0),
+        ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::MacCatalyst) => (14, 0, 0),
+        ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0),
+        ("ios", Arch::Arm64e, TargetAbi::Normal) => (14, 0, 0),
         // Mac Catalyst defaults to 13.1 in Clang.
         ("ios", _, TargetAbi::MacCatalyst) => (13, 1, 0),
+        ("tvos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0),
+        ("watchos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (7, 0, 0),
         _ => os_min,
     };
 
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index c3e7f74c564..f12e3e595ad 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -855,6 +855,43 @@ impl ToJson for RelroLevel {
     }
 }
 
+#[derive(Clone, Debug, PartialEq, Hash)]
+pub enum SmallDataThresholdSupport {
+    None,
+    DefaultForArch,
+    LlvmModuleFlag(StaticCow<str>),
+    LlvmArg(StaticCow<str>),
+}
+
+impl FromStr for SmallDataThresholdSupport {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        if s == "none" {
+            Ok(Self::None)
+        } else if s == "default-for-arch" {
+            Ok(Self::DefaultForArch)
+        } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
+            Ok(Self::LlvmModuleFlag(flag.to_string().into()))
+        } else if let Some(arg) = s.strip_prefix("llvm-arg=") {
+            Ok(Self::LlvmArg(arg.to_string().into()))
+        } else {
+            Err(())
+        }
+    }
+}
+
+impl ToJson for SmallDataThresholdSupport {
+    fn to_json(&self) -> Value {
+        match self {
+            Self::None => "none".to_json(),
+            Self::DefaultForArch => "default-for-arch".to_json(),
+            Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(),
+            Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(),
+        }
+    }
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, Hash)]
 pub enum MergeFunctions {
     Disabled,
@@ -2392,6 +2429,9 @@ pub struct TargetOptions {
 
     /// Whether the target supports XRay instrumentation.
     pub supports_xray: bool,
+
+    /// Whether the targets supports -Z small-data-threshold
+    small_data_threshold_support: SmallDataThresholdSupport,
 }
 
 /// Add arguments for the given flavor and also for its "twin" flavors
@@ -2609,6 +2649,7 @@ impl Default for TargetOptions {
             entry_name: "main".into(),
             entry_abi: Conv::C,
             supports_xray: false,
+            small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
         }
     }
 }
@@ -2884,6 +2925,15 @@ impl Target {
                     Some(Ok(()))
                 })).unwrap_or(Ok(()))
             } );
+            ($key_name:ident, SmallDataThresholdSupport) => ( {
+                obj.remove("small-data-threshold-support").and_then(|o| o.as_str().and_then(|s| {
+                    match s.parse::<SmallDataThresholdSupport>() {
+                        Ok(support) => base.small_data_threshold_support = support,
+                        _ => return Some(Err(format!("'{s}' is not a valid value for small-data-threshold-support."))),
+                    }
+                    Some(Ok(()))
+                })).unwrap_or(Ok(()))
+            } );
             ($key_name:ident, PanicStrategy) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
                 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
@@ -3321,6 +3371,7 @@ impl Target {
         key!(supported_sanitizers, SanitizerSet)?;
         key!(generate_arange_section, bool);
         key!(supports_stack_protector, bool);
+        key!(small_data_threshold_support, SmallDataThresholdSupport)?;
         key!(entry_name);
         key!(entry_abi, Conv)?;
         key!(supports_xray, bool);
@@ -3415,6 +3466,30 @@ impl Target {
             }
         }
     }
+
+    /// Return the target's small data threshold support, converting
+    /// `DefaultForArch` into a concrete value.
+    pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport {
+        match &self.options.small_data_threshold_support {
+            // Avoid having to duplicate the small data support in every
+            // target file by supporting a default value for each
+            // architecture.
+            SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() {
+                "mips" | "mips64" | "mips32r6" => {
+                    SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into())
+                }
+                "hexagon" => {
+                    SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into())
+                }
+                "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()),
+                "riscv32" | "riscv64" => {
+                    SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into())
+                }
+                _ => SmallDataThresholdSupport::None,
+            },
+            s => s.clone(),
+        }
+    }
 }
 
 impl ToJson for Target {
@@ -3577,6 +3652,7 @@ impl ToJson for Target {
         target_option_val!(c_enum_min_bits);
         target_option_val!(generate_arange_section);
         target_option_val!(supports_stack_protector);
+        target_option_val!(small_data_threshold_support);
         target_option_val!(entry_name);
         target_option_val!(entry_abi);
         target_option_val!(supports_xray);
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index 67afe35bee4..3e27f1f899b 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -1,10 +1,8 @@
 use crate::spec::base::apple::{base, Arch, TargetAbi};
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
+use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (mut opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
-    opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
-
+    let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index e7f14aa9209..4304dfc3f68 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -1,9 +1,8 @@
 use crate::spec::base::apple::{base, Arch, TargetAbi};
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
-    opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
+    let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index f44bc660a62..9fb5a46187a 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -1,11 +1,10 @@
 use crate::spec::base::apple::{base, Arch, TargetAbi};
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
     opts.max_atomic_width = Some(128);
     opts.frame_pointer = FramePointer::Always;
-    opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
     opts.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;