diff options
Diffstat (limited to 'compiler/rustc_target/src/spec')
41 files changed, 561 insertions, 307 deletions
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 6d919a4c2..e72cab629 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -1,26 +1,23 @@ +use super::apple_base::{macos_llvm_target, opts, Arch}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = "arm64"; - let mut base = super::apple_base::opts("macos", arch, ""); + let arch = Arch::Arm64; + let mut 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.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(arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + llvm_target: macos_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), frame_pointer: FramePointer::NonLeaf, diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs index beb904239..b5f9eb125 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs @@ -1,19 +1,17 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_llvm_target, opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the target to pick the right - // MACH-O commands, so we do too. - let arch = "arm64"; - let llvm_target = super::apple_base::ios_llvm_target(arch); - + let arch = Arch::Arm64; Target { - llvm_target: llvm_target.into(), + // 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: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), @@ -30,7 +28,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..opts("ios", Arch::Arm64) + ..opts("ios", arch) }, } } 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 2d2671549..0009972cf 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs @@ -1,17 +1,18 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { let llvm_target = "arm64-apple-ios14.0-macabi"; - let mut base = opts("ios", Arch::Arm64_macabi); + 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]); Target { llvm_target: llvm_target.into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12".into(), max_atomic_width: Some(128), 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 b4e135f66..3374755e2 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs @@ -1,21 +1,17 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::Arm64_sim); - - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the simulator target to pick the right - // MACH-O commands, so we do too. - let arch = "arm64"; - let llvm_target = super::apple_base::ios_sim_llvm_target(arch); - + let arch = Arch::Arm64_sim; Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // IPHONEOS_DEPLOYMENT_TARGET. + // This is required for the simulator target to pick the right + // MACH-O commands, so we do too. + llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), @@ -32,7 +28,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs index 2e31d16dc..bb7c39ff2 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs @@ -1,18 +1,19 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { + let arch = Arch::Arm64; Target { llvm_target: "arm64-apple-tvos".into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), forces_embed_bitcode: true, frame_pointer: FramePointer::NonLeaf, - ..opts("tvos", Arch::Arm64) + ..opts("tvos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs index 3059f4214..e4af4127c 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs @@ -1,21 +1,17 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, watchos_sim_llvm_target, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("watchos", Arch::Arm64_sim); - - // Clang automatically chooses a more specific target based on - // WATCHOS_DEPLOYMENT_TARGET. - // This is required for the simulator target to pick the right - // MACH-O commands, so we do too. - let arch = "arm64"; - let llvm_target = super::apple_base::watchos_sim_llvm_target(arch); - + let arch = Arch::Arm64_sim; Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // WATCHOS_DEPLOYMENT_TARGET. + // This is required for the simulator target to pick the right + // MACH-O commands, so we do too. + llvm_target: watchos_sim_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), @@ -32,7 +28,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("watchos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs b/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs new file mode 100644 index 000000000..916b6137b --- /dev/null +++ b/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs @@ -0,0 +1,28 @@ +use super::nto_qnx_base; +use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "aarch64-unknown-unknown".into(), + pointer_width: 64, + // from: https://llvm.org/docs/LangRef.html#data-layout + // e = little endian + // m:e = ELF mangling: Private symbols get a .L prefix + // i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32 + // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32 + // i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64 + // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 + // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. + // S128 = 128 bits are the natural alignment of the stack in bits. + 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), + pre_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-Vgcc_ntoaarch64le_cxx"], + ), + ..nto_qnx_base::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index ce45fa139..cb2a0c04c 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -40,6 +40,28 @@ pub enum Abi { RustCold, } +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. + // * 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 + // up the arguments. (callee doesn't know how many arguments are there) + // * Same for Fastcall, Vectorcall and Thiscall. + // * System can become Stdcall, so is also a no-no. + // * Other calling conventions are related to hardware or the compiler itself. + match self { + Self::C { .. } + | Self::Cdecl { .. } + | Self::Win64 { .. } + | Self::SysV64 { .. } + | Self::EfiApi => true, + _ => false, + } + } +} + #[derive(Copy, Clone)] pub struct AbiData { abi: Abi, diff --git a/compiler/rustc_target/src/spec/aix_base.rs b/compiler/rustc_target/src/spec/aix_base.rs new file mode 100644 index 000000000..c71c4ba2c --- /dev/null +++ b/compiler/rustc_target/src/spec/aix_base.rs @@ -0,0 +1,32 @@ +use crate::abi::Endian; +use crate::spec::{crt_objects, cvs, Cc, CodeModel, LinkOutputKind, LinkerFlavor, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { + abi: "vec-extabi".into(), + code_model: Some(CodeModel::Small), + cpu: "pwr7".into(), + os: "aix".into(), + vendor: "ibm".into(), + dynamic_linking: true, + endian: Endian::Big, + executables: true, + archive_format: "aix_big".into(), + families: cvs!["unix"], + has_rpath: false, + has_thread_local: true, + crt_static_respected: true, + linker_flavor: LinkerFlavor::Unix(Cc::No), + linker: Some("ld".into()), + eh_frame_header: false, + is_like_aix: true, + default_dwarf_version: 3, + function_sections: true, + pre_link_objects: crt_objects::new(&[ + (LinkOutputKind::DynamicNoPicExe, &["/usr/lib/crt0_64.o", "/usr/lib/crti_64.o"]), + (LinkOutputKind::DynamicPicExe, &["/usr/lib/crt0_64.o", "/usr/lib/crti_64.o"]), + ]), + dll_suffix: ".a".into(), + ..Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/apple/tests.rs b/compiler/rustc_target/src/spec/apple/tests.rs new file mode 100644 index 000000000..3c90a5e7e --- /dev/null +++ b/compiler/rustc_target/src/spec/apple/tests.rs @@ -0,0 +1,35 @@ +use crate::spec::{ + aarch64_apple_darwin, aarch64_apple_ios_sim, aarch64_apple_watchos_sim, i686_apple_darwin, + x86_64_apple_darwin, x86_64_apple_ios, x86_64_apple_tvos, x86_64_apple_watchos_sim, +}; + +#[test] +fn simulator_targets_set_abi() { + let all_sim_targets = [ + x86_64_apple_ios::target(), + x86_64_apple_tvos::target(), + x86_64_apple_watchos_sim::target(), + aarch64_apple_ios_sim::target(), + // Note: There is currently no ARM64 tvOS simulator target + aarch64_apple_watchos_sim::target(), + ]; + + for target in all_sim_targets { + assert_eq!(target.abi, "sim") + } +} + +#[test] +fn macos_link_environment_unmodified() { + let all_macos_targets = [ + aarch64_apple_darwin::target(), + i686_apple_darwin::target(), + x86_64_apple_darwin::target(), + ]; + + for target in all_macos_targets { + // macOS targets should only remove information for cross-compiling, but never + // for the host. + assert_eq!(target.link_env_remove, crate::spec::cvs!["IPHONEOS_DEPLOYMENT_TARGET"]); + } +} diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 40bc59ca1..7f8160b5d 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -3,7 +3,78 @@ use std::{borrow::Cow, env}; use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs}; use crate::spec::{LinkerFlavor, Lld, SplitDebuginfo, StaticCow, TargetOptions}; -fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs { +#[cfg(test)] +#[path = "apple/tests.rs"] +mod tests; + +use Arch::*; +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub enum Arch { + Armv7, + Armv7k, + Armv7s, + Arm64, + Arm64_32, + I386, + I686, + X86_64, + X86_64_sim, + X86_64_macabi, + Arm64_macabi, + Arm64_sim, +} + +impl Arch { + pub fn target_name(self) -> &'static str { + match self { + Armv7 => "armv7", + Armv7k => "armv7k", + Armv7s => "armv7s", + Arm64 | Arm64_macabi | Arm64_sim => "arm64", + Arm64_32 => "arm64_32", + I386 => "i386", + I686 => "i686", + X86_64 | X86_64_sim | X86_64_macabi => "x86_64", + } + } + + pub fn target_arch(self) -> Cow<'static, str> { + Cow::Borrowed(match self { + Armv7 | Armv7k | Armv7s => "arm", + Arm64 | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64", + I386 | I686 => "x86", + X86_64 | X86_64_sim | X86_64_macabi => "x86_64", + }) + } + + fn target_abi(self) -> &'static str { + match self { + Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 => "", + 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... + Arm64_sim | X86_64_sim => "sim", + } + } + + 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", + Arm64 => "apple-a7", + Arm64_32 => "apple-s4", + I386 | I686 => "yonah", + X86_64 | X86_64_sim => "core2", + X86_64_macabi => "core2", + Arm64_macabi => "apple-a12", + Arm64_sim => "apple-a12", + } + } +} + +fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs { let platform_name: StaticCow<str> = match abi { "sim" => format!("{}-simulator", os).into(), "macabi" => "mac-catalyst".into(), @@ -19,6 +90,8 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin } .into(); + let arch = arch.target_name(); + let mut args = TargetOptions::link_args( LinkerFlavor::Darwin(Cc::No, Lld::No), &["-arch", arch, "-platform_version"], @@ -35,24 +108,29 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin args } -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 +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 ELF TLS. + // warnings about the usage of static TLS. // - // Here we detect what version is being requested, defaulting to 10.7. ELF + // 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 = macos_deployment_target("x86_64") >= (10, 7); + let has_thread_local = os == "macos" && macos_deployment_target(Arch::X86_64) >= (10, 7); + + let abi = arch.target_abi(); TargetOptions { + abi: abi.into(), os: os.into(), + cpu: arch.target_cpu().into(), + link_env_remove: link_env_remove(arch, os), vendor: "apple".into(), linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No), // macOS has -dead_strip, which doesn't rely on function_sections @@ -103,46 +181,65 @@ fn deployment_target(var_name: &str) -> Option<(u32, u32)> { .and_then(|(a, b)| a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok()) } -fn macos_default_deployment_target(arch: &str) -> (u32, u32) { - if arch == "arm64" { (11, 0) } else { (10, 7) } +fn macos_default_deployment_target(arch: Arch) -> (u32, u32) { + // Note: Arm64_sim is not included since macOS has no simulator. + if matches!(arch, Arm64 | Arm64_macabi) { (11, 0) } else { (10, 7) } } -fn macos_deployment_target(arch: &str) -> (u32, u32) { +fn macos_deployment_target(arch: Arch) -> (u32, u32) { deployment_target("MACOSX_DEPLOYMENT_TARGET") .unwrap_or_else(|| macos_default_deployment_target(arch)) } -fn macos_lld_platform_version(arch: &str) -> String { +fn macos_lld_platform_version(arch: Arch) -> String { let (major, minor) = macos_deployment_target(arch); format!("{}.{}", major, minor) } -pub fn macos_llvm_target(arch: &str) -> String { +pub fn macos_llvm_target(arch: Arch) -> String { let (major, minor) = macos_deployment_target(arch); - format!("{}-apple-macosx{}.{}.0", arch, major, minor) + format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor) } -pub fn macos_link_env_remove() -> Vec<StaticCow<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".into()) +fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]> { + // Apple platforms only officially support macOS as a host for any compilation. + // + // If building for macOS, we go ahead and remove any erronous environment state + // that's only applicable to cross-OS compilation. Always leave anything for the + // host OS alone though. + if os == "macos" { + 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".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".into()); + env_remove.into() + } else { + // 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 + | Arm64_sim => { + cvs!["MACOSX_DEPLOYMENT_TARGET"] + } + X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], } } - // 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".into()); - env_remove } fn ios_deployment_target() -> (u32, u32) { deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0)) } -pub fn ios_llvm_target(arch: &str) -> String { +pub fn ios_llvm_target(arch: Arch) -> String { // Modern iOS tooling extracts information about deployment target // from LC_BUILD_VERSION. This load command will only be emitted when // we build with a version specific `llvm_target`, with the version @@ -150,7 +247,7 @@ pub fn ios_llvm_target(arch: &str) -> String { // to pick it up (since std and core are still built with the fallback // of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION). let (major, minor) = ios_deployment_target(); - format!("{}-apple-ios{}.{}.0", arch, major, minor) + format!("{}-apple-ios{}.{}.0", arch.target_name(), major, minor) } fn ios_lld_platform_version() -> String { @@ -158,9 +255,9 @@ fn ios_lld_platform_version() -> String { format!("{}.{}", major, minor) } -pub fn ios_sim_llvm_target(arch: &str) -> String { +pub fn ios_sim_llvm_target(arch: Arch) -> String { let (major, minor) = ios_deployment_target(); - format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor) + format!("{}-apple-ios{}.{}.0-simulator", arch.target_name(), major, minor) } fn tvos_deployment_target() -> (u32, u32) { @@ -181,7 +278,7 @@ fn watchos_lld_platform_version() -> String { format!("{}.{}", major, minor) } -pub fn watchos_sim_llvm_target(arch: &str) -> String { +pub fn watchos_sim_llvm_target(arch: Arch) -> String { let (major, minor) = watchos_deployment_target(); - format!("{}-apple-watchos{}.{}.0-simulator", arch, major, minor) + format!("{}-apple-watchos{}.{}.0-simulator", arch.target_name(), major, minor) } diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs deleted file mode 100644 index 49e302676..000000000 --- a/compiler/rustc_target/src/spec/apple_sdk_base.rs +++ /dev/null @@ -1,72 +0,0 @@ -use crate::spec::{cvs, TargetOptions}; -use std::borrow::Cow; - -use Arch::*; -#[allow(non_camel_case_types)] -#[derive(Copy, Clone)] -pub enum Arch { - Armv7, - Armv7k, - Armv7s, - Arm64, - Arm64_32, - I386, - X86_64, - X86_64_macabi, - Arm64_macabi, - Arm64_sim, -} - -fn target_arch_name(arch: Arch) -> &'static str { - match arch { - Armv7 => "armv7", - Armv7k => "armv7k", - Armv7s => "armv7s", - Arm64 | Arm64_macabi | Arm64_sim => "arm64", - Arm64_32 => "arm64_32", - I386 => "i386", - X86_64 | X86_64_macabi => "x86_64", - } -} - -fn target_abi(arch: Arch) -> &'static str { - match arch { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 => "", - X86_64_macabi | Arm64_macabi => "macabi", - Arm64_sim => "sim", - } -} - -fn target_cpu(arch: Arch) -> &'static str { - match arch { - Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher - Armv7k => "cortex-a8", - Armv7s => "cortex-a9", - Arm64 => "apple-a7", - Arm64_32 => "apple-s4", - I386 => "yonah", - X86_64 => "core2", - X86_64_macabi => "core2", - Arm64_macabi => "apple-a12", - Arm64_sim => "apple-a12", - } -} - -fn link_env_remove(arch: Arch) -> Cow<'static, [Cow<'static, str>]> { - match arch { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 | Arm64_sim => { - cvs!["MACOSX_DEPLOYMENT_TARGET"] - } - X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], - } -} - -pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { - TargetOptions { - abi: target_abi(arch).into(), - cpu: target_cpu(arch).into(), - link_env_remove: link_env_remove(arch), - has_thread_local: false, - ..super::apple_base::opts(os, target_arch_name(arch), target_abi(arch)) - } -} diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs index cb7f5f2a5..52ee68e75 100644 --- a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { @@ -12,6 +12,8 @@ pub fn target() -> Target { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), forces_embed_bitcode: true, + dynamic_linking: false, + position_independent_executables: true, // These arguments are not actually invoked - they just have // to look right to pass App Store validation. bitcode_llvm_cmdline: "-triple\0\ diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs index 57fd74a36..3259c8547 100644 --- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7_apple_ios.rs @@ -1,18 +1,21 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_llvm_target, opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let llvm_target = super::apple_base::ios_llvm_target("armv7"); - + let arch = Arch::Armv7; Target { - llvm_target: llvm_target.into(), + // 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: "arm".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+v7,+vfp3,+neon".into(), max_atomic_width: Some(64), - ..opts("ios", Arch::Armv7) + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs index af5d1c2ff..6e1d00d1f 100644 --- a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs @@ -1,17 +1,19 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = opts("watchos", Arch::Armv7k); + let arch = Arch::Armv7k; Target { llvm_target: "armv7k-apple-watchos".into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(), - arch: "arm".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), forces_embed_bitcode: true, + dynamic_linking: false, + position_independent_executables: true, // These arguments are not actually invoked - they just have // to look right to pass App Store validation. bitcode_llvm_cmdline: "-triple\0\ @@ -22,7 +24,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("watchos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs index cc17265b2..be4bc6758 100644 --- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs @@ -1,16 +1,17 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { + let arch = Arch::Armv7s; Target { 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".into(), - arch: "arm".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), - ..opts("ios", Arch::Armv7s) + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs index b85214a9c..581998161 100644 --- a/compiler/rustc_target/src/spec/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs @@ -1,21 +1,23 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::I386); - let llvm_target = super::apple_base::ios_sim_llvm_target("i386"); - + let arch = Arch::I386; Target { - llvm_target: llvm_target.into(), + // 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_sim_llvm_target(arch).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" .into(), - arch: "x86".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..base + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index 15607c12e..ad22467ba 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -1,28 +1,27 @@ +use super::apple_base::{macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - // ld64 only understand i386 and not i686 - let mut base = super::apple_base::opts("macos", "i386", ""); - base.cpu = "yonah".into(); + // ld64 only understands i386 and not i686 + let arch = Arch::I386; + let mut base = opts("macos", arch); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); - base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); base.stack_probes = StackProbeType::X86; base.frame_pointer = FramePointer::Always; - // 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 = "i686"; - let llvm_target = super::apple_base::macos_llvm_target(&arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + // + // While ld64 doesn't understand i686, LLVM does. + llvm_target: macos_llvm_target(Arch::I686).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" .into(), - arch: "x86".into(), + arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs deleted file mode 100644 index f41533a95..000000000 --- a/compiler/rustc_target/src/spec/linux_kernel_base.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::spec::TargetOptions; -use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType}; - -pub fn opts() -> TargetOptions { - TargetOptions { - env: "gnu".into(), - disable_redzone: true, - panic_strategy: PanicStrategy::Abort, - stack_probes: StackProbeType::X86, - frame_pointer: FramePointer::Always, - position_independent_executables: true, - needs_plt: true, - relro_level: RelroLevel::Full, - relocation_model: RelocModel::Static, - - ..Default::default() - } -} diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psx.rs b/compiler/rustc_target/src/spec/mipsel_sony_psx.rs new file mode 100644 index 000000000..12a66efdd --- /dev/null +++ b/compiler/rustc_target/src/spec/mipsel_sony_psx.rs @@ -0,0 +1,37 @@ +use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "mipsel-sony-psx".into(), + pointer_width: 32, + 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: "none".into(), + env: "psx".into(), + vendor: "sony".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + cpu: "mips1".into(), + executables: true, + linker: Some("rust-lld".into()), + relocation_model: RelocModel::Static, + exe_suffix: ".exe".into(), + + // PSX doesn't natively support floats. + features: "+soft-float".into(), + + // This should be 16 bits, but LLVM incorrectly tries emitting MIPS-II SYNC instructions + // for atomic loads and stores. This crashes rustc so we have to disable the Atomic* API + // until this is fixed upstream. See https://reviews.llvm.org/D122427#3420144 for more + // info. + max_atomic_width: Some(0), + + // PSX does not support trap-on-condition instructions. + llvm_args: cvs!["-mno-check-zero-division"], + llvm_abiname: "o32".into(), + panic_strategy: PanicStrategy::Abort, + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 8909cf33a..d05b8aa42 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -34,7 +34,8 @@ //! the target's settings, though `target-feature` and `link-args` will *add* //! to the list specified by the target, rather than replace. -use crate::abi::Endian; +use crate::abi::call::Conv; +use crate::abi::{Endian, Integer, Size, TargetDataLayout, TargetDataLayoutErrors}; use crate::json::{Json, ToJson}; use crate::spec::abi::{lookup as lookup_abi, Abi}; use crate::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault}; @@ -57,9 +58,9 @@ use rustc_macros::HashStable_Generic; pub mod abi; pub mod crt_objects; +mod aix_base; mod android_base; mod apple_base; -mod apple_sdk_base; mod avr_gnu_base; mod bpf_base; mod dragonfly_base; @@ -71,11 +72,11 @@ mod illumos_base; mod l4re_base; mod linux_base; mod linux_gnu_base; -mod linux_kernel_base; mod linux_musl_base; mod linux_uclibc_base; mod msvc_base; mod netbsd_base; +mod nto_qnx_base; mod openbsd_base; mod redox_base; mod solaris_base; @@ -115,7 +116,7 @@ pub enum Lld { /// relevant now. /// /// The second goal is to keep the number of flavors to the minimum if possible. -/// LLD somewhat forces our hand here because that linker is self-sufficent only if its executable +/// LLD somewhat forces our hand here because that linker is self-sufficient only if its executable /// (`argv[0]`) is named in specific way, otherwise it doesn't work and requires a /// `-flavor LLD_FLAVOR` argument to choose which logic to use. Our shipped `rust-lld` in /// particular is not named in such specific way, so it needs the flavor option, so we make our @@ -1003,7 +1004,7 @@ macro_rules! supported_targets { $( #[test] // `#[test]` fn $module() { - tests_impl::test_target(super::$module::target(), $triple); + tests_impl::test_target(super::$module::target()); } )+ } @@ -1027,6 +1028,7 @@ supported_targets! { ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu), ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe), ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl), + ("powerpc64-ibm-aix", powerpc64_ibm_aix), ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu), ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl), ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu), @@ -1071,8 +1073,6 @@ supported_targets! { ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi), ("aarch64-linux-android", aarch64_linux_android), - ("x86_64-unknown-none-linuxkernel", x86_64_unknown_none_linuxkernel), - ("aarch64-unknown-freebsd", aarch64_unknown_freebsd), ("armv6-unknown-freebsd", armv6_unknown_freebsd), ("armv7-unknown-freebsd", armv7_unknown_freebsd), @@ -1222,6 +1222,7 @@ supported_targets! { ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf), ("mipsel-sony-psp", mipsel_sony_psp), + ("mipsel-sony-psx", mipsel_sony_psx), ("mipsel-unknown-none", mipsel_unknown_none), ("thumbv4t-none-eabi", thumbv4t_none_eabi), ("armv4t-none-eabi", armv4t_none_eabi), @@ -1245,6 +1246,9 @@ supported_targets! { ("x86_64-unknown-none", x86_64_unknown_none), ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl), + + ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx_710), + ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710), } /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]> @@ -1313,6 +1317,35 @@ pub struct Target { pub options: TargetOptions, } +impl Target { + pub fn parse_data_layout<'a>(&'a self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> { + let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(&self.data_layout)?; + + // Perform consistency checks against the Target information. + if dl.endian != self.endian { + return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture { + dl: dl.endian.as_str(), + target: self.endian.as_str(), + }); + } + + let target_pointer_width: u64 = self.pointer_width.into(); + if dl.pointer_size.bits() != target_pointer_width { + return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth { + pointer_size: dl.pointer_size.bits(), + target: self.pointer_width, + }); + } + + dl.c_enum_min_size = match Integer::from_size(Size::from_bits(self.c_enum_min_bits)) { + Ok(bits) => bits, + Err(err) => return Err(TargetDataLayoutErrors::InvalidBitsSize { err }), + }; + + Ok(dl) + } +} + pub trait HasTargetSpec { fn target_spec(&self) -> &Target; } @@ -1452,6 +1485,9 @@ pub struct TargetOptions { 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 AIX's. Linker options on AIX are special and it uses + /// XCOFF as binary format. Defaults to false. + pub is_like_aix: bool, /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS, /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. /// Also indiates whether to use Apple-specific ABI changes, such as extending function @@ -1526,9 +1562,9 @@ pub struct TargetOptions { /// Flag indicating whether #[thread_local] is available for this target. pub has_thread_local: bool, - // This is mainly for easy compatibility with emscripten. - // If we give emcc .o files that are actually .bc files it - // will 'just work'. + /// This is mainly for easy compatibility with emscripten. + /// If we give emcc .o files that are actually .bc files it + /// will 'just work'. pub obj_is_bitcode: bool, /// Whether the target requires that emitted object code includes bitcode. pub forces_embed_bitcode: bool, @@ -1667,6 +1703,14 @@ pub struct TargetOptions { /// Whether the target supports stack canary checks. `true` by default, /// since this is most common among tier 1 and tier 2 targets. pub supports_stack_protector: bool, + + /// The name of entry function. + /// Default value is "main" + pub entry_name: StaticCow<str>, + + /// The ABI of entry function. + /// Default value is `Conv::C`, i.e. C call convention + pub entry_abi: Conv, } /// Add arguments for the given flavor and also for its "twin" flavors @@ -1807,6 +1851,7 @@ impl Default for TargetOptions { staticlib_suffix: ".a".into(), families: cvs![], abi_return_struct_as_int: false, + is_like_aix: false, is_like_osx: false, is_like_solaris: false, is_like_windows: false, @@ -1883,6 +1928,8 @@ impl Default for TargetOptions { c_enum_min_bits: 32, generate_arange_section: true, supports_stack_protector: true, + entry_name: "main".into(), + entry_abi: Conv::C, } } } @@ -1914,6 +1961,7 @@ impl Target { Abi::Stdcall { unwind } } Abi::System { unwind } => Abi::C { unwind }, + Abi::EfiApi if self.arch == "arm" => Abi::Aapcs { unwind: false }, Abi::EfiApi if self.arch == "x86_64" => Abi::Win64 { unwind: false }, Abi::EfiApi => Abi::C { unwind: false }, @@ -1940,8 +1988,10 @@ impl Target { | PlatformIntrinsic | Unadjusted | Cdecl { .. } - | EfiApi | RustCold => true, + EfiApi => { + ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..]) + } X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]), Aapcs { .. } => "arm" == self.arch, CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]), @@ -2400,6 +2450,18 @@ impl Target { } } } ); + ($key_name:ident, Conv) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match Conv::from_str(s) { + Ok(c) => { + base.$key_name = c; + Some(Ok(())) + } + Err(e) => Some(Err(e)) + } + })).unwrap_or(Ok(())) + } ); } if let Some(j) = obj.remove("target-endian") { @@ -2461,6 +2523,7 @@ impl Target { key!(staticlib_suffix); key!(families, TargetFamilies); key!(abi_return_struct_as_int, bool); + key!(is_like_aix, bool); key!(is_like_osx, bool); key!(is_like_solaris, bool); key!(is_like_windows, bool); @@ -2519,6 +2582,8 @@ impl Target { key!(c_enum_min_bits, u64); key!(generate_arange_section, bool); key!(supports_stack_protector, bool); + key!(entry_name); + key!(entry_abi, Conv)?; if base.is_builtin { // This can cause unfortunate ICEs later down the line. @@ -2593,7 +2658,7 @@ impl Target { // Additionally look in the sysroot under `lib/rustlib/<triple>/target.json` // as a fallback. - let rustlib_path = crate::target_rustlib_path(&sysroot, &target_triple); + let rustlib_path = crate::target_rustlib_path(sysroot, target_triple); let p = PathBuf::from_iter([ Path::new(sysroot), Path::new(&rustlib_path), @@ -2712,6 +2777,7 @@ impl ToJson for Target { target_option_val!(staticlib_suffix); target_option_val!(families, "target-family"); target_option_val!(abi_return_struct_as_int); + target_option_val!(is_like_aix); target_option_val!(is_like_osx); target_option_val!(is_like_solaris); target_option_val!(is_like_windows); @@ -2769,6 +2835,8 @@ 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!(entry_name); + target_option_val!(entry_abi); if let Some(abi) = self.default_adjusted_cabi { d.insert("default-adjusted-cabi".into(), Abi::name(abi).to_json()); diff --git a/compiler/rustc_target/src/spec/nto_qnx_base.rs b/compiler/rustc_target/src/spec/nto_qnx_base.rs new file mode 100644 index 000000000..6fb581ef5 --- /dev/null +++ b/compiler/rustc_target/src/spec/nto_qnx_base.rs @@ -0,0 +1,19 @@ +use crate::spec::{cvs, RelroLevel, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { + crt_static_respected: true, + dynamic_linking: true, + env: "nto71".into(), + executables: true, + families: cvs!["unix"], + has_rpath: true, + has_thread_local: false, + linker: Some("qcc".into()), + os: "nto".into(), + position_independent_executables: true, + static_position_independent_executables: true, + relro_level: RelroLevel::Full, + ..Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs new file mode 100644 index 000000000..e3eb9bccd --- /dev/null +++ b/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs @@ -0,0 +1,23 @@ +use crate::spec::{Cc, LinkerFlavor, Target}; + +pub fn target() -> Target { + let mut base = super::aix_base::opts(); + base.max_atomic_width = Some(64); + base.add_pre_link_args( + LinkerFlavor::Unix(Cc::No), + &[ + "-b64".into(), + "-bpT:0x100000000".into(), + "-bpD:0x110000000".into(), + "-bcdtors:all:0:s".into(), + ], + ); + + Target { + llvm_target: "powerpc64-ibm-aix".into(), + pointer_width: 64, + data_layout: "E-m:a-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(), + arch: "powerpc64".into(), + options: base, + } +} diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs index 0539eca6c..8281bac10 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-freebsd".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), 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 7d1bf228c..90dccb280 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-linux-gnu".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), 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 f04f8a48b..1a56c78e6 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-linux-musl".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), 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 67806d578..409b0b269 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs @@ -3,7 +3,7 @@ use crate::spec::{RelocModel, Target, TargetOptions}; pub fn target() -> Target { Target { - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), llvm_target: "riscv64".into(), pointer_width: 64, arch: "riscv64".into(), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs index cd10f3afa..ade9d7762 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-openbsd".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), 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 f371e09be..87aba9171 100644 --- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs @@ -3,7 +3,7 @@ use crate::spec::{RelocModel, Target, TargetOptions}; pub fn target() -> Target { Target { - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), llvm_target: "riscv64".into(), pointer_width: 64, arch: "riscv64".into(), diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index 172da0ed5..e0ecf8037 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -2,15 +2,15 @@ use super::super::*; use std::assert_matches::assert_matches; // Test target self-consistency and JSON encoding/decoding roundtrip. -pub(super) fn test_target(mut target: Target, triple: &str) { +pub(super) fn test_target(mut target: Target) { let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j); target.update_to_cli(); - target.check_consistency(triple); + target.check_consistency(); assert_eq!(recycled_target, Ok(target)); } impl Target { - fn check_consistency(&self, triple: &str) { + fn check_consistency(&self) { assert_eq!(self.is_like_osx, self.vendor == "apple"); assert_eq!(self.is_like_solaris, self.os == "solaris" || self.os == "illumos"); assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi"); @@ -129,8 +129,7 @@ impl Target { if self.dynamic_linking && !(self.is_like_wasm && self.os != "emscripten") { assert_eq!(self.relocation_model, RelocModel::Pic); } - // PIEs are supported but not enabled by default with linuxkernel target. - if self.position_independent_executables && !triple.ends_with("-linuxkernel") { + if self.position_independent_executables { assert_eq!(self.relocation_model, RelocModel::Pic); } // The UEFI targets do not support dynamic linking but still require PIC (#101377). diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 8dad941b5..06529c2e4 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -33,12 +33,6 @@ pub fn target() -> Target { // For now this target just never has an entry symbol no matter the output // type, so unconditionally pass this. "--no-entry", - // 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. - "--export-dynamic", ], ); options.add_pre_link_args( @@ -48,7 +42,6 @@ pub fn target() -> Target { // otherwise "--target=wasm32-unknown-unknown", "-Wl,--no-entry", - "-Wl,--export-dynamic", ], ); diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index 93a956403..a0476d542 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -72,7 +72,8 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use super::{crt_objects, wasm_base, Cc, LinkerFlavor, Target}; +use super::crt_objects::{self, LinkSelfContainedDefault}; +use super::{wasm_base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { let mut options = wasm_base::options(); @@ -83,6 +84,9 @@ pub fn target() -> Target { options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained(); options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); + // FIXME: Figure out cases in which WASM needs to link with a native toolchain. + options.link_self_contained = LinkSelfContainedDefault::True; + // Right now this is a bit of a workaround but we're currently saying that // the target by default has a static crt which we're taking as a signal // for "use the bundled crt". If that's turned off then the system's crt @@ -100,6 +104,10 @@ pub fn target() -> Target { // `args::args()` makes the WASI API calls itself. options.main_needs_argc_argv = false; + // And, WASI mangles the name of "main" to distinguish between different + // signatures. + options.entry_name = "__main_void".into(); + Target { llvm_target: "wasm32-wasi".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs index 528a84a8b..625d3b37c 100644 --- a/compiler/rustc_target/src/spec/wasm_base.rs +++ b/compiler/rustc_target/src/spec/wasm_base.rs @@ -1,4 +1,3 @@ -use super::crt_objects::LinkSelfContainedDefault; use super::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel}; pub fn options() -> TargetOptions { @@ -95,9 +94,6 @@ pub fn options() -> TargetOptions { pre_link_args, - // FIXME: Figure out cases in which WASM needs to link with a native toolchain. - link_self_contained: LinkSelfContainedDefault::True, - // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when // 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 diff --git a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs index 58210c75a..cada28652 100644 --- a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs @@ -1,4 +1,5 @@ -use crate::spec::{cvs, Cc, LinkerFlavor, Lld, TargetOptions}; +use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions}; +use std::borrow::Cow; pub fn opts() -> TargetOptions { // We cannot use `-nodefaultlibs` because compiler-rt has to be passed @@ -36,7 +37,10 @@ pub fn opts() -> TargetOptions { eh_frame_header: false, no_default_libraries: false, has_thread_local: true, - + // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to + // output DWO, despite using DWARF, doesn't use ELF.. + debuginfo_kind: DebuginfoKind::Pdb, + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..Default::default() } } 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 087be1b95..9a3e7a805 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -1,29 +1,26 @@ +use super::apple_base::{macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - 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 + let arch = Arch::X86_64; + let mut base = opts("macos", arch); + base.max_atomic_width = Some(128); // core2 supports cmpxchg16b base.frame_pointer = FramePointer::Always; base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); - base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); base.stack_probes = StackProbeType::X86; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; - // 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(&arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + llvm_target: macos_llvm_target(arch).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" .into(), - arch: arch.into(), + arch: arch.target_arch(), 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 e6143025d..fbd3ebd4d 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs @@ -1,20 +1,18 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::X86_64); - let llvm_target = super::apple_base::ios_sim_llvm_target("x86_64"); - + let arch = Arch::X86_64_sim; Target { - llvm_target: llvm_target.into(), + llvm_target: ios_sim_llvm_target(arch).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" .into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..base + ..opts("ios", arch) }, } } 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 13259205a..0f3f85199 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,10 +1,11 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let llvm_target = "x86_64-apple-ios13.0-macabi"; - let mut base = opts("ios", Arch::X86_64_macabi); + 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]); Target { @@ -12,7 +13,7 @@ pub fn target() -> Target { 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" .into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, 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 3d54da086..550ce0b9c 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs @@ -1,17 +1,17 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("tvos", Arch::X86_64); + let arch = Arch::X86_64_sim; Target { llvm_target: "x86_64-apple-tvos".into(), pointer_width: 64, data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..base + ..opts("tvos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs index e499b1985..75ce02cba 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs @@ -1,18 +1,14 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, watchos_sim_llvm_target, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("watchos", Arch::X86_64); - - let arch = "x86_64"; - let llvm_target = super::apple_base::watchos_sim_llvm_target(arch); - + let arch = Arch::X86_64_sim; Target { - llvm_target: llvm_target.into(), + llvm_target: watchos_sim_llvm_target(arch).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" .into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, @@ -28,7 +24,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("watchos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs new file mode 100644 index 000000000..e9b3acee2 --- /dev/null +++ b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs @@ -0,0 +1,21 @@ +use super::nto_qnx_base; +use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "x86_64-pc-unknown".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" + .into(), + arch: "x86_64".into(), + options: TargetOptions { + cpu: "x86-64".into(), + max_atomic_width: Some(64), + pre_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-Vgcc_ntox86_64_cxx"], + ), + ..nto_qnx_base::opts() + }, + } +} 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 deleted file mode 100644 index ebd9636ff..000000000 --- a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs +++ /dev/null @@ -1,28 +0,0 @@ -// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for -// generic Linux kernel options. - -use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, Target}; - -pub fn target() -> Target { - let mut base = super::linux_kernel_base::opts(); - 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".into(); - base.code_model = Some(CodeModel::Kernel); - base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); - - 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".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" - .into(), - arch: "x86_64".into(), - - options: base, - } -} |