From a725250806b90db15bc4f6bb239ceae989eeb302 Mon Sep 17 00:00:00 2001 From: Mary Date: Tue, 9 Aug 2022 11:04:48 +0200 Subject: [PATCH] Add support for link-flavor rust-lld for macOS Also refactor iOS, watchOS and tvOS common code. --- compiler/rustc_codegen_ssa/src/back/link.rs | 8 ++- .../src/spec/aarch64_apple_darwin.rs | 8 +-- compiler/rustc_target/src/spec/apple_base.rs | 53 +++++++++++++++++-- .../rustc_target/src/spec/apple_sdk_base.rs | 44 +-------------- .../src/spec/i686_apple_darwin.rs | 3 +- .../src/spec/x86_64_apple_darwin.rs | 6 +-- 6 files changed, 66 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 63207803e327f..468d034e635ff 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2674,11 +2674,16 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { let os = &sess.target.os; let llvm_target = &sess.target.llvm_target; if sess.target.vendor != "apple" - || !matches!(os.as_ref(), "ios" | "tvos" | "watchos") + || !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "macos") || (flavor != LinkerFlavor::Gcc && flavor != LinkerFlavor::Lld(LldFlavor::Ld64)) { return; } + + if os == "macos" && flavor != LinkerFlavor::Lld(LldFlavor::Ld64) { + return; + } + let sdk_name = match (arch.as_ref(), os.as_ref()) { ("aarch64", "tvos") => "appletvos", ("x86_64", "tvos") => "appletvsimulator", @@ -2694,6 +2699,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { ("aarch64", "watchos") if llvm_target.ends_with("-simulator") => "watchsimulator", ("aarch64", "watchos") => "watchos", ("arm", "watchos") => "watchos", + (_, "macos") => "macosx", _ => { sess.err(&format!("unsupported arch `{}` for os `{}`", arch, os)); return; diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 9d36e37d7b82e..6d919a4c2ad2e 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -1,20 +1,20 @@ -use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::apple_base::opts("macos"); + let arch = "arm64"; + let mut base = super::apple_base::opts("macos", arch, ""); 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.add_pre_link_args(LinkerFlavor::Gcc, &["-arch", "arm64"]); 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 // correctly, we do too. - let llvm_target = super::apple_base::macos_llvm_target("arm64"); + let llvm_target = super::apple_base::macos_llvm_target(arch); Target { llvm_target: llvm_target.into(), diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 15e4fb9be6303..db38ff50c7878 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -1,8 +1,45 @@ use std::{borrow::Cow, env}; -use crate::spec::{cvs, FramePointer, LldFlavor, SplitDebuginfo, TargetOptions}; +use crate::spec::{cvs, FramePointer, SplitDebuginfo, TargetOptions}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor}; + +fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs { + let mut args = LinkArgs::new(); + + let platform_name = match abi { + "sim" => format!("{}-simulator", os), + "macabi" => "mac-catalyst".to_string(), + _ => os.to_string(), + }; + + let platform_version = match os.as_ref() { + "ios" => ios_lld_platform_version(), + "tvos" => tvos_lld_platform_version(), + "watchos" => watchos_lld_platform_version(), + "macos" => macos_lld_platform_version(arch), + _ => unreachable!(), + }; + + if abi != "macabi" { + args.insert(LinkerFlavor::Gcc, vec!["-arch".into(), arch.into()]); + } + + args.insert( + LinkerFlavor::Lld(LldFlavor::Ld64), + vec![ + "-arch".into(), + arch.into(), + "-platform_version".into(), + platform_name.into(), + platform_version.clone().into(), + platform_version.into(), + ], + ); + + args +} -pub fn opts(os: &'static str) -> TargetOptions { +pub fn opts(os: &'static str, arch: &'static str, abi: &'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 @@ -24,6 +61,7 @@ pub fn opts(os: &'static str) -> TargetOptions { // macOS has -dead_strip, which doesn't rely on function_sections function_sections: false, dynamic_linking: true, + pre_link_args: pre_link_args(os, arch, abi), linker_is_gnu: false, families: cvs!["unix"], is_like_osx: true, @@ -73,6 +111,11 @@ fn macos_deployment_target(arch: &str) -> (u32, u32) { .unwrap_or_else(|| macos_default_deployment_target(arch)) } +fn macos_lld_platform_version(arch: &str) -> String { + let (major, minor) = macos_deployment_target(arch); + format!("{}.{}", major, minor) +} + pub fn macos_llvm_target(arch: &str) -> String { let (major, minor) = macos_deployment_target(arch); format!("{}-apple-macosx{}.{}.0", arch, major, minor) @@ -109,7 +152,7 @@ pub fn ios_llvm_target(arch: &str) -> String { format!("{}-apple-ios{}.{}.0", arch, major, minor) } -pub fn ios_lld_platform_version() -> String { +fn ios_lld_platform_version() -> String { let (major, minor) = ios_deployment_target(); format!("{}.{}", major, minor) } @@ -123,7 +166,7 @@ fn tvos_deployment_target() -> (u32, u32) { deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((7, 0)) } -pub fn tvos_lld_platform_version() -> String { +fn tvos_lld_platform_version() -> String { let (major, minor) = tvos_deployment_target(); format!("{}.{}", major, minor) } @@ -132,7 +175,7 @@ fn watchos_deployment_target() -> (u32, u32) { deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0)) } -pub fn watchos_lld_platform_version() -> String { +fn watchos_lld_platform_version() -> String { let (major, minor) = watchos_deployment_target(); format!("{}.{}", major, minor) } diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs index d77558f0f8429..bf3ebaa2840f6 100644 --- a/compiler/rustc_target/src/spec/apple_sdk_base.rs +++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{cvs, LinkArgs, LinkerFlavor, LldFlavor, TargetOptions}; +use crate::spec::{cvs, TargetOptions}; use std::borrow::Cow; use Arch::*; @@ -61,53 +61,13 @@ fn link_env_remove(arch: Arch) -> Cow<'static, [Cow<'static, str>]> { } } -fn pre_link_args(os: &'static str, arch: Arch) -> LinkArgs { - let mut args = LinkArgs::new(); - - let target_abi = target_abi(arch); - - let platform_name = match target_abi { - "sim" => format!("{}-simulator", os), - "macabi" => "mac-catalyst".to_string(), - _ => os.to_string(), - }; - - let platform_version = match os.as_ref() { - "ios" => super::apple_base::ios_lld_platform_version(), - "tvos" => super::apple_base::tvos_lld_platform_version(), - "watchos" => super::apple_base::watchos_lld_platform_version(), - _ => unreachable!(), - }; - - let arch_str = target_arch_name(arch); - - if target_abi != "macabi" { - args.insert(LinkerFlavor::Gcc, vec!["-arch".into(), arch_str.into()]); - } - - args.insert( - LinkerFlavor::Lld(LldFlavor::Ld64), - vec![ - "-arch".into(), - arch_str.into(), - "-platform_version".into(), - platform_name.into(), - platform_version.clone().into(), - platform_version.into(), - ], - ); - - args -} - pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { TargetOptions { abi: target_abi(arch).into(), cpu: target_cpu(arch).into(), dynamic_linking: false, - pre_link_args: pre_link_args(os, arch), link_env_remove: link_env_remove(arch), has_thread_local: false, - ..super::apple_base::opts(os) + ..super::apple_base::opts(os, target_arch_name(arch), target_abi(arch)) } } diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index 1718bd77b868f..5e9ceb844f73c 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -1,7 +1,8 @@ use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::apple_base::opts("macos"); + // ld64 only understand i386 and not i686 + let mut base = super::apple_base::opts("macos", "i386", ""); base.cpu = "yonah".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); 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 dbd26899c1899..176c9dd6b764b 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -2,11 +2,12 @@ use crate::spec::TargetOptions; use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::apple_base::opts("macos"); + let arch = "x86_64"; + let mut base = super::apple_base::opts("macos", arch, ""); base.cpu = "core2".into(); base.max_atomic_width = Some(128); // core2 support cmpxchg16b base.frame_pointer = FramePointer::Always; - base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-arch", "x86_64"]); + base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); 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; @@ -16,7 +17,6 @@ pub fn target() -> Target { // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. - let arch = "x86_64"; let llvm_target = super::apple_base::macos_llvm_target(&arch); Target {