summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_target/src/spec
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_target/src/spec')
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_darwin.rs30
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios.rs36
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs32
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs38
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_tvos.rs18
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs38
-rw-r--r--compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs18
-rw-r--r--compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs21
-rw-r--r--compiler/rustc_target/src/spec/aarch64_fuchsia.rs15
-rw-r--r--compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs19
-rw-r--r--compiler/rustc_target/src/spec/aarch64_linux_android.rs25
-rw-r--r--compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs26
-rw-r--r--compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding_linker_script.ld78
-rw-r--r--compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs16
-rw-r--r--compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs15
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs18
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs15
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs23
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs17
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs14
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs15
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_none.rs29
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs30
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs11
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_redox.rs14
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs20
-rw-r--r--compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs14
-rw-r--r--compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs11
-rw-r--r--compiler/rustc_target/src/spec/abi.rs175
-rw-r--r--compiler/rustc_target/src/spec/abi/tests.rs27
-rw-r--r--compiler/rustc_target/src/spec/android_base.rs15
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs143
-rw-r--r--compiler/rustc_target/src/spec/apple_sdk_base.rs113
-rw-r--r--compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs28
-rw-r--r--compiler/rustc_target/src/spec/arm_linux_androideabi.rs18
-rw-r--r--compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs17
-rw-r--r--compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs17
-rw-r--r--compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs22
-rw-r--r--compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs22
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabi.rs27
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs28
-rw-r--r--compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs19
-rw-r--r--compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs19
-rw-r--r--compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs23
-rw-r--r--compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs19
-rw-r--r--compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs19
-rw-r--r--compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs19
-rw-r--r--compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs38
-rw-r--r--compiler/rustc_target/src/spec/armv7_apple_ios.rs18
-rw-r--r--compiler/rustc_target/src/spec/armv7_linux_androideabi.rs27
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs19
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs20
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs21
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs26
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs25
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs23
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs24
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs19
-rw-r--r--compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs17
-rw-r--r--compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs19
-rw-r--r--compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs19
-rw-r--r--compiler/rustc_target/src/spec/armv7a_none_eabi.rs40
-rw-r--r--compiler/rustc_target/src/spec/armv7a_none_eabihf.rs32
-rw-r--r--compiler/rustc_target/src/spec/armv7k_apple_watchos.rs28
-rw-r--r--compiler/rustc_target/src/spec/armv7r_none_eabi.rs26
-rw-r--r--compiler/rustc_target/src/spec/armv7r_none_eabihf.rs27
-rw-r--r--compiler/rustc_target/src/spec/armv7s_apple_ios.rs16
-rw-r--r--compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs7
-rw-r--r--compiler/rustc_target/src/spec/avr_gnu_base.rs27
-rw-r--r--compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs5
-rw-r--r--compiler/rustc_target/src/spec/bpf_base.rs25
-rw-r--r--compiler/rustc_target/src/spec/bpfeb_unknown_none.rs12
-rw-r--r--compiler/rustc_target/src/spec/bpfel_unknown_none.rs12
-rw-r--r--compiler/rustc_target/src/spec/crt_objects.rs157
-rw-r--r--compiler/rustc_target/src/spec/dragonfly_base.rs14
-rw-r--r--compiler/rustc_target/src/spec/freebsd_base.rs15
-rw-r--r--compiler/rustc_target/src/spec/fuchsia_base.rs38
-rw-r--r--compiler/rustc_target/src/spec/haiku_base.rs11
-rw-r--r--compiler/rustc_target/src/spec/hermit_base.rs21
-rw-r--r--compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs30
-rw-r--r--compiler/rustc_target/src/spec/i386_apple_ios.rs22
-rw-r--r--compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs8
-rw-r--r--compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs8
-rw-r--r--compiler/rustc_target/src/spec/i686_apple_darwin.rs28
-rw-r--r--compiler/rustc_target/src/spec/i686_linux_android.rs26
-rw-r--r--compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs24
-rw-r--r--compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs32
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_freebsd.rs20
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_haiku.rs20
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs20
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs34
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_netbsd.rs20
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_openbsd.rs20
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_uefi.rs89
-rw-r--r--compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs23
-rw-r--r--compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs17
-rw-r--r--compiler/rustc_target/src/spec/i686_wrs_vxworks.rs20
-rw-r--r--compiler/rustc_target/src/spec/illumos_base.rs59
-rw-r--r--compiler/rustc_target/src/spec/l4re_base.rs14
-rw-r--r--compiler/rustc_target/src/spec/linux_base.rs15
-rw-r--r--compiler/rustc_target/src/spec/linux_gnu_base.rs5
-rw-r--r--compiler/rustc_target/src/spec/linux_kernel_base.rs19
-rw-r--r--compiler/rustc_target/src/spec/linux_musl_base.rs16
-rw-r--r--compiler/rustc_target/src/spec/linux_uclibc_base.rs5
-rw-r--r--compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs15
-rw-r--r--compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs26
-rw-r--r--compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs22
-rw-r--r--compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs22
-rw-r--r--compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs20
-rw-r--r--compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs16
-rw-r--r--compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs20
-rw-r--r--compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs17
-rw-r--r--compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs20
-rw-r--r--compiler/rustc_target/src/spec/mipsel_sony_psp.rs34
-rw-r--r--compiler/rustc_target/src/spec/mipsel_sony_psp_linker_script.ld45
-rw-r--r--compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs19
-rw-r--r--compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs16
-rw-r--r--compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs19
-rw-r--r--compiler/rustc_target/src/spec/mipsel_unknown_none.rs27
-rw-r--r--compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs20
-rw-r--r--compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs19
-rw-r--r--compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs22
-rw-r--r--compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs20
-rw-r--r--compiler/rustc_target/src/spec/mod.rs2585
-rw-r--r--compiler/rustc_target/src/spec/msp430_none_elf.rs59
-rw-r--r--compiler/rustc_target/src/spec/msvc_base.rs24
-rw-r--r--compiler/rustc_target/src/spec/netbsd_base.rs16
-rw-r--r--compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs53
-rw-r--r--compiler/rustc_target/src/spec/openbsd_base.rs16
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs17
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs21
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs17
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs17
-rw-r--r--compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs16
-rw-r--r--compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs16
-rw-r--r--compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs16
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs23
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs16
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs21
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs16
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs16
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs16
-rw-r--r--compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs16
-rw-r--r--compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs22
-rw-r--r--compiler/rustc_target/src/spec/redox_base.rs17
-rw-r--r--compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs18
-rw-r--r--compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs18
-rw-r--r--compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs24
-rw-r--r--compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs25
-rw-r--r--compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs24
-rw-r--r--compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs23
-rw-r--r--compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs36
-rw-r--r--compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs25
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs18
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs18
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs18
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs26
-rw-r--r--compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs25
-rw-r--r--compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs23
-rw-r--r--compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs24
-rw-r--r--compiler/rustc_target/src/spec/solaris_base.rs16
-rw-r--r--compiler/rustc_target/src/spec/solid_base.rs13
-rw-r--r--compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs17
-rw-r--r--compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs17
-rw-r--r--compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs18
-rw-r--r--compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs18
-rw-r--r--compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs24
-rw-r--r--compiler/rustc_target/src/spec/tests/tests_impl.rs135
-rw-r--r--compiler/rustc_target/src/spec/thumb_base.rs60
-rw-r--r--compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs69
-rw-r--r--compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs23
-rw-r--r--compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs28
-rw-r--r--compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs18
-rw-r--r--compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs27
-rw-r--r--compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs36
-rw-r--r--compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs18
-rw-r--r--compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs26
-rw-r--r--compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs23
-rw-r--r--compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs29
-rw-r--r--compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs21
-rw-r--r--compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs19
-rw-r--r--compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs25
-rw-r--r--compiler/rustc_target/src/spec/uefi_msvc_base.rs51
-rw-r--r--compiler/rustc_target/src/spec/vxworks_base.rs21
-rw-r--r--compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs34
-rw-r--r--compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs64
-rw-r--r--compiler/rustc_target/src/spec/wasm32_wasi.rs112
-rw-r--r--compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs49
-rw-r--r--compiler/rustc_target/src/spec/wasm_base.rs129
-rw-r--r--compiler/rustc_target/src/spec/windows_gnu_base.rs91
-rw-r--r--compiler/rustc_target/src/spec/windows_gnullvm_base.rs40
-rw-r--r--compiler/rustc_target/src/spec/windows_msvc_base.rs34
-rw-r--r--compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs34
-rw-r--r--compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs11
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_darwin.rs30
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios.rs21
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs23
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_tvos.rs18
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs35
-rw-r--r--compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs84
-rw-r--r--compiler/rustc_target/src/spec/x86_64_fuchsia.rs19
-rw-r--r--compiler/rustc_target/src/spec/x86_64_linux_android.rs21
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_solaris.rs21
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs20
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs18
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs16
-rw-r--r--compiler/rustc_target/src/spec/x86_64_sun_solaris.rs20
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs19
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs21
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs21
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs19
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs20
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs19
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs25
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs25
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs25
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs24
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none.rs40
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs28
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs19
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_redox.rs19
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs36
-rw-r--r--compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs19
-rw-r--r--compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs16
-rw-r--r--compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs20
228 files changed, 8783 insertions, 0 deletions
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
new file mode 100644
index 000000000..9d36e37d7
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
@@ -0,0 +1,30 @@
+use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::apple_base::opts("macos");
+ 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");
+
+ 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(),
+ options: TargetOptions {
+ mcount: "\u{1}mcount".into(),
+ frame_pointer: FramePointer::NonLeaf,
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
new file mode 100644
index 000000000..beb904239
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
@@ -0,0 +1,36 @@
+use super::apple_sdk_base::{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);
+
+ 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(),
+ options: TargetOptions {
+ features: "+neon,+fp-armv8,+apple-a7".into(),
+ max_atomic_width: Some(128),
+ forces_embed_bitcode: true,
+ frame_pointer: FramePointer::NonLeaf,
+ // Taken from a clang build on Xcode 11.4.1.
+ // These arguments are not actually invoked - they just have
+ // to look right to pass App Store validation.
+ bitcode_llvm_cmdline: "-triple\0\
+ arm64-apple-ios11.0.0\0\
+ -emit-obj\0\
+ -disable-llvm-passes\0\
+ -target-abi\0\
+ darwinpcs\0\
+ -Os\0"
+ .into(),
+ ..opts("ios", Arch::Arm64)
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
new file mode 100644
index 000000000..1dad07a9a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -0,0 +1,32 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{FramePointer, LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let llvm_target = "arm64-apple-ios14.0-macabi";
+
+ let mut base = opts("ios", Arch::Arm64_macabi);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-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(),
+ options: TargetOptions {
+ features: "+neon,+fp-armv8,+apple-a12".into(),
+ max_atomic_width: Some(128),
+ forces_embed_bitcode: true,
+ frame_pointer: FramePointer::NonLeaf,
+ // Taken from a clang build on Xcode 11.4.1.
+ // These arguments are not actually invoked - they just have
+ // to look right to pass App Store validation.
+ bitcode_llvm_cmdline: "-triple\0\
+ arm64-apple-ios14.0-macabi\0\
+ -emit-obj\0\
+ -disable-llvm-passes\0\
+ -Os\0"
+ .into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
new file mode 100644
index 000000000..b4e135f66
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
@@ -0,0 +1,38 @@
+use super::apple_sdk_base::{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);
+
+ 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(),
+ options: TargetOptions {
+ features: "+neon,+fp-armv8,+apple-a7".into(),
+ max_atomic_width: Some(128),
+ forces_embed_bitcode: true,
+ frame_pointer: FramePointer::NonLeaf,
+ // Taken from a clang build on Xcode 11.4.1.
+ // These arguments are not actually invoked - they just have
+ // to look right to pass App Store validation.
+ bitcode_llvm_cmdline: "-triple\0\
+ arm64-apple-ios14.0-simulator\0\
+ -emit-obj\0\
+ -disable-llvm-passes\0\
+ -target-abi\0\
+ darwinpcs\0\
+ -Os\0"
+ .into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
new file mode 100644
index 000000000..2e31d16dc
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
@@ -0,0 +1,18 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{FramePointer, Target, TargetOptions};
+
+pub fn target() -> Target {
+ 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(),
+ 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)
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs
new file mode 100644
index 000000000..3059f4214
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs
@@ -0,0 +1,38 @@
+use super::apple_sdk_base::{opts, 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);
+
+ 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(),
+ options: TargetOptions {
+ features: "+neon,+fp-armv8,+apple-a7".into(),
+ max_atomic_width: Some(128),
+ forces_embed_bitcode: true,
+ frame_pointer: FramePointer::NonLeaf,
+ // Taken from a clang build on Xcode 11.4.1.
+ // These arguments are not actually invoked - they just have
+ // to look right to pass App Store validation.
+ bitcode_llvm_cmdline: "-triple\0\
+ arm64-apple-watchos5.0-simulator\0\
+ -emit-obj\0\
+ -disable-llvm-passes\0\
+ -target-abi\0\
+ darwinpcs\0\
+ -Os\0"
+ .into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
new file mode 100644
index 000000000..9bce82a19
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
@@ -0,0 +1,18 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "aarch64_be-unknown-linux-gnu".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ features: "+outline-atomics".into(),
+ max_atomic_width: Some(128),
+ mcount: "\u{1}_mcount".into(),
+ endian: Endian::Big,
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
new file mode 100644
index 000000000..c9ceb55dd
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -0,0 +1,21 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.max_atomic_width = Some(128);
+
+ Target {
+ llvm_target: "aarch64_be-unknown-linux-gnu_ilp32".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ abi: "ilp32".into(),
+ features: "+outline-atomics".into(),
+ mcount: "\u{1}_mcount".into(),
+ endian: Endian::Big,
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs
new file mode 100644
index 000000000..4634433c4
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs
@@ -0,0 +1,15 @@
+use crate::spec::{SanitizerSet, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "aarch64-fuchsia".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ max_atomic_width: Some(128),
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI,
+ ..super::fuchsia_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs
new file mode 100644
index 000000000..6ea9ae266
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs
@@ -0,0 +1,19 @@
+use super::{RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let base = super::solid_base::opts("asp3");
+ Target {
+ llvm_target: "aarch64-unknown-none".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ linker: Some("aarch64-kmc-elf-gcc".into()),
+ features: "+neon,+fp-armv8".into(),
+ relocation_model: RelocModel::Static,
+ disable_redzone: true,
+ max_atomic_width: Some(128),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/aarch64_linux_android.rs
new file mode 100644
index 000000000..c85f7f62a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_linux_android.rs
@@ -0,0 +1,25 @@
+use crate::spec::{SanitizerSet, Target, TargetOptions};
+
+// See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
+// for target ABI requirements.
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "aarch64-linux-android".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ max_atomic_width: Some(128),
+ // As documented in https://developer.android.com/ndk/guides/cpu-features.html
+ // the neon (ASIMD) and FP must exist on all android aarch64 targets.
+ features: "+neon,+fp-armv8".into(),
+ supported_sanitizers: SanitizerSet::CFI
+ | SanitizerSet::HWADDRESS
+ | SanitizerSet::MEMTAG
+ | SanitizerSet::SHADOWCALLSTACK
+ | SanitizerSet::ADDRESS,
+ ..super::android_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs b/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs
new file mode 100644
index 000000000..1b7161fbb
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs
@@ -0,0 +1,26 @@
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelroLevel, Target, TargetOptions};
+
+const LINKER_SCRIPT: &str = include_str!("./aarch64_nintendo_switch_freestanding_linker_script.ld");
+
+/// A base target for Nintendo Switch devices using a pure LLVM toolchain.
+pub fn target() -> Target {
+ Target {
+ llvm_target: "aarch64-unknown-none".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ link_script: Some(LINKER_SCRIPT.into()),
+ os: "horizon".into(),
+ max_atomic_width: Some(128),
+ panic_strategy: PanicStrategy::Abort,
+ position_independent_executables: true,
+ dynamic_linking: true,
+ executables: true,
+ relro_level: RelroLevel::Off,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding_linker_script.ld b/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding_linker_script.ld
new file mode 100644
index 000000000..f3441e659
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding_linker_script.ld
@@ -0,0 +1,78 @@
+OUTPUT_FORMAT(elf64-littleaarch64)
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+
+PHDRS
+{
+ text PT_LOAD FLAGS(5);
+ rodata PT_LOAD FLAGS(4);
+ data PT_LOAD FLAGS(6);
+ bss PT_LOAD FLAGS(6);
+ dynamic PT_DYNAMIC;
+}
+
+SECTIONS
+{
+ . = 0;
+
+ .text : ALIGN(0x1000) {
+ HIDDEN(__text_start = .);
+ KEEP(*(.text.jmp))
+
+ . = 0x80;
+
+ *(.text .text.*)
+ *(.plt .plt.*)
+ }
+
+ /* Read-only sections */
+
+ . = ALIGN(0x1000);
+
+ .module_name : { *(.module_name) } :rodata
+
+ .rodata : { *(.rodata .rodata.*) } :rodata
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym .dynsym.*) }
+ .dynstr : { *(.dynstr .dynstr.*) }
+ .rela.dyn : { *(.rela.dyn) }
+
+ .eh_frame : {
+ HIDDEN(__eh_frame_start = .);
+ *(.eh_frame .eh_frame.*)
+ HIDDEN(__eh_frame_end = .);
+ }
+
+ .eh_frame_hdr : {
+ HIDDEN(__eh_frame_hdr_start = .);
+ *(.eh_frame_hdr .eh_frame_hdr.*)
+ HIDDEN(__eh_frame_hdr_end = .);
+ }
+
+ /* Read-write sections */
+
+ . = ALIGN(0x1000);
+
+ .data : {
+ *(.data .data.*)
+ *(.got .got.*)
+ *(.got.plt .got.plt.*)
+ } :data
+
+ .dynamic : {
+ HIDDEN(__dynamic_start = .);
+ *(.dynamic)
+ }
+
+ /* BSS section */
+
+ . = ALIGN(0x1000);
+
+ .bss : {
+ HIDDEN(__bss_start = .);
+ *(.bss .bss.*)
+ *(COMMON)
+ . = ALIGN(8);
+ HIDDEN(__bss_end = .);
+ } :bss
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs
new file mode 100644
index 000000000..59c6a95c2
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs
@@ -0,0 +1,16 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::windows_gnullvm_base::opts();
+ base.max_atomic_width = Some(64);
+ base.features = "+neon,+fp-armv8".into();
+ base.linker = Some("aarch64-w64-mingw32-clang".into());
+
+ Target {
+ llvm_target: "aarch64-pc-windows-gnu".into(),
+ pointer_width: 64,
+ data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs
new file mode 100644
index 000000000..856ec4fb0
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs
@@ -0,0 +1,15 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::windows_msvc_base::opts();
+ base.max_atomic_width = Some(64);
+ base.features = "+neon,+fp-armv8".into();
+
+ Target {
+ llvm_target: "aarch64-pc-windows-msvc".into(),
+ pointer_width: 64,
+ data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
new file mode 100644
index 000000000..2f39c4862
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
@@ -0,0 +1,18 @@
+use crate::spec::{SanitizerSet, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "aarch64-unknown-freebsd".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ max_atomic_width: Some(128),
+ supported_sanitizers: SanitizerSet::ADDRESS
+ | SanitizerSet::CFI
+ | SanitizerSet::MEMORY
+ | SanitizerSet::THREAD,
+ ..super::freebsd_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
new file mode 100644
index 000000000..1d7269c8d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
@@ -0,0 +1,15 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::hermit_base::opts();
+ base.max_atomic_width = Some(128);
+ base.features = "+strict-align,+neon,+fp-armv8".into();
+
+ Target {
+ llvm_target: "aarch64-unknown-hermit".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
new file mode 100644
index 000000000..3006044d5
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
@@ -0,0 +1,23 @@
+use crate::spec::{SanitizerSet, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "aarch64-unknown-linux-gnu".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ features: "+outline-atomics".into(),
+ mcount: "\u{1}_mcount".into(),
+ max_atomic_width: Some(128),
+ supported_sanitizers: SanitizerSet::ADDRESS
+ | SanitizerSet::CFI
+ | SanitizerSet::LEAK
+ | SanitizerSet::MEMORY
+ | SanitizerSet::MEMTAG
+ | SanitizerSet::THREAD
+ | SanitizerSet::HWADDRESS,
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
new file mode 100644
index 000000000..63023df1d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
@@ -0,0 +1,17 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "aarch64-unknown-linux-gnu_ilp32".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ abi: "ilp32".into(),
+ features: "+outline-atomics".into(),
+ max_atomic_width: Some(128),
+ mcount: "\u{1}_mcount".into(),
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
new file mode 100644
index 000000000..002d0dac2
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
@@ -0,0 +1,14 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.max_atomic_width = Some(128);
+
+ Target {
+ llvm_target: "aarch64-unknown-linux-musl".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions { mcount: "\u{1}_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs
new file mode 100644
index 000000000..703f75022
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs
@@ -0,0 +1,15 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "aarch64-unknown-netbsd".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ mcount: "__mcount".into(),
+ max_atomic_width: Some(128),
+ ..super::netbsd_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
new file mode 100644
index 000000000..d3fd7051a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
@@ -0,0 +1,29 @@
+// Generic AArch64 target for bare-metal code - Floating point enabled
+//
+// Can be used in conjunction with the `target-feature` and
+// `target-cpu` compiler flags to opt-in more hardware-specific
+// features.
+//
+// For example, `-C target-cpu=cortex-a53`.
+
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let opts = TargetOptions {
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ features: "+strict-align,+neon,+fp-armv8".into(),
+ relocation_model: RelocModel::Static,
+ disable_redzone: true,
+ max_atomic_width: Some(128),
+ panic_strategy: PanicStrategy::Abort,
+ ..Default::default()
+ };
+ Target {
+ llvm_target: "aarch64-unknown-none".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: opts,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
new file mode 100644
index 000000000..6316abe1b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
@@ -0,0 +1,30 @@
+// Generic AArch64 target for bare-metal code - Floating point disabled
+//
+// Can be used in conjunction with the `target-feature` and
+// `target-cpu` compiler flags to opt-in more hardware-specific
+// features.
+//
+// For example, `-C target-cpu=cortex-a53`.
+
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let opts = TargetOptions {
+ abi: "softfloat".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ features: "+strict-align,-neon,-fp-armv8".into(),
+ relocation_model: RelocModel::Static,
+ disable_redzone: true,
+ max_atomic_width: Some(128),
+ panic_strategy: PanicStrategy::Abort,
+ ..Default::default()
+ };
+ Target {
+ llvm_target: "aarch64-unknown-none".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: opts,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs
new file mode 100644
index 000000000..3d99040f0
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs
@@ -0,0 +1,11 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "aarch64-unknown-openbsd".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions { max_atomic_width: Some(128), ..super::openbsd_base::opts() },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs
new file mode 100644
index 000000000..6c9be4c8e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs
@@ -0,0 +1,14 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::redox_base::opts();
+ base.max_atomic_width = Some(128);
+
+ Target {
+ llvm_target: "aarch64-unknown-redox".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
new file mode 100644
index 000000000..162b091b2
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
@@ -0,0 +1,20 @@
+// This defines the aarch64 target for UEFI systems as described in the UEFI specification. See the
+// uefi-base module for generic UEFI options.
+
+use super::uefi_msvc_base;
+use crate::spec::{LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut base = uefi_msvc_base::opts();
+
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Msvc, &["/machine:arm64"]);
+
+ Target {
+ llvm_target: "aarch64-unknown-windows".into(),
+ pointer_width: 64,
+ data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs
new file mode 100644
index 000000000..54247fd93
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs
@@ -0,0 +1,14 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::windows_uwp_msvc_base::opts();
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "aarch64-pc-windows-msvc".into(),
+ pointer_width: 64,
+ data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs
new file mode 100644
index 000000000..e118553df
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs
@@ -0,0 +1,11 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "aarch64-unknown-linux-gnu".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions { max_atomic_width: Some(128), ..super::vxworks_base::opts() },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs
new file mode 100644
index 000000000..337554dc9
--- /dev/null
+++ b/compiler/rustc_target/src/spec/abi.rs
@@ -0,0 +1,175 @@
+use std::fmt;
+
+use rustc_macros::HashStable_Generic;
+
+#[cfg(test)]
+mod tests;
+
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
+pub enum Abi {
+ // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the
+ // 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 },
+ PtxKernel,
+ Msp430Interrupt,
+ X86Interrupt,
+ AmdGpuKernel,
+ EfiApi,
+ AvrInterrupt,
+ AvrNonBlockingInterrupt,
+ CCmseNonSecureCall,
+ Wasm,
+ System { unwind: bool },
+ RustIntrinsic,
+ RustCall,
+ PlatformIntrinsic,
+ Unadjusted,
+ RustCold,
+}
+
+#[derive(Copy, Clone)]
+pub struct AbiData {
+ abi: Abi,
+
+ /// Name of this ABI as we like it called.
+ name: &'static str,
+}
+
+#[allow(non_upper_case_globals)]
+const AbiDatas: &[AbiData] = &[
+ AbiData { abi: Abi::Rust, name: "Rust" },
+ AbiData { abi: Abi::C { unwind: false }, name: "C" },
+ AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" },
+ AbiData { abi: Abi::Cdecl { unwind: false }, name: "cdecl" },
+ AbiData { abi: Abi::Cdecl { unwind: true }, name: "cdecl-unwind" },
+ AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall" },
+ AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" },
+ AbiData { abi: Abi::Fastcall { unwind: false }, name: "fastcall" },
+ AbiData { abi: Abi::Fastcall { unwind: true }, name: "fastcall-unwind" },
+ AbiData { abi: Abi::Vectorcall { unwind: false }, name: "vectorcall" },
+ AbiData { abi: Abi::Vectorcall { unwind: true }, name: "vectorcall-unwind" },
+ AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall" },
+ AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" },
+ AbiData { abi: Abi::Aapcs { unwind: false }, name: "aapcs" },
+ AbiData { abi: Abi::Aapcs { unwind: true }, name: "aapcs-unwind" },
+ AbiData { abi: Abi::Win64 { unwind: false }, name: "win64" },
+ AbiData { abi: Abi::Win64 { unwind: true }, name: "win64-unwind" },
+ AbiData { abi: Abi::SysV64 { unwind: false }, name: "sysv64" },
+ AbiData { abi: Abi::SysV64 { unwind: true }, name: "sysv64-unwind" },
+ AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" },
+ AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" },
+ AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" },
+ AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel" },
+ AbiData { abi: Abi::EfiApi, name: "efiapi" },
+ AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" },
+ AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" },
+ AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" },
+ AbiData { abi: Abi::Wasm, name: "wasm" },
+ AbiData { abi: Abi::System { unwind: false }, name: "system" },
+ AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" },
+ AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" },
+ AbiData { abi: Abi::RustCall, name: "rust-call" },
+ AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic" },
+ AbiData { abi: Abi::Unadjusted, name: "unadjusted" },
+ AbiData { abi: Abi::RustCold, name: "rust-cold" },
+];
+
+/// Returns the ABI with the given name (if any).
+pub fn lookup(name: &str) -> Option<Abi> {
+ AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi)
+}
+
+pub fn all_names() -> Vec<&'static str> {
+ AbiDatas.iter().map(|d| d.name).collect()
+}
+
+impl Abi {
+ /// Default ABI chosen for `extern fn` declarations without an explicit ABI.
+ pub const FALLBACK: Abi = Abi::C { unwind: false };
+
+ #[inline]
+ pub fn index(self) -> usize {
+ // N.B., this ordering MUST match the AbiDatas array above.
+ // (This is ensured by the test indices_are_correct().)
+ use Abi::*;
+ let i = match self {
+ // Cross-platform ABIs
+ Rust => 0,
+ C { unwind: false } => 1,
+ C { unwind: true } => 2,
+ // Platform-specific ABIs
+ Cdecl { unwind: false } => 3,
+ Cdecl { unwind: true } => 4,
+ Stdcall { unwind: false } => 5,
+ Stdcall { unwind: true } => 6,
+ Fastcall { unwind: false } => 7,
+ Fastcall { unwind: true } => 8,
+ Vectorcall { unwind: false } => 9,
+ Vectorcall { unwind: true } => 10,
+ Thiscall { unwind: false } => 11,
+ Thiscall { unwind: true } => 12,
+ Aapcs { unwind: false } => 13,
+ Aapcs { unwind: true } => 14,
+ Win64 { unwind: false } => 15,
+ Win64 { unwind: true } => 16,
+ SysV64 { unwind: false } => 17,
+ SysV64 { unwind: true } => 18,
+ PtxKernel => 19,
+ Msp430Interrupt => 20,
+ X86Interrupt => 21,
+ AmdGpuKernel => 22,
+ EfiApi => 23,
+ AvrInterrupt => 24,
+ AvrNonBlockingInterrupt => 25,
+ CCmseNonSecureCall => 26,
+ Wasm => 27,
+ // Cross-platform ABIs
+ System { unwind: false } => 28,
+ System { unwind: true } => 29,
+ RustIntrinsic => 30,
+ RustCall => 31,
+ PlatformIntrinsic => 32,
+ Unadjusted => 33,
+ RustCold => 34,
+ };
+ debug_assert!(
+ AbiDatas
+ .iter()
+ .enumerate()
+ .find(|(_, AbiData { abi, .. })| *abi == self)
+ .map(|(index, _)| index)
+ .expect("abi variant has associated data")
+ == i,
+ "Abi index did not match `AbiDatas` ordering"
+ );
+ i
+ }
+
+ #[inline]
+ pub fn data(self) -> &'static AbiData {
+ &AbiDatas[self.index()]
+ }
+
+ pub fn name(self) -> &'static str {
+ self.data().name
+ }
+}
+
+impl fmt::Display for Abi {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ abi => write!(f, "\"{}\"", abi.name()),
+ }
+ }
+}
diff --git a/compiler/rustc_target/src/spec/abi/tests.rs b/compiler/rustc_target/src/spec/abi/tests.rs
new file mode 100644
index 000000000..8bea5e5ef
--- /dev/null
+++ b/compiler/rustc_target/src/spec/abi/tests.rs
@@ -0,0 +1,27 @@
+use super::*;
+
+#[allow(non_snake_case)]
+#[test]
+fn lookup_Rust() {
+ let abi = lookup("Rust");
+ assert!(abi.is_some() && abi.unwrap().data().name == "Rust");
+}
+
+#[test]
+fn lookup_cdecl() {
+ let abi = lookup("cdecl");
+ assert!(abi.is_some() && abi.unwrap().data().name == "cdecl");
+}
+
+#[test]
+fn lookup_baz() {
+ let abi = lookup("baz");
+ assert!(abi.is_none());
+}
+
+#[test]
+fn indices_are_correct() {
+ for (i, abi_data) in AbiDatas.iter().enumerate() {
+ assert_eq!(i, abi_data.abi.index());
+ }
+}
diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs
new file mode 100644
index 000000000..dc06597db
--- /dev/null
+++ b/compiler/rustc_target/src/spec/android_base.rs
@@ -0,0 +1,15 @@
+use crate::spec::TargetOptions;
+
+pub fn opts() -> TargetOptions {
+ let mut base = super::linux_base::opts();
+ base.os = "android".into();
+ base.default_dwarf_version = 2;
+ base.position_independent_executables = true;
+ base.has_thread_local = false;
+ // This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867
+ // for context. (At that time, there was no `-C force-unwind-tables`, so the only solution
+ // was to always emit `uwtable`).
+ base.default_uwtable = true;
+ base.crt_static_respected = false;
+ base
+}
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
new file mode 100644
index 000000000..15e4fb9be
--- /dev/null
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -0,0 +1,143 @@
+use std::{borrow::Cow, env};
+
+use crate::spec::{cvs, FramePointer, LldFlavor, SplitDebuginfo, TargetOptions};
+
+pub fn opts(os: &'static str) -> TargetOptions {
+ // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
+ // either the linker will complain if it is used or the binary will end up
+ // segfaulting at runtime when run on 10.6. Rust by default supports macOS
+ // 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.
+ //
+ // Here we detect what version is being requested, defaulting to 10.7. ELF
+ // 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);
+
+ TargetOptions {
+ os: os.into(),
+ vendor: "apple".into(),
+ // macOS has -dead_strip, which doesn't rely on function_sections
+ function_sections: false,
+ dynamic_linking: true,
+ linker_is_gnu: false,
+ families: cvs!["unix"],
+ is_like_osx: true,
+ default_dwarf_version: 2,
+ frame_pointer: FramePointer::Always,
+ has_rpath: true,
+ dll_suffix: ".dylib".into(),
+ archive_format: "darwin".into(),
+ has_thread_local,
+ abi_return_struct_as_int: true,
+ emit_debug_gdb_scripts: false,
+ eh_frame_header: false,
+ lld_flavor: LldFlavor::Ld64,
+
+ // The historical default for macOS targets is to run `dsymutil` which
+ // generates a packed version of debuginfo split from the main file.
+ split_debuginfo: SplitDebuginfo::Packed,
+
+ // This environment variable is pretty magical but is intended for
+ // producing deterministic builds. This was first discovered to be used
+ // by the `ar` tool as a way to control whether or not mtime entries in
+ // the archive headers were set to zero or not. It appears that
+ // eventually the linker got updated to do the same thing and now reads
+ // this environment variable too in recent versions.
+ //
+ // For some more info see the commentary on #47086
+ link_env: Cow::Borrowed(&[(Cow::Borrowed("ZERO_AR_DATE"), Cow::Borrowed("1"))]),
+
+ ..Default::default()
+ }
+}
+
+fn deployment_target(var_name: &str) -> Option<(u32, u32)> {
+ let deployment_target = env::var(var_name).ok();
+ deployment_target
+ .as_ref()
+ .and_then(|s| s.split_once('.'))
+ .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_deployment_target(arch: &str) -> (u32, u32) {
+ deployment_target("MACOSX_DEPLOYMENT_TARGET")
+ .unwrap_or_else(|| macos_default_deployment_target(arch))
+}
+
+pub fn macos_llvm_target(arch: &str) -> String {
+ let (major, minor) = macos_deployment_target(arch);
+ format!("{}-apple-macosx{}.{}.0", arch, major, minor)
+}
+
+pub fn macos_link_env_remove() -> Vec<Cow<'static, str>> {
+ let mut env_remove = Vec::with_capacity(2);
+ // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
+ // may occur when we're linking a custom build script while targeting iOS for example.
+ if let Ok(sdkroot) = env::var("SDKROOT") {
+ if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") {
+ env_remove.push("SDKROOT".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
+}
+
+fn ios_deployment_target() -> (u32, u32) {
+ deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0))
+}
+
+pub fn ios_llvm_target(arch: &str) -> 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
+ // set high enough. Luckily one LC_BUILD_VERSION is enough, for Xcode
+ // 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)
+}
+
+pub fn ios_lld_platform_version() -> String {
+ let (major, minor) = ios_deployment_target();
+ format!("{}.{}", major, minor)
+}
+
+pub fn ios_sim_llvm_target(arch: &str) -> String {
+ let (major, minor) = ios_deployment_target();
+ format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor)
+}
+
+fn tvos_deployment_target() -> (u32, u32) {
+ deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((7, 0))
+}
+
+pub fn tvos_lld_platform_version() -> String {
+ let (major, minor) = tvos_deployment_target();
+ format!("{}.{}", major, minor)
+}
+
+fn watchos_deployment_target() -> (u32, u32) {
+ deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0))
+}
+
+pub fn watchos_lld_platform_version() -> String {
+ let (major, minor) = watchos_deployment_target();
+ format!("{}.{}", major, minor)
+}
+
+pub fn watchos_sim_llvm_target(arch: &str) -> String {
+ let (major, minor) = watchos_deployment_target();
+ format!("{}-apple-watchos{}.{}.0-simulator", arch, major, minor)
+}
diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs
new file mode 100644
index 000000000..d77558f0f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs
@@ -0,0 +1,113 @@
+use crate::spec::{cvs, LinkArgs, LinkerFlavor, LldFlavor, 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"],
+ }
+}
+
+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)
+ }
+}
diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
new file mode 100644
index 000000000..7b23fe1c4
--- /dev/null
+++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
@@ -0,0 +1,28 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let base = opts("watchos", Arch::Arm64_32);
+ Target {
+ llvm_target: "arm64_32-apple-watchos".into(),
+ pointer_width: 32,
+ data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128".into(),
+ arch: "aarch64".into(),
+ options: TargetOptions {
+ features: "+neon,+fp-armv8,+apple-a7".into(),
+ max_atomic_width: Some(64),
+ forces_embed_bitcode: true,
+ // These arguments are not actually invoked - they just have
+ // to look right to pass App Store validation.
+ bitcode_llvm_cmdline: "-triple\0\
+ arm64_32-apple-watchos5.0.0\0\
+ -emit-obj\0\
+ -disable-llvm-passes\0\
+ -target-abi\0\
+ darwinpcs\0\
+ -Os\0"
+ .into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/arm_linux_androideabi.rs b/compiler/rustc_target/src/spec/arm_linux_androideabi.rs
new file mode 100644
index 000000000..bbf1fa315
--- /dev/null
+++ b/compiler/rustc_target/src/spec/arm_linux_androideabi.rs
@@ -0,0 +1,18 @@
+use crate::spec::{SanitizerSet, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "arm-linux-androideabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ // https://developer.android.com/ndk/guides/abis.html#armeabi
+ features: "+strict-align,+v5te".into(),
+ supported_sanitizers: SanitizerSet::ADDRESS,
+ max_atomic_width: Some(32),
+ ..super::android_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
new file mode 100644
index 000000000..c0f1827ad
--- /dev/null
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
@@ -0,0 +1,17 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "arm-unknown-linux-gnueabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ features: "+strict-align,+v6".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}__gnu_mcount_nc".into(),
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
new file mode 100644
index 000000000..79b8958c2
--- /dev/null
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
@@ -0,0 +1,17 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "arm-unknown-linux-gnueabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ features: "+strict-align,+v6,+vfp2,-d32".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}__gnu_mcount_nc".into(),
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs
new file mode 100644
index 000000000..3ef441d6a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs
@@ -0,0 +1,22 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it
+ // to determine the calling convention and float ABI, and it doesn't
+ // support the "musleabi" value.
+ llvm_target: "arm-unknown-linux-gnueabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ // Most of these settings are copied from the arm_unknown_linux_gnueabi
+ // target.
+ features: "+strict-align,+v6".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}mcount".into(),
+ ..super::linux_musl_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs
new file mode 100644
index 000000000..eb6660d4c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs
@@ -0,0 +1,22 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+ // uses it to determine the calling convention and float ABI, and it
+ // doesn't support the "musleabihf" value.
+ llvm_target: "arm-unknown-linux-gnueabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ // Most of these settings are copied from the arm_unknown_linux_gnueabihf
+ // target.
+ features: "+strict-align,+v6,+vfp2,-d32".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}mcount".into(),
+ ..super::linux_musl_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
new file mode 100644
index 000000000..511693abe
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
@@ -0,0 +1,27 @@
+// Targets the Big endian Cortex-R4/R5 processor (ARMv7-R)
+
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armebv7r-unknown-none-eabi".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ endian: Endian::Big,
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ relocation_model: RelocModel::Static,
+ panic_strategy: PanicStrategy::Abort,
+ max_atomic_width: Some(32),
+ emit_debug_gdb_scripts: false,
+ // GCC and Clang default to 8 for arm-none here
+ c_enum_min_bits: 8,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
new file mode 100644
index 000000000..5df4a0a15
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
@@ -0,0 +1,28 @@
+// Targets the Cortex-R4F/R5F processor (ARMv7-R)
+
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armebv7r-unknown-none-eabihf".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ endian: Endian::Big,
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ relocation_model: RelocModel::Static,
+ panic_strategy: PanicStrategy::Abort,
+ features: "+vfp3,-d32,-fp16".into(),
+ max_atomic_width: Some(32),
+ emit_debug_gdb_scripts: false,
+ // GCC and Clang default to 8 for arm-none here
+ c_enum_min_bits: 8,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
new file mode 100644
index 000000000..1de63a920
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv4t-unknown-linux-gnueabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ features: "+soft-float,+strict-align".into(),
+ // Atomic operations provided by compiler-builtins
+ max_atomic_width: Some(32),
+ mcount: "\u{1}__gnu_mcount_nc".into(),
+ has_thumb_interworking: true,
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs
new file mode 100644
index 000000000..b94056310
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv5te-unknown-linux-gnueabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ features: "+soft-float,+strict-align".into(),
+ // Atomic operations provided by compiler-builtins
+ max_atomic_width: Some(32),
+ mcount: "\u{1}__gnu_mcount_nc".into(),
+ has_thumb_interworking: true,
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs
new file mode 100644
index 000000000..2530971b5
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs
@@ -0,0 +1,23 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ // FIXME: this comment below does not seem applicable?
+ // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+ // uses it to determine the calling convention and float ABI, and LLVM
+ // doesn't support the "musleabihf" value.
+ llvm_target: "armv5te-unknown-linux-gnueabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ features: "+soft-float,+strict-align".into(),
+ // Atomic operations provided by compiler-builtins
+ max_atomic_width: Some(32),
+ mcount: "\u{1}mcount".into(),
+ has_thumb_interworking: true,
+ ..super::linux_musl_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs
new file mode 100644
index 000000000..a51be10a3
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ features: "+soft-float,+strict-align".into(),
+ // Atomic operations provided by compiler-builtins
+ max_atomic_width: Some(32),
+ mcount: "\u{1}__gnu_mcount_nc".into(),
+ has_thumb_interworking: true,
+ ..super::linux_uclibc_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
new file mode 100644
index 000000000..b7cfccc8b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv6-unknown-freebsd-gnueabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ // FIXME: change env to "gnu" when cfg_target_abi becomes stable
+ env: "gnueabihf".into(),
+ features: "+v6,+vfp2,-d32".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}__gnu_mcount_nc".into(),
+ ..super::freebsd_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs
new file mode 100644
index 000000000..6e26f686f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv6-unknown-netbsdelf-eabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ // FIXME: remove env when cfg_target_abi becomes stable
+ env: "eabihf".into(),
+ features: "+v6,+vfp2,-d32".into(),
+ max_atomic_width: Some(64),
+ mcount: "__mcount".into(),
+ ..super::netbsd_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
new file mode 100644
index 000000000..1bba39393
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
@@ -0,0 +1,38 @@
+use crate::spec::{cvs, LinkerFlavor, RelocModel, Target, TargetOptions};
+
+/// A base target for Nintendo 3DS devices using the devkitARM toolchain.
+///
+/// Requires the devkitARM toolchain for 3DS targets on the host system.
+
+pub fn target() -> Target {
+ let pre_link_args = TargetOptions::link_args(
+ LinkerFlavor::Gcc,
+ &["-specs=3dsx.specs", "-mtune=mpcore", "-mfloat-abi=hard", "-mtp=soft"],
+ );
+
+ Target {
+ llvm_target: "armv6k-none-eabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ os: "horizon".into(),
+ env: "newlib".into(),
+ vendor: "nintendo".into(),
+ abi: "eabihf".into(),
+ linker_flavor: LinkerFlavor::Gcc,
+ cpu: "mpcore".into(),
+ families: cvs!["unix"],
+ linker: Some("arm-none-eabi-gcc".into()),
+ relocation_model: RelocModel::Static,
+ features: "+vfp2".into(),
+ pre_link_args,
+ exe_suffix: ".elf".into(),
+ no_default_libraries: false,
+ // There are some issues in debug builds with this enabled in certain programs.
+ has_thread_local: false,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs
new file mode 100644
index 000000000..57fd74a36
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_apple_ios.rs
@@ -0,0 +1,18 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let llvm_target = super::apple_base::ios_llvm_target("armv7");
+
+ Target {
+ llvm_target: llvm_target.into(),
+ pointer_width: 32,
+ data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ features: "+v7,+vfp3,+neon".into(),
+ max_atomic_width: Some(64),
+ ..opts("ios", Arch::Armv7)
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
new file mode 100644
index 000000000..38c117a49
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
@@ -0,0 +1,27 @@
+use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
+
+// This target if is for the baseline of the Android v7a ABI
+// in thumb mode. It's named armv7-* instead of thumbv7-*
+// for historical reasons. See the thumbv7neon variant for
+// enabling NEON.
+
+// See https://developer.android.com/ndk/guides/abis.html#v7a
+// for target ABI requirements.
+
+pub fn target() -> Target {
+ let mut base = super::android_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-march=armv7-a"]);
+ Target {
+ llvm_target: "armv7-none-linux-android".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ features: "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".into(),
+ supported_sanitizers: SanitizerSet::ADDRESS,
+ max_atomic_width: Some(64),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs
new file mode 100644
index 000000000..bc37b62de
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv7-unknown-freebsd-gnueabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ // FIXME: change env to "gnu" when cfg_target_abi becomes stable
+ env: "gnueabihf".into(),
+ features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}__gnu_mcount_nc".into(),
+ ..super::freebsd_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
new file mode 100644
index 000000000..903042d7e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
@@ -0,0 +1,20 @@
+use crate::spec::{Target, TargetOptions};
+
+// This target is for glibc Linux on ARMv7 without thumb-mode, NEON or
+// hardfloat.
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv7-unknown-linux-gnueabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ features: "+v7,+thumb2,+soft-float,-neon".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}__gnu_mcount_nc".into(),
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs
new file mode 100644
index 000000000..e39ea49a0
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs
@@ -0,0 +1,21 @@
+use crate::spec::{Target, TargetOptions};
+
+// This target is for glibc Linux on ARMv7 without NEON or
+// thumb-mode. See the thumbv7neon variant for enabling both.
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ // Info about features at https://wiki.debian.org/ArmHardFloatPort
+ features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}__gnu_mcount_nc".into(),
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs
new file mode 100644
index 000000000..7dae85773
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs
@@ -0,0 +1,26 @@
+use crate::spec::{Target, TargetOptions};
+
+// This target is for musl Linux on ARMv7 without thumb-mode, NEON or
+// hardfloat.
+
+pub fn target() -> Target {
+ // Most of these settings are copied from the armv7_unknown_linux_gnueabi
+ // target.
+ Target {
+ // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it
+ // to determine the calling convention and float ABI, and it doesn't
+ // support the "musleabi" value.
+ llvm_target: "armv7-unknown-linux-gnueabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ abi: "eabi".into(),
+ features: "+v7,+thumb2,+soft-float,-neon".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}mcount".into(),
+ ..super::linux_musl_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs
new file mode 100644
index 000000000..ba83964bf
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs
@@ -0,0 +1,25 @@
+use crate::spec::{Target, TargetOptions};
+
+// This target is for musl Linux on ARMv7 without thumb-mode or NEON.
+
+pub fn target() -> Target {
+ Target {
+ // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+ // uses it to determine the calling convention and float ABI, and LLVM
+ // doesn't support the "musleabihf" value.
+ llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
+ // target.
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}mcount".into(),
+ ..super::linux_musl_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs
new file mode 100644
index 000000000..171f67070
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs
@@ -0,0 +1,23 @@
+use crate::spec::{Target, TargetOptions};
+
+// This target is for uclibc Linux on ARMv7 without NEON,
+// thumb-mode or hardfloat.
+
+pub fn target() -> Target {
+ let base = super::linux_uclibc_base::opts();
+ Target {
+ llvm_target: "armv7-unknown-linux-gnueabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ features: "+v7,+thumb2,+soft-float,-neon".into(),
+ cpu: "generic".into(),
+ max_atomic_width: Some(64),
+ mcount: "_mcount".into(),
+ abi: "eabi".into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs
new file mode 100644
index 000000000..d3e95a657
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs
@@ -0,0 +1,24 @@
+use crate::spec::{Target, TargetOptions};
+
+// This target is for uclibc Linux on ARMv7 without NEON or
+// thumb-mode. See the thumbv7neon variant for enabling both.
+
+pub fn target() -> Target {
+ let base = super::linux_uclibc_base::opts();
+ Target {
+ llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ // Info about features at https://wiki.debian.org/ArmHardFloatPort
+ features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
+ cpu: "generic".into(),
+ max_atomic_width: Some(64),
+ mcount: "_mcount".into(),
+ abi: "eabihf".into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs
new file mode 100644
index 000000000..c89ae2483
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv7-unknown-netbsdelf-eabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ // FIXME: remove env when cfg_target_abi becomes stable
+ env: "eabihf".into(),
+ features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
+ max_atomic_width: Some(64),
+ mcount: "__mcount".into(),
+ ..super::netbsd_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs
new file mode 100644
index 000000000..c1ab90172
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs
@@ -0,0 +1,17 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ // Info about features at https://wiki.debian.org/ArmHardFloatPort
+ features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
+ max_atomic_width: Some(64),
+ ..super::vxworks_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs
new file mode 100644
index 000000000..b49dc650b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs
@@ -0,0 +1,19 @@
+use super::{RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let base = super::solid_base::opts("asp3");
+ Target {
+ llvm_target: "armv7a-none-eabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ linker: Some("arm-kmc-eabi-gcc".into()),
+ features: "+v7,+soft-float,+thumb2,-neon".into(),
+ relocation_model: RelocModel::Static,
+ disable_redzone: true,
+ max_atomic_width: Some(64),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs
new file mode 100644
index 000000000..7d30238e8
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs
@@ -0,0 +1,19 @@
+use super::{RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let base = super::solid_base::opts("asp3");
+ Target {
+ llvm_target: "armv7a-none-eabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ linker: Some("arm-kmc-eabi-gcc".into()),
+ features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
+ relocation_model: RelocModel::Static,
+ disable_redzone: true,
+ max_atomic_width: Some(64),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
new file mode 100644
index 000000000..cb5cbe158
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
@@ -0,0 +1,40 @@
+// Generic ARMv7-A target for bare-metal code - floating point disabled
+//
+// This is basically the `armv7-unknown-linux-gnueabi` target with some changes
+// (listed below) to bring it closer to the bare-metal `thumb` & `aarch64`
+// targets:
+//
+// - `TargetOptions.features`: added `+strict-align`. rationale: unaligned
+// memory access is disabled on boot on these cores
+// - linker changed to LLD. rationale: C is not strictly needed to build
+// bare-metal binaries (the `gcc` linker has the advantage that it knows where C
+// libraries and crt*.o are but it's not much of an advantage here); LLD is also
+// faster
+// - `panic_strategy` set to `abort`. rationale: matches `thumb` targets
+// - `relocation-model` set to `static`; also no PIE, no relro and no dynamic
+// linking. rationale: matches `thumb` targets
+
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let opts = TargetOptions {
+ abi: "eabi".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ features: "+v7,+thumb2,+soft-float,-neon,+strict-align".into(),
+ relocation_model: RelocModel::Static,
+ disable_redzone: true,
+ max_atomic_width: Some(64),
+ panic_strategy: PanicStrategy::Abort,
+ emit_debug_gdb_scripts: false,
+ c_enum_min_bits: 8,
+ ..Default::default()
+ };
+ Target {
+ llvm_target: "armv7a-none-eabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: opts,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
new file mode 100644
index 000000000..fb5dd2e75
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
@@ -0,0 +1,32 @@
+// Generic ARMv7-A target for bare-metal code - floating point enabled (assumes
+// FPU is present and emits FPU instructions)
+//
+// This is basically the `armv7-unknown-linux-gnueabihf` target with some
+// changes (list in `armv7a_none_eabi.rs`) to bring it closer to the bare-metal
+// `thumb` & `aarch64` targets.
+
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let opts = TargetOptions {
+ abi: "eabihf".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".into(),
+ relocation_model: RelocModel::Static,
+ disable_redzone: true,
+ max_atomic_width: Some(64),
+ panic_strategy: PanicStrategy::Abort,
+ emit_debug_gdb_scripts: false,
+ // GCC and Clang default to 8 for arm-none here
+ c_enum_min_bits: 8,
+ ..Default::default()
+ };
+ Target {
+ llvm_target: "armv7a-none-eabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: opts,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs
new file mode 100644
index 000000000..af5d1c2ff
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs
@@ -0,0 +1,28 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let base = opts("watchos", 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(),
+ options: TargetOptions {
+ features: "+v7,+vfp4,+neon".into(),
+ max_atomic_width: Some(64),
+ forces_embed_bitcode: true,
+ // These arguments are not actually invoked - they just have
+ // to look right to pass App Store validation.
+ bitcode_llvm_cmdline: "-triple\0\
+ armv7k-apple-watchos3.0.0\0\
+ -emit-obj\0\
+ -disable-llvm-passes\0\
+ -target-abi\0\
+ darwinpcs\0\
+ -Os\0"
+ .into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
new file mode 100644
index 000000000..5f1da09b3
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
@@ -0,0 +1,26 @@
+// Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R)
+
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv7r-unknown-none-eabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ abi: "eabi".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ relocation_model: RelocModel::Static,
+ panic_strategy: PanicStrategy::Abort,
+ max_atomic_width: Some(32),
+ emit_debug_gdb_scripts: false,
+ // GCC and Clang default to 8 for arm-none here
+ c_enum_min_bits: 8,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
new file mode 100644
index 000000000..0038ed0df
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
@@ -0,0 +1,27 @@
+// Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R)
+
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv7r-unknown-none-eabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ relocation_model: RelocModel::Static,
+ panic_strategy: PanicStrategy::Abort,
+ features: "+vfp3,-d32,-fp16".into(),
+ max_atomic_width: Some(32),
+ emit_debug_gdb_scripts: false,
+ // GCC and Clang default to 8 for arm-none here
+ c_enum_min_bits: 8,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
new file mode 100644
index 000000000..cc17265b2
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
@@ -0,0 +1,16 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ 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(),
+ options: TargetOptions {
+ features: "+v7,+vfp4,+neon".into(),
+ max_atomic_width: Some(64),
+ ..opts("ios", Arch::Armv7s)
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs
new file mode 100644
index 000000000..b4cf2c5ee
--- /dev/null
+++ b/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs
@@ -0,0 +1,7 @@
+use super::{wasm32_unknown_emscripten, LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut target = wasm32_unknown_emscripten::target();
+ target.add_post_link_args(LinkerFlavor::Em, &["-sWASM=0", "--memory-init-file", "0"]);
+ target
+}
diff --git a/compiler/rustc_target/src/spec/avr_gnu_base.rs b/compiler/rustc_target/src/spec/avr_gnu_base.rs
new file mode 100644
index 000000000..1d441e558
--- /dev/null
+++ b/compiler/rustc_target/src/spec/avr_gnu_base.rs
@@ -0,0 +1,27 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+/// A base target for AVR devices using the GNU toolchain.
+///
+/// Requires GNU avr-gcc and avr-binutils on the host system.
+/// FIXME: Remove the second parameter when const string concatenation is possible.
+pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
+ Target {
+ arch: "avr".into(),
+ data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
+ llvm_target: "avr-unknown-unknown".into(),
+ pointer_width: 16,
+ options: TargetOptions {
+ c_int_width: "16".into(),
+ cpu: target_cpu.into(),
+ exe_suffix: ".elf".into(),
+
+ linker: Some("avr-gcc".into()),
+ eh_frame_header: false,
+ pre_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &[mmcu]),
+ late_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &["-lgcc"]),
+ max_atomic_width: Some(0),
+ atomic_cas: false,
+ ..TargetOptions::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs
new file mode 100644
index 000000000..6c16b03cc
--- /dev/null
+++ b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs
@@ -0,0 +1,5 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ super::avr_gnu_base::target("atmega328", "-mmcu=atmega328")
+}
diff --git a/compiler/rustc_target/src/spec/bpf_base.rs b/compiler/rustc_target/src/spec/bpf_base.rs
new file mode 100644
index 000000000..3c4da6f88
--- /dev/null
+++ b/compiler/rustc_target/src/spec/bpf_base.rs
@@ -0,0 +1,25 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, TargetOptions};
+
+pub fn opts(endian: Endian) -> TargetOptions {
+ TargetOptions {
+ allow_asm: true,
+ endian,
+ linker_flavor: LinkerFlavor::BpfLinker,
+ atomic_cas: false,
+ dynamic_linking: true,
+ no_builtins: true,
+ panic_strategy: PanicStrategy::Abort,
+ position_independent_executables: true,
+ // Disable MergeFunctions since:
+ // - older kernels don't support bpf-to-bpf calls
+ // - on newer kernels, userspace still needs to relocate before calling
+ // BPF_PROG_LOAD and not all BPF libraries do that yet
+ merge_functions: MergeFunctions::Disabled,
+ obj_is_bitcode: true,
+ requires_lto: false,
+ singlethread: true,
+ max_atomic_width: Some(64),
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs
new file mode 100644
index 000000000..174ddfa50
--- /dev/null
+++ b/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs
@@ -0,0 +1,12 @@
+use crate::spec::Target;
+use crate::{abi::Endian, spec::bpf_base};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "bpfeb".into(),
+ data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
+ pointer_width: 64,
+ arch: "bpf".into(),
+ options: bpf_base::opts(Endian::Big),
+ }
+}
diff --git a/compiler/rustc_target/src/spec/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/bpfel_unknown_none.rs
new file mode 100644
index 000000000..7625e7b0e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/bpfel_unknown_none.rs
@@ -0,0 +1,12 @@
+use crate::spec::Target;
+use crate::{abi::Endian, spec::bpf_base};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "bpfel".into(),
+ data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
+ pointer_width: 64,
+ arch: "bpf".into(),
+ options: bpf_base::opts(Endian::Little),
+ }
+}
diff --git a/compiler/rustc_target/src/spec/crt_objects.rs b/compiler/rustc_target/src/spec/crt_objects.rs
new file mode 100644
index 000000000..52ac3622e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/crt_objects.rs
@@ -0,0 +1,157 @@
+//! Object files providing support for basic runtime facilities and added to the produced binaries
+//! at the start and at the end of linking.
+//!
+//! Table of CRT objects for popular toolchains.
+//! The `crtx` ones are generally distributed with libc and the `begin/end` ones with gcc.
+//! See <https://dev.gentoo.org/~vapier/crt.txt> for some more details.
+//!
+//! | Pre-link CRT objects | glibc | musl | bionic | mingw | wasi |
+//! |----------------------|------------------------|------------------------|------------------|-------------------|--------------|
+//! | dynamic-nopic-exe | crt1, crti, crtbegin | crt1, crti, crtbegin | crtbegin_dynamic | crt2, crtbegin | crt1 |
+//! | dynamic-pic-exe | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1 |
+//! | static-nopic-exe | crt1, crti, crtbeginT | crt1, crti, crtbegin | crtbegin_static | crt2, crtbegin | crt1 |
+//! | static-pic-exe | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1 |
+//! | dynamic-dylib | crti, crtbeginS | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | - |
+//! | static-dylib (gcc) | crti, crtbeginT | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | - |
+//! | static-dylib (clang) | crti, crtbeginT | N/A | crtbegin_static | dllcrt2, crtbegin | - |
+//! | wasi-reactor-exe | N/A | N/A | N/A | N/A | crt1-reactor |
+//!
+//! | Post-link CRT objects | glibc | musl | bionic | mingw | wasi |
+//! |-----------------------|---------------|---------------|----------------|--------|------|
+//! | dynamic-nopic-exe | crtend, crtn | crtend, crtn | crtend_android | crtend | - |
+//! | dynamic-pic-exe | crtendS, crtn | crtendS, crtn | crtend_android | crtend | - |
+//! | static-nopic-exe | crtend, crtn | crtend, crtn | crtend_android | crtend | - |
+//! | static-pic-exe | crtendS, crtn | crtendS, crtn | crtend_android | crtend | - |
+//! | dynamic-dylib | crtendS, crtn | crtendS, crtn | crtend_so | crtend | - |
+//! | static-dylib (gcc) | crtend, crtn | crtendS, crtn | crtend_so | crtend | - |
+//! | static-dylib (clang) | crtendS, crtn | N/A | crtend_so | crtend | - |
+//!
+//! Use cases for rustc linking the CRT objects explicitly:
+//! - rustc needs to add its own Rust-specific objects (mingw is the example)
+//! - gcc wrapper cannot be used for some reason and linker like ld or lld is used directly.
+//! - gcc wrapper pulls wrong CRT objects (e.g. from glibc when we are targeting musl).
+//!
+//! In general it is preferable to rely on the target's native toolchain to pull the objects.
+//! However, for some targets (musl, mingw) rustc historically provides a more self-contained
+//! installation not requiring users to install the native target's toolchain.
+//! In that case rustc distributes the objects as a part of the target's Rust toolchain
+//! and falls back to linking with them manually.
+//! Unlike native toolchains, rustc only currently adds the libc's objects during linking,
+//! but not gcc's. As a result rustc cannot link with C++ static libraries (#36710)
+//! when linking in self-contained mode.
+
+use crate::json::{Json, ToJson};
+use crate::spec::LinkOutputKind;
+use std::borrow::Cow;
+use std::collections::BTreeMap;
+use std::str::FromStr;
+
+pub type CrtObjects = BTreeMap<LinkOutputKind, Vec<Cow<'static, str>>>;
+
+pub(super) fn new(obj_table: &[(LinkOutputKind, &[&'static str])]) -> CrtObjects {
+ obj_table.iter().map(|(z, k)| (*z, k.iter().map(|b| (*b).into()).collect())).collect()
+}
+
+pub(super) fn all(obj: &'static str) -> CrtObjects {
+ new(&[
+ (LinkOutputKind::DynamicNoPicExe, &[obj]),
+ (LinkOutputKind::DynamicPicExe, &[obj]),
+ (LinkOutputKind::StaticNoPicExe, &[obj]),
+ (LinkOutputKind::StaticPicExe, &[obj]),
+ (LinkOutputKind::DynamicDylib, &[obj]),
+ (LinkOutputKind::StaticDylib, &[obj]),
+ ])
+}
+
+pub(super) fn pre_musl_fallback() -> CrtObjects {
+ new(&[
+ (LinkOutputKind::DynamicNoPicExe, &["crt1.o", "crti.o", "crtbegin.o"]),
+ (LinkOutputKind::DynamicPicExe, &["Scrt1.o", "crti.o", "crtbeginS.o"]),
+ (LinkOutputKind::StaticNoPicExe, &["crt1.o", "crti.o", "crtbegin.o"]),
+ (LinkOutputKind::StaticPicExe, &["rcrt1.o", "crti.o", "crtbeginS.o"]),
+ (LinkOutputKind::DynamicDylib, &["crti.o", "crtbeginS.o"]),
+ (LinkOutputKind::StaticDylib, &["crti.o", "crtbeginS.o"]),
+ ])
+}
+
+pub(super) fn post_musl_fallback() -> CrtObjects {
+ new(&[
+ (LinkOutputKind::DynamicNoPicExe, &["crtend.o", "crtn.o"]),
+ (LinkOutputKind::DynamicPicExe, &["crtendS.o", "crtn.o"]),
+ (LinkOutputKind::StaticNoPicExe, &["crtend.o", "crtn.o"]),
+ (LinkOutputKind::StaticPicExe, &["crtendS.o", "crtn.o"]),
+ (LinkOutputKind::DynamicDylib, &["crtendS.o", "crtn.o"]),
+ (LinkOutputKind::StaticDylib, &["crtendS.o", "crtn.o"]),
+ ])
+}
+
+pub(super) fn pre_mingw_fallback() -> CrtObjects {
+ new(&[
+ (LinkOutputKind::DynamicNoPicExe, &["crt2.o", "rsbegin.o"]),
+ (LinkOutputKind::DynamicPicExe, &["crt2.o", "rsbegin.o"]),
+ (LinkOutputKind::StaticNoPicExe, &["crt2.o", "rsbegin.o"]),
+ (LinkOutputKind::StaticPicExe, &["crt2.o", "rsbegin.o"]),
+ (LinkOutputKind::DynamicDylib, &["dllcrt2.o", "rsbegin.o"]),
+ (LinkOutputKind::StaticDylib, &["dllcrt2.o", "rsbegin.o"]),
+ ])
+}
+
+pub(super) fn post_mingw_fallback() -> CrtObjects {
+ all("rsend.o")
+}
+
+pub(super) fn pre_mingw() -> CrtObjects {
+ all("rsbegin.o")
+}
+
+pub(super) fn post_mingw() -> CrtObjects {
+ all("rsend.o")
+}
+
+pub(super) fn pre_wasi_fallback() -> CrtObjects {
+ // Use crt1-command.o instead of crt1.o to enable support for new-style
+ // commands. See https://reviews.llvm.org/D81689 for more info.
+ new(&[
+ (LinkOutputKind::DynamicNoPicExe, &["crt1-command.o"]),
+ (LinkOutputKind::DynamicPicExe, &["crt1-command.o"]),
+ (LinkOutputKind::StaticNoPicExe, &["crt1-command.o"]),
+ (LinkOutputKind::StaticPicExe, &["crt1-command.o"]),
+ (LinkOutputKind::WasiReactorExe, &["crt1-reactor.o"]),
+ ])
+}
+
+pub(super) fn post_wasi_fallback() -> CrtObjects {
+ new(&[])
+}
+
+/// Which logic to use to determine whether to fall back to the "self-contained" mode or not.
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum CrtObjectsFallback {
+ Musl,
+ Mingw,
+ Wasm,
+}
+
+impl FromStr for CrtObjectsFallback {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<CrtObjectsFallback, ()> {
+ Ok(match s {
+ "musl" => CrtObjectsFallback::Musl,
+ "mingw" => CrtObjectsFallback::Mingw,
+ "wasm" => CrtObjectsFallback::Wasm,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl ToJson for CrtObjectsFallback {
+ fn to_json(&self) -> Json {
+ match *self {
+ CrtObjectsFallback::Musl => "musl",
+ CrtObjectsFallback::Mingw => "mingw",
+ CrtObjectsFallback::Wasm => "wasm",
+ }
+ .to_json()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/dragonfly_base.rs b/compiler/rustc_target/src/spec/dragonfly_base.rs
new file mode 100644
index 000000000..de2be7817
--- /dev/null
+++ b/compiler/rustc_target/src/spec/dragonfly_base.rs
@@ -0,0 +1,14 @@
+use crate::spec::{cvs, RelroLevel, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "dragonfly".into(),
+ dynamic_linking: true,
+ families: cvs!["unix"],
+ has_rpath: true,
+ position_independent_executables: true,
+ relro_level: RelroLevel::Full,
+ default_dwarf_version: 2,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/freebsd_base.rs b/compiler/rustc_target/src/spec/freebsd_base.rs
new file mode 100644
index 000000000..8c141aaae
--- /dev/null
+++ b/compiler/rustc_target/src/spec/freebsd_base.rs
@@ -0,0 +1,15 @@
+use crate::spec::{cvs, RelroLevel, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "freebsd".into(),
+ dynamic_linking: true,
+ families: cvs!["unix"],
+ has_rpath: true,
+ position_independent_executables: true,
+ relro_level: RelroLevel::Full,
+ abi_return_struct_as_int: true,
+ default_dwarf_version: 2,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/fuchsia_base.rs b/compiler/rustc_target/src/spec/fuchsia_base.rs
new file mode 100644
index 000000000..df1e3275f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/fuchsia_base.rs
@@ -0,0 +1,38 @@
+use crate::spec::{crt_objects, cvs, LinkOutputKind, LinkerFlavor, LldFlavor, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ let pre_link_args = TargetOptions::link_args(
+ LinkerFlavor::Ld,
+ &[
+ "--build-id",
+ "--hash-style=gnu",
+ "-z",
+ "max-page-size=4096",
+ "-z",
+ "now",
+ "-z",
+ "rodynamic",
+ "-z",
+ "separate-loadable-segments",
+ "--pack-dyn-relocs=relr",
+ ],
+ );
+
+ TargetOptions {
+ os: "fuchsia".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ dynamic_linking: true,
+ families: cvs!["unix"],
+ pre_link_args,
+ pre_link_objects: crt_objects::new(&[
+ (LinkOutputKind::DynamicNoPicExe, &["Scrt1.o"]),
+ (LinkOutputKind::DynamicPicExe, &["Scrt1.o"]),
+ (LinkOutputKind::StaticNoPicExe, &["Scrt1.o"]),
+ (LinkOutputKind::StaticPicExe, &["Scrt1.o"]),
+ ]),
+ position_independent_executables: true,
+ has_thread_local: true,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/haiku_base.rs b/compiler/rustc_target/src/spec/haiku_base.rs
new file mode 100644
index 000000000..8ab874410
--- /dev/null
+++ b/compiler/rustc_target/src/spec/haiku_base.rs
@@ -0,0 +1,11 @@
+use crate::spec::{cvs, RelroLevel, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "haiku".into(),
+ dynamic_linking: true,
+ families: cvs!["unix"],
+ relro_level: RelroLevel::Full,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/hermit_base.rs
new file mode 100644
index 000000000..562ccef7e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/hermit_base.rs
@@ -0,0 +1,21 @@
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel};
+
+pub fn opts() -> TargetOptions {
+ let pre_link_args = TargetOptions::link_args(
+ LinkerFlavor::Ld,
+ &["--build-id", "--hash-style=gnu", "--Bstatic"],
+ );
+
+ TargetOptions {
+ os: "hermit".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ has_thread_local: true,
+ pre_link_args,
+ panic_strategy: PanicStrategy::Abort,
+ position_independent_executables: true,
+ static_position_independent_executables: true,
+ tls_model: TlsModel::InitialExec,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
new file mode 100644
index 000000000..cc2c78c69
--- /dev/null
+++ b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
@@ -0,0 +1,30 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.cpu = "hexagonv60".into();
+ base.max_atomic_width = Some(32);
+ // FIXME: HVX length defaults are per-CPU
+ base.features = "-small-data,+hvx-length128b".into();
+
+ base.crt_static_default = false;
+ base.has_rpath = true;
+ base.linker_is_gnu = false;
+ base.dynamic_linking = true;
+
+ base.c_enum_min_bits = 8;
+
+ Target {
+ llvm_target: "hexagon-unknown-linux-musl".into(),
+ pointer_width: 32,
+ data_layout: concat!(
+ "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32",
+ ":32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32",
+ ":32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048",
+ ":2048:2048"
+ )
+ .into(),
+ arch: "hexagon".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs
new file mode 100644
index 000000000..8b6266c58
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs
@@ -0,0 +1,22 @@
+use super::apple_sdk_base::{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");
+
+ Target {
+ llvm_target: llvm_target.into(),
+ pointer_width: 32,
+ data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+ f64:32:64-f80:128-n8:16:32-S128"
+ .into(),
+ arch: "x86".into(),
+ options: TargetOptions {
+ max_atomic_width: Some(64),
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ stack_probes: StackProbeType::Call,
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
new file mode 100644
index 000000000..801a88933
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::i686_unknown_linux_gnu::target();
+ base.cpu = "i386".into();
+ base.llvm_target = "i386-unknown-linux-gnu".into();
+ base
+}
diff --git a/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
new file mode 100644
index 000000000..a11fbecc3
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::i686_unknown_linux_gnu::target();
+ base.cpu = "i486".into();
+ base.llvm_target = "i486-unknown-linux-gnu".into();
+ base
+}
diff --git a/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs
new file mode 100644
index 000000000..befb0f89f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::i686_pc_windows_msvc::target();
+ base.cpu = "pentium".into();
+ base.llvm_target = "i586-pc-windows-msvc".into();
+ base
+}
diff --git a/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs
new file mode 100644
index 000000000..b699a7af1
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::i686_unknown_linux_gnu::target();
+ base.cpu = "pentium".into();
+ base.llvm_target = "i586-unknown-linux-gnu".into();
+ base
+}
diff --git a/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs
new file mode 100644
index 000000000..55a26eb00
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::i686_unknown_linux_musl::target();
+ base.cpu = "pentium".into();
+ base.llvm_target = "i586-unknown-linux-musl".into();
+ base
+}
diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs
new file mode 100644
index 000000000..1718bd77b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs
@@ -0,0 +1,28 @@
+use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::apple_base::opts("macos");
+ base.cpu = "yonah".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ base.frame_pointer = FramePointer::Always;
+
+ // 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(),
+ 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(),
+ options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/i686_linux_android.rs b/compiler/rustc_target/src/spec/i686_linux_android.rs
new file mode 100644
index 000000000..bdaf5c990
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_linux_android.rs
@@ -0,0 +1,26 @@
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions};
+
+// See https://developer.android.com/ndk/guides/abis.html#x86
+// for target ABI requirements.
+
+pub fn target() -> Target {
+ let mut base = super::android_base::opts();
+
+ base.max_atomic_width = Some(64);
+
+ // https://developer.android.com/ndk/guides/abis.html#x86
+ base.cpu = "pentiumpro".into();
+ base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".into();
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "i686-linux-android".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: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
new file mode 100644
index 000000000..631865439
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
@@ -0,0 +1,24 @@
+use crate::spec::{FramePointer, LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut base = super::windows_gnu_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-gcc".into());
+
+ // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
+ // space available to x86 Windows binaries on x86_64.
+ base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--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_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
new file mode 100644
index 000000000..f4ceaa1ca
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
@@ -0,0 +1,32 @@
+use crate::spec::{LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut base = super::windows_msvc_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+
+ base.add_pre_link_args(
+ LinkerFlavor::Msvc,
+ &[
+ // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
+ // space available to x86 Windows binaries on x86_64.
+ "/LARGEADDRESSAWARE",
+ // Ensure the linker will only produce an image if it can also produce a table of
+ // the image's safe exception handlers.
+ // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers
+ "/SAFESEH",
+ ],
+ );
+ // Workaround for #95429
+ base.has_thread_local = false;
+
+ Target {
+ llvm_target: "i686-pc-windows-msvc".into(),
+ pointer_width: 32,
+ data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+ i64:64-f80:128-n8:16:32-a:0:32-S32"
+ .into(),
+ arch: "x86".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
new file mode 100644
index 000000000..aff284bf2
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
@@ -0,0 +1,20 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::freebsd_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-Wl,-znotext"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "i686-unknown-freebsd".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/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
new file mode 100644
index 000000000..87aa74e40
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
@@ -0,0 +1,20 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::haiku_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "i686-unknown-haiku".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/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
new file mode 100644
index 000000000..765803d16
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
@@ -0,0 +1,20 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "i686-unknown-linux-gnu".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/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
new file mode 100644
index 000000000..d94928043
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
@@ -0,0 +1,34 @@
+use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-Wl,-melf_i386"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ // The unwinder used by i686-unknown-linux-musl, the LLVM libunwind
+ // implementation, apparently relies on frame pointers existing... somehow.
+ // It's not clear to me why nor where this dependency is introduced, but the
+ // test suite does not pass with frame pointers eliminated and it passes
+ // with frame pointers present.
+ //
+ // If you think that this is no longer necessary, then please feel free to
+ // ignore! If it still passes the test suite and the bots then sounds good
+ // to me.
+ //
+ // This may or may not be related to this bug:
+ // https://llvm.org/bugs/show_bug.cgi?id=30879
+ base.frame_pointer = FramePointer::Always;
+
+ Target {
+ llvm_target: "i686-unknown-linux-musl".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+ f64:32:64-f80:32-n8:16:32-S128"
+ .into(),
+ arch: "x86".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
new file mode 100644
index 000000000..8de698b51
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
@@ -0,0 +1,20 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::netbsd_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "i686-unknown-netbsdelf".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: TargetOptions { mcount: "__mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
new file mode 100644
index 000000000..7f25a1a16
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
@@ -0,0 +1,20 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::openbsd_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-fuse-ld=lld"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "i686-unknown-openbsd".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/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/i686_unknown_uefi.rs
new file mode 100644
index 000000000..a2e42c5e6
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_unknown_uefi.rs
@@ -0,0 +1,89 @@
+// This defines the ia32 target for UEFI systems as described in the UEFI specification. See the
+// uefi-base module for generic UEFI options. On ia32 systems
+// UEFI systems always run in protected-mode, have the interrupt-controller pre-configured and
+// force a single-CPU execution.
+// The cdecl ABI is used. It differs from the stdcall or fastcall ABI.
+// "i686-unknown-windows" is used to get the minimal subset of windows-specific features.
+
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::uefi_msvc_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+
+ // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
+ // enable these CPU features explicitly before their first use, otherwise their instructions
+ // will trigger an exception. Rust does not inject any code that enables AVX/MMX/SSE
+ // instruction sets, so this must be done by the firmware. However, existing firmware is known
+ // to leave these uninitialized, thus triggering exceptions if we make use of them. Which is
+ // why we avoid them and instead use soft-floats. This is also what GRUB and friends did so
+ // far.
+ // If you initialize FP units yourself, you can override these flags with custom linker
+ // arguments, thus giving you access to full MMX/SSE acceleration.
+ base.features = "-mmx,-sse,+soft-float".into();
+
+ // Use -GNU here, because of the reason below:
+ // Background and Problem:
+ // If we use i686-unknown-windows, the LLVM IA32 MSVC generates compiler intrinsic
+ // _alldiv, _aulldiv, _allrem, _aullrem, _allmul, which will cause undefined symbol.
+ // A real issue is __aulldiv() is referred by __udivdi3() - udivmod_inner!(), from
+ // https://github.com/rust-lang-nursery/compiler-builtins.
+ // As result, rust-lld generates link error finally.
+ // Root-cause:
+ // In rust\src\llvm-project\llvm\lib\Target\X86\X86ISelLowering.cpp,
+ // we have below code to use MSVC intrinsics. It assumes MSVC target
+ // will link MSVC library. But that is NOT true in UEFI environment.
+ // UEFI does not link any MSVC or GCC standard library.
+ // if (Subtarget.isTargetKnownWindowsMSVC() ||
+ // Subtarget.isTargetWindowsItanium()) {
+ // // Setup Windows compiler runtime calls.
+ // setLibcallName(RTLIB::SDIV_I64, "_alldiv");
+ // setLibcallName(RTLIB::UDIV_I64, "_aulldiv");
+ // setLibcallName(RTLIB::SREM_I64, "_allrem");
+ // setLibcallName(RTLIB::UREM_I64, "_aullrem");
+ // setLibcallName(RTLIB::MUL_I64, "_allmul");
+ // setLibcallCallingConv(RTLIB::SDIV_I64, CallingConv::X86_StdCall);
+ // setLibcallCallingConv(RTLIB::UDIV_I64, CallingConv::X86_StdCall);
+ // setLibcallCallingConv(RTLIB::SREM_I64, CallingConv::X86_StdCall);
+ // setLibcallCallingConv(RTLIB::UREM_I64, CallingConv::X86_StdCall);
+ // setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::X86_StdCall);
+ // }
+ // The compiler intrinsics should be implemented by compiler-builtins.
+ // Unfortunately, compiler-builtins has not provided those intrinsics yet. Such as:
+ // i386/divdi3.S
+ // i386/lshrdi3.S
+ // i386/moddi3.S
+ // i386/muldi3.S
+ // i386/udivdi3.S
+ // i386/umoddi3.S
+ // Possible solution:
+ // 1. Eliminate Intrinsics generation.
+ // 1.1 Choose different target to bypass isTargetKnownWindowsMSVC().
+ // 1.2 Remove the "Setup Windows compiler runtime calls" in LLVM
+ // 2. Implement Intrinsics.
+ // We evaluated all options.
+ // #2 is hard because we need implement the intrinsics (_aulldiv) generated
+ // from the other intrinsics (__udivdi3) implementation with the same
+ // functionality (udivmod_inner). If we let _aulldiv() call udivmod_inner!(),
+ // then we are in loop. We may have to find another way to implement udivmod_inner!().
+ // #1.2 may break the existing usage.
+ // #1.1 seems the simplest solution today.
+ // The IA32 -gnu calling convention is same as the one defined in UEFI specification.
+ // It uses cdecl, EAX/ECX/EDX as volatile register, and EAX/EDX as return value.
+ // We also checked the LLVM X86TargetLowering, the differences between -gnu and -msvc
+ // is fmodf(f32), longjmp() and TLS. None of them impacts the UEFI code.
+ // As a result, we choose -gnu for i686 version before those intrinsics are implemented in
+ // compiler-builtins. After compiler-builtins implements all required intrinsics, we may
+ // remove -gnu and use the default one.
+ Target {
+ llvm_target: "i686-unknown-windows-gnu".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_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
new file mode 100644
index 000000000..d52810d2f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
@@ -0,0 +1,23 @@
+use crate::spec::{FramePointer, LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut base = super::windows_uwp_gnu_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+ base.frame_pointer = FramePointer::Always; // Required for backtraces
+
+ // 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::Ld, &["-m", "i386pe", "--large-address-aware"]);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--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_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs
new file mode 100644
index 000000000..4c657fe90
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs
@@ -0,0 +1,17 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::windows_uwp_msvc_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "i686-pc-windows-msvc".into(),
+ pointer_width: 32,
+ data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+ i64:64-f80:128-n8:16:32-a:0:32-S32"
+ .into(),
+ arch: "x86".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
new file mode 100644
index 000000000..f62404e82
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
@@ -0,0 +1,20 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::vxworks_base::opts();
+ base.cpu = "pentium4".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "i686-unknown-linux-gnu".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/illumos_base.rs b/compiler/rustc_target/src/spec/illumos_base.rs
new file mode 100644
index 000000000..77e000474
--- /dev/null
+++ b/compiler/rustc_target/src/spec/illumos_base.rs
@@ -0,0 +1,59 @@
+use crate::spec::{cvs, FramePointer, LinkerFlavor, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ let late_link_args = TargetOptions::link_args(
+ LinkerFlavor::Gcc,
+ &[
+ // The illumos libc contains a stack unwinding implementation, as
+ // does libgcc_s. The latter implementation includes several
+ // additional symbols that are not always in base libc. To force
+ // the consistent use of just one unwinder, we ensure libc appears
+ // after libgcc_s in the NEEDED list for the resultant binary by
+ // ignoring any attempts to add it as a dynamic dependency until the
+ // very end.
+ // FIXME: This should be replaced by a more complete and generic
+ // mechanism for controlling the order of library arguments passed
+ // to the linker.
+ "-lc",
+ // LLVM will insert calls to the stack protector functions
+ // "__stack_chk_fail" and "__stack_chk_guard" into code in native
+ // object files. Some platforms include these symbols directly in
+ // libc, but at least historically these have been provided in
+ // libssp.so on illumos and Solaris systems.
+ "-lssp",
+ ],
+ );
+
+ TargetOptions {
+ os: "illumos".into(),
+ dynamic_linking: true,
+ has_rpath: true,
+ families: cvs!["unix"],
+ is_like_solaris: true,
+ linker_is_gnu: false,
+ limit_rdylib_exports: false, // Linker doesn't support this
+ frame_pointer: FramePointer::Always,
+ eh_frame_header: false,
+ late_link_args,
+
+ // While we support ELF TLS, rust requires a way to register
+ // cleanup handlers (in C, this would be something along the lines of:
+ // void register_callback(void (*fn)(void *), void *arg);
+ // (see src/libstd/sys/unix/fast_thread_local.rs) that is currently
+ // missing in illumos. For now at least, we must fallback to using
+ // pthread_{get,set}specific.
+ //has_thread_local: true,
+
+ // FIXME: Currently, rust is invoking cc to link, which ends up
+ // causing these to get included twice. We should eventually transition
+ // to having rustc invoke ld directly, in which case these will need to
+ // be uncommented.
+ //
+ // We want XPG6 behavior from libc and libm. See standards(5)
+ //pre_link_objects_exe: vec![
+ // "/usr/lib/amd64/values-Xc.o".into(),
+ // "/usr/lib/amd64/values-xpg6.o".into(),
+ //],
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/l4re_base.rs b/compiler/rustc_target/src/spec/l4re_base.rs
new file mode 100644
index 000000000..a08756861
--- /dev/null
+++ b/compiler/rustc_target/src/spec/l4re_base.rs
@@ -0,0 +1,14 @@
+use crate::spec::{cvs, LinkerFlavor, PanicStrategy, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "l4re".into(),
+ env: "uclibc".into(),
+ linker_flavor: LinkerFlavor::L4Bender,
+ panic_strategy: PanicStrategy::Abort,
+ linker: Some("l4-bender".into()),
+ linker_is_gnu: false,
+ families: cvs!["unix"],
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/linux_base.rs b/compiler/rustc_target/src/spec/linux_base.rs
new file mode 100644
index 000000000..f4fce3b40
--- /dev/null
+++ b/compiler/rustc_target/src/spec/linux_base.rs
@@ -0,0 +1,15 @@
+use crate::spec::{cvs, RelroLevel, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "linux".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/linux_gnu_base.rs b/compiler/rustc_target/src/spec/linux_gnu_base.rs
new file mode 100644
index 000000000..8d6b3f185
--- /dev/null
+++ b/compiler/rustc_target/src/spec/linux_gnu_base.rs
@@ -0,0 +1,5 @@
+use crate::spec::TargetOptions;
+
+pub fn opts() -> TargetOptions {
+ TargetOptions { env: "gnu".into(), ..super::linux_base::opts() }
+}
diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs
new file mode 100644
index 000000000..0f5d85205
--- /dev/null
+++ b/compiler/rustc_target/src/spec/linux_kernel_base.rs
@@ -0,0 +1,19 @@
+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,
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ stack_probes: StackProbeType::Call,
+ 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/linux_musl_base.rs b/compiler/rustc_target/src/spec/linux_musl_base.rs
new file mode 100644
index 000000000..207a87ab0
--- /dev/null
+++ b/compiler/rustc_target/src/spec/linux_musl_base.rs
@@ -0,0 +1,16 @@
+use crate::spec::crt_objects::{self, CrtObjectsFallback};
+use crate::spec::TargetOptions;
+
+pub fn opts() -> TargetOptions {
+ let mut base = super::linux_base::opts();
+
+ base.env = "musl".into();
+ base.pre_link_objects_fallback = crt_objects::pre_musl_fallback();
+ base.post_link_objects_fallback = crt_objects::post_musl_fallback();
+ base.crt_objects_fallback = Some(CrtObjectsFallback::Musl);
+
+ // These targets statically link libc by default
+ base.crt_static_default = true;
+
+ base
+}
diff --git a/compiler/rustc_target/src/spec/linux_uclibc_base.rs b/compiler/rustc_target/src/spec/linux_uclibc_base.rs
new file mode 100644
index 000000000..4ba480ffe
--- /dev/null
+++ b/compiler/rustc_target/src/spec/linux_uclibc_base.rs
@@ -0,0 +1,5 @@
+use crate::spec::TargetOptions;
+
+pub fn opts() -> TargetOptions {
+ TargetOptions { env: "uclibc".into(), ..super::linux_base::opts() }
+}
diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
new file mode 100644
index 000000000..ebd74012d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
@@ -0,0 +1,15 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.max_atomic_width = Some(32);
+
+ Target {
+ llvm_target: "m68k-unknown-linux-gnu".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16".into(),
+ arch: "m68k".into(),
+ options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs
new file mode 100644
index 000000000..3c6ef52c6
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs
@@ -0,0 +1,26 @@
+/// A target tuple for OpenWrt MIPS64 targets
+///
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.cpu = "mips64r2".into();
+ base.features = "+mips64r2,+soft-float".into();
+ base.max_atomic_width = Some(64);
+ base.crt_static_default = false;
+
+ Target {
+ // LLVM doesn't recognize "muslabi64" yet.
+ llvm_target: "mips64-unknown-linux-musl".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+ arch: "mips64".into(),
+ options: TargetOptions {
+ abi: "abi64".into(),
+ endian: Endian::Big,
+ mcount: "_mcount".into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
new file mode 100644
index 000000000..fc5dbd114
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
@@ -0,0 +1,22 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mips64-unknown-linux-gnuabi64".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+ arch: "mips64".into(),
+ options: TargetOptions {
+ abi: "abi64".into(),
+ endian: Endian::Big,
+ // NOTE(mips64r2) matches C toolchain
+ cpu: "mips64r2".into(),
+ features: "+mips64r2".into(),
+ max_atomic_width: Some(64),
+ mcount: "_mcount".into(),
+
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
new file mode 100644
index 000000000..465e97a02
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
@@ -0,0 +1,22 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.cpu = "mips64r2".into();
+ base.features = "+mips64r2".into();
+ base.max_atomic_width = Some(64);
+ Target {
+ // LLVM doesn't recognize "muslabi64" yet.
+ llvm_target: "mips64-unknown-linux-musl".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+ arch: "mips64".into(),
+ options: TargetOptions {
+ abi: "abi64".into(),
+ endian: Endian::Big,
+ mcount: "_mcount".into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
new file mode 100644
index 000000000..e0d5f6f57
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
@@ -0,0 +1,20 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mips64el-unknown-linux-gnuabi64".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+ arch: "mips64".into(),
+ options: TargetOptions {
+ abi: "abi64".into(),
+ // NOTE(mips64r2) matches C toolchain
+ cpu: "mips64r2".into(),
+ features: "+mips64r2".into(),
+ max_atomic_width: Some(64),
+ mcount: "_mcount".into(),
+
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs
new file mode 100644
index 000000000..75575eb7e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs
@@ -0,0 +1,16 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.cpu = "mips64r2".into();
+ base.features = "+mips64r2".into();
+ base.max_atomic_width = Some(64);
+ Target {
+ // LLVM doesn't recognize "muslabi64" yet.
+ llvm_target: "mips64el-unknown-linux-musl".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+ arch: "mips64".into(),
+ options: TargetOptions { abi: "abi64".into(), mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
new file mode 100644
index 000000000..8df8b0b4c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
@@ -0,0 +1,20 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mips-unknown-linux-gnu".into(),
+ pointer_width: 32,
+ data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+ arch: "mips".into(),
+ options: TargetOptions {
+ endian: Endian::Big,
+ cpu: "mips32r2".into(),
+ features: "+mips32r2,+fpxx,+nooddspreg".into(),
+ max_atomic_width: Some(32),
+ mcount: "_mcount".into(),
+
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
new file mode 100644
index 000000000..c2846313a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
@@ -0,0 +1,17 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.cpu = "mips32r2".into();
+ base.features = "+mips32r2,+soft-float".into();
+ base.max_atomic_width = Some(32);
+ base.crt_static_default = false;
+ Target {
+ llvm_target: "mips-unknown-linux-musl".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 { endian: Endian::Big, mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
new file mode 100644
index 000000000..c59bb5fdd
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
@@ -0,0 +1,20 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mips-unknown-linux-uclibc".into(),
+ pointer_width: 32,
+ data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+ arch: "mips".into(),
+ options: TargetOptions {
+ endian: Endian::Big,
+ cpu: "mips32r2".into(),
+ features: "+mips32r2,+soft-float".into(),
+ max_atomic_width: Some(32),
+ mcount: "_mcount".into(),
+
+ ..super::linux_uclibc_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
new file mode 100644
index 000000000..cfc8ec21c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
@@ -0,0 +1,34 @@
+use crate::spec::{cvs, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, LldFlavor, RelocModel};
+
+// The PSP has custom linker requirements.
+const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");
+
+pub fn target() -> Target {
+ let pre_link_args = TargetOptions::link_args(LinkerFlavor::Ld, &["--emit-relocs", "--nmagic"]);
+
+ Target {
+ llvm_target: "mipsel-sony-psp".into(),
+ pointer_width: 32,
+ data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+ arch: "mips".into(),
+
+ options: TargetOptions {
+ os: "psp".into(),
+ vendor: "sony".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ cpu: "mips2".into(),
+ linker: Some("rust-lld".into()),
+ relocation_model: RelocModel::Static,
+
+ // PSP FPU only supports single precision floats.
+ features: "+single-float".into(),
+
+ // PSP does not support trap-on-condition instructions.
+ llvm_args: cvs!["-mno-check-zero-division"],
+ pre_link_args,
+ link_script: Some(LINKER_SCRIPT.into()),
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp_linker_script.ld b/compiler/rustc_target/src/spec/mipsel_sony_psp_linker_script.ld
new file mode 100644
index 000000000..9eb35ad9f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsel_sony_psp_linker_script.ld
@@ -0,0 +1,45 @@
+ENTRY(module_start)
+SECTIONS
+{
+ /* PRX format requires text to begin at 0 */
+ .text 0 : { *(.text .text.*) }
+
+ /* Sort stubs for convenient ordering */
+ .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) }
+
+ /* PSP import library stub sections. Bundles together `.lib.stub.entry.*`
+ * sections for better `--gc-sections` support. */
+ .lib.stub.top : { *(.lib.stub.top) }
+ .lib.stub : { *(.lib.stub) *(.lib.stub.entry.*) }
+ .lib.stub.btm : { *(.lib.stub.btm) }
+
+ /* Keep these sections around, even though they may appear unused to the linker */
+ .lib.ent.top : { KEEP(*(.lib.ent.top)) }
+ .lib.ent : { KEEP(*(.lib.ent)) }
+ .lib.ent.btm : { KEEP(*(.lib.ent.btm)) }
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+
+ /* Add symbols for LLVM's libunwind */
+ __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
+ __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
+ .eh_frame :
+ {
+ __eh_frame_start = .;
+ KEEP(*(.eh_frame))
+ __eh_frame_end = .;
+ }
+
+ /* These are explicitly listed to avoid being merged into .rodata */
+ .rodata.sceResident : { *(.rodata.sceResident) *(.rodata.sceResident.*) }
+ .rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) }
+ /* Sort NIDs for convenient ordering */
+ .rodata.sceNid : { *(.rodata.sceNid) *(SORT(.rodata.sceNid.*)) }
+
+ .rodata : { *(.rodata .rodata.*) }
+ .data : { *(.data .data.*) }
+ .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) }
+ .bss : { *(.bss .bss.*) }
+
+ /DISCARD/ : { *(.rel.sceStub.text .MIPS.abiflags .reginfo) }
+}
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs
new file mode 100644
index 000000000..01346e71a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mipsel-unknown-linux-gnu".into(),
+ pointer_width: 32,
+ data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+ arch: "mips".into(),
+
+ options: TargetOptions {
+ cpu: "mips32r2".into(),
+ features: "+mips32r2,+fpxx,+nooddspreg".into(),
+ max_atomic_width: Some(32),
+ mcount: "_mcount".into(),
+
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs
new file mode 100644
index 000000000..0e8f1a2c8
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs
@@ -0,0 +1,16 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.cpu = "mips32r2".into();
+ base.features = "+mips32r2,+soft-float".into();
+ base.max_atomic_width = Some(32);
+ base.crt_static_default = false;
+ Target {
+ llvm_target: "mipsel-unknown-linux-musl".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 { mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs
new file mode 100644
index 000000000..834207458
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mipsel-unknown-linux-uclibc".into(),
+ pointer_width: 32,
+ data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+ arch: "mips".into(),
+
+ options: TargetOptions {
+ cpu: "mips32r2".into(),
+ features: "+mips32r2,+soft-float".into(),
+ max_atomic_width: Some(32),
+ mcount: "_mcount".into(),
+
+ ..super::linux_uclibc_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
new file mode 100644
index 000000000..fe2aa2de8
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
@@ -0,0 +1,27 @@
+//! Bare MIPS32r2, little endian, softfloat, O32 calling convention
+//!
+//! Can be used for MIPS M4K core (e.g. on PIC32MX devices)
+
+use crate::spec::{LinkerFlavor, LldFlavor, RelocModel};
+use crate::spec::{PanicStrategy, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mipsel-unknown-none".into(),
+ pointer_width: 32,
+ data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+ arch: "mips".into(),
+
+ options: TargetOptions {
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ cpu: "mips32r2".into(),
+ features: "+mips32r2,+soft-float,+noabicalls".into(),
+ max_atomic_width: Some(32),
+ linker: Some("rust-lld".into()),
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ emit_debug_gdb_scripts: false,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
new file mode 100644
index 000000000..1e066b271
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
@@ -0,0 +1,20 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mipsisa32r6-unknown-linux-gnu".into(),
+ pointer_width: 32,
+ data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+ arch: "mips".into(),
+ options: TargetOptions {
+ endian: Endian::Big,
+ cpu: "mips32r6".into(),
+ features: "+mips32r6".into(),
+ max_atomic_width: Some(32),
+ mcount: "_mcount".into(),
+
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs
new file mode 100644
index 000000000..4785929c1
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mipsisa32r6el-unknown-linux-gnu".into(),
+ pointer_width: 32,
+ data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
+ arch: "mips".into(),
+
+ options: TargetOptions {
+ cpu: "mips32r6".into(),
+ features: "+mips32r6".into(),
+ max_atomic_width: Some(32),
+ mcount: "_mcount".into(),
+
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
new file mode 100644
index 000000000..766ac7680
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -0,0 +1,22 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+ arch: "mips64".into(),
+ options: TargetOptions {
+ abi: "abi64".into(),
+ endian: Endian::Big,
+ // NOTE(mips64r6) matches C toolchain
+ cpu: "mips64r6".into(),
+ features: "+mips64r6".into(),
+ max_atomic_width: Some(64),
+ mcount: "_mcount".into(),
+
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
new file mode 100644
index 000000000..d2b07c654
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
@@ -0,0 +1,20 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+ arch: "mips64".into(),
+ options: TargetOptions {
+ abi: "abi64".into(),
+ // NOTE(mips64r6) matches C toolchain
+ cpu: "mips64r6".into(),
+ features: "+mips64r6".into(),
+ max_atomic_width: Some(64),
+ mcount: "_mcount".into(),
+
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
new file mode 100644
index 000000000..f7abeafd3
--- /dev/null
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -0,0 +1,2585 @@
+//! [Flexible target specification.](https://github.com/rust-lang/rfcs/pull/131)
+//!
+//! Rust targets a wide variety of usecases, and in the interest of flexibility,
+//! allows new target triples to be defined in configuration files. Most users
+//! will not need to care about these, but this is invaluable when porting Rust
+//! to a new platform, and allows for an unprecedented level of control over how
+//! the compiler works.
+//!
+//! # Using custom targets
+//!
+//! A target triple, as passed via `rustc --target=TRIPLE`, will first be
+//! compared against the list of built-in targets. This is to ease distributing
+//! rustc (no need for configuration files) and also to hold these built-in
+//! targets as immutable and sacred. If `TRIPLE` is not one of the built-in
+//! targets, rustc will check if a file named `TRIPLE` exists. If it does, it
+//! will be loaded as the target configuration. If the file does not exist,
+//! rustc will search each directory in the environment variable
+//! `RUST_TARGET_PATH` for a file named `TRIPLE.json`. The first one found will
+//! be loaded. If no file is found in any of those directories, a fatal error
+//! will be given.
+//!
+//! Projects defining their own targets should use
+//! `--target=path/to/my-awesome-platform.json` instead of adding to
+//! `RUST_TARGET_PATH`.
+//!
+//! # Defining a new target
+//!
+//! Targets are defined using [JSON](https://json.org/). The `Target` struct in
+//! this module defines the format the JSON file should take, though each
+//! underscore in the field names should be replaced with a hyphen (`-`) in the
+//! JSON file. Some fields are required in every target specification, such as
+//! `llvm-target`, `target-endian`, `target-pointer-width`, `data-layout`,
+//! `arch`, and `os`. In general, options passed to rustc with `-C` override
+//! 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::json::{Json, ToJson};
+use crate::spec::abi::{lookup as lookup_abi, Abi};
+use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use rustc_span::symbol::{sym, Symbol};
+use serde_json::Value;
+use std::borrow::Cow;
+use std::collections::BTreeMap;
+use std::convert::TryFrom;
+use std::hash::{Hash, Hasher};
+use std::iter::FromIterator;
+use std::ops::{Deref, DerefMut};
+use std::path::{Path, PathBuf};
+use std::str::FromStr;
+use std::{fmt, io};
+
+use rustc_macros::HashStable_Generic;
+
+pub mod abi;
+pub mod crt_objects;
+
+mod android_base;
+mod apple_base;
+mod apple_sdk_base;
+mod avr_gnu_base;
+mod bpf_base;
+mod dragonfly_base;
+mod freebsd_base;
+mod fuchsia_base;
+mod haiku_base;
+mod hermit_base;
+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 openbsd_base;
+mod redox_base;
+mod solaris_base;
+mod solid_base;
+mod thumb_base;
+mod uefi_msvc_base;
+mod vxworks_base;
+mod wasm_base;
+mod windows_gnu_base;
+mod windows_gnullvm_base;
+mod windows_msvc_base;
+mod windows_uwp_gnu_base;
+mod windows_uwp_msvc_base;
+
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub enum LinkerFlavor {
+ Em,
+ Gcc,
+ L4Bender,
+ Ld,
+ Msvc,
+ Lld(LldFlavor),
+ PtxLinker,
+ BpfLinker,
+}
+
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub enum LldFlavor {
+ Wasm,
+ Ld64,
+ Ld,
+ Link,
+}
+
+impl LldFlavor {
+ pub fn as_str(&self) -> &'static str {
+ match self {
+ LldFlavor::Wasm => "wasm",
+ LldFlavor::Ld64 => "darwin",
+ LldFlavor::Ld => "gnu",
+ LldFlavor::Link => "link",
+ }
+ }
+
+ fn from_str(s: &str) -> Option<Self> {
+ Some(match s {
+ "darwin" => LldFlavor::Ld64,
+ "gnu" => LldFlavor::Ld,
+ "link" => LldFlavor::Link,
+ "wasm" => LldFlavor::Wasm,
+ _ => return None,
+ })
+ }
+}
+
+impl ToJson for LldFlavor {
+ fn to_json(&self) -> Json {
+ self.as_str().to_json()
+ }
+}
+
+impl ToJson for LinkerFlavor {
+ fn to_json(&self) -> Json {
+ self.desc().to_json()
+ }
+}
+macro_rules! flavor_mappings {
+ ($((($($flavor:tt)*), $string:expr),)*) => (
+ impl LinkerFlavor {
+ pub const fn one_of() -> &'static str {
+ concat!("one of: ", $($string, " ",)*)
+ }
+
+ pub fn from_str(s: &str) -> Option<Self> {
+ Some(match s {
+ $($string => $($flavor)*,)*
+ _ => return None,
+ })
+ }
+
+ pub fn desc(&self) -> &str {
+ match *self {
+ $($($flavor)* => $string,)*
+ }
+ }
+ }
+ )
+}
+
+flavor_mappings! {
+ ((LinkerFlavor::Em), "em"),
+ ((LinkerFlavor::Gcc), "gcc"),
+ ((LinkerFlavor::L4Bender), "l4-bender"),
+ ((LinkerFlavor::Ld), "ld"),
+ ((LinkerFlavor::Msvc), "msvc"),
+ ((LinkerFlavor::PtxLinker), "ptx-linker"),
+ ((LinkerFlavor::BpfLinker), "bpf-linker"),
+ ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
+ ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
+ ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
+ ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
+pub enum PanicStrategy {
+ Unwind,
+ Abort,
+}
+
+impl PanicStrategy {
+ pub fn desc(&self) -> &str {
+ match *self {
+ PanicStrategy::Unwind => "unwind",
+ PanicStrategy::Abort => "abort",
+ }
+ }
+
+ pub const fn desc_symbol(&self) -> Symbol {
+ match *self {
+ PanicStrategy::Unwind => sym::unwind,
+ PanicStrategy::Abort => sym::abort,
+ }
+ }
+
+ pub const fn all() -> [Symbol; 2] {
+ [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
+ }
+}
+
+impl ToJson for PanicStrategy {
+ fn to_json(&self) -> Json {
+ match *self {
+ PanicStrategy::Abort => "abort".to_json(),
+ PanicStrategy::Unwind => "unwind".to_json(),
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Hash)]
+pub enum RelroLevel {
+ Full,
+ Partial,
+ Off,
+ None,
+}
+
+impl RelroLevel {
+ pub fn desc(&self) -> &str {
+ match *self {
+ RelroLevel::Full => "full",
+ RelroLevel::Partial => "partial",
+ RelroLevel::Off => "off",
+ RelroLevel::None => "none",
+ }
+ }
+}
+
+impl FromStr for RelroLevel {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<RelroLevel, ()> {
+ match s {
+ "full" => Ok(RelroLevel::Full),
+ "partial" => Ok(RelroLevel::Partial),
+ "off" => Ok(RelroLevel::Off),
+ "none" => Ok(RelroLevel::None),
+ _ => Err(()),
+ }
+ }
+}
+
+impl ToJson for RelroLevel {
+ fn to_json(&self) -> Json {
+ match *self {
+ RelroLevel::Full => "full".to_json(),
+ RelroLevel::Partial => "partial".to_json(),
+ RelroLevel::Off => "off".to_json(),
+ RelroLevel::None => "None".to_json(),
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Hash)]
+pub enum MergeFunctions {
+ Disabled,
+ Trampolines,
+ Aliases,
+}
+
+impl MergeFunctions {
+ pub fn desc(&self) -> &str {
+ match *self {
+ MergeFunctions::Disabled => "disabled",
+ MergeFunctions::Trampolines => "trampolines",
+ MergeFunctions::Aliases => "aliases",
+ }
+ }
+}
+
+impl FromStr for MergeFunctions {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<MergeFunctions, ()> {
+ match s {
+ "disabled" => Ok(MergeFunctions::Disabled),
+ "trampolines" => Ok(MergeFunctions::Trampolines),
+ "aliases" => Ok(MergeFunctions::Aliases),
+ _ => Err(()),
+ }
+ }
+}
+
+impl ToJson for MergeFunctions {
+ fn to_json(&self) -> Json {
+ match *self {
+ MergeFunctions::Disabled => "disabled".to_json(),
+ MergeFunctions::Trampolines => "trampolines".to_json(),
+ MergeFunctions::Aliases => "aliases".to_json(),
+ }
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum RelocModel {
+ Static,
+ Pic,
+ Pie,
+ DynamicNoPic,
+ Ropi,
+ Rwpi,
+ RopiRwpi,
+}
+
+impl FromStr for RelocModel {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<RelocModel, ()> {
+ Ok(match s {
+ "static" => RelocModel::Static,
+ "pic" => RelocModel::Pic,
+ "pie" => RelocModel::Pie,
+ "dynamic-no-pic" => RelocModel::DynamicNoPic,
+ "ropi" => RelocModel::Ropi,
+ "rwpi" => RelocModel::Rwpi,
+ "ropi-rwpi" => RelocModel::RopiRwpi,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl ToJson for RelocModel {
+ fn to_json(&self) -> Json {
+ match *self {
+ RelocModel::Static => "static",
+ RelocModel::Pic => "pic",
+ RelocModel::Pie => "pie",
+ RelocModel::DynamicNoPic => "dynamic-no-pic",
+ RelocModel::Ropi => "ropi",
+ RelocModel::Rwpi => "rwpi",
+ RelocModel::RopiRwpi => "ropi-rwpi",
+ }
+ .to_json()
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum CodeModel {
+ Tiny,
+ Small,
+ Kernel,
+ Medium,
+ Large,
+}
+
+impl FromStr for CodeModel {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<CodeModel, ()> {
+ Ok(match s {
+ "tiny" => CodeModel::Tiny,
+ "small" => CodeModel::Small,
+ "kernel" => CodeModel::Kernel,
+ "medium" => CodeModel::Medium,
+ "large" => CodeModel::Large,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl ToJson for CodeModel {
+ fn to_json(&self) -> Json {
+ match *self {
+ CodeModel::Tiny => "tiny",
+ CodeModel::Small => "small",
+ CodeModel::Kernel => "kernel",
+ CodeModel::Medium => "medium",
+ CodeModel::Large => "large",
+ }
+ .to_json()
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum TlsModel {
+ GeneralDynamic,
+ LocalDynamic,
+ InitialExec,
+ LocalExec,
+}
+
+impl FromStr for TlsModel {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<TlsModel, ()> {
+ Ok(match s {
+ // Note the difference "general" vs "global" difference. The model name is "general",
+ // but the user-facing option name is "global" for consistency with other compilers.
+ "global-dynamic" => TlsModel::GeneralDynamic,
+ "local-dynamic" => TlsModel::LocalDynamic,
+ "initial-exec" => TlsModel::InitialExec,
+ "local-exec" => TlsModel::LocalExec,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl ToJson for TlsModel {
+ fn to_json(&self) -> Json {
+ match *self {
+ TlsModel::GeneralDynamic => "global-dynamic",
+ TlsModel::LocalDynamic => "local-dynamic",
+ TlsModel::InitialExec => "initial-exec",
+ TlsModel::LocalExec => "local-exec",
+ }
+ .to_json()
+ }
+}
+
+/// Everything is flattened to a single enum to make the json encoding/decoding less annoying.
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
+pub enum LinkOutputKind {
+ /// Dynamically linked non position-independent executable.
+ DynamicNoPicExe,
+ /// Dynamically linked position-independent executable.
+ DynamicPicExe,
+ /// Statically linked non position-independent executable.
+ StaticNoPicExe,
+ /// Statically linked position-independent executable.
+ StaticPicExe,
+ /// Regular dynamic library ("dynamically linked").
+ DynamicDylib,
+ /// Dynamic library with bundled libc ("statically linked").
+ StaticDylib,
+ /// WASI module with a lifetime past the _initialize entry point
+ WasiReactorExe,
+}
+
+impl LinkOutputKind {
+ fn as_str(&self) -> &'static str {
+ match self {
+ LinkOutputKind::DynamicNoPicExe => "dynamic-nopic-exe",
+ LinkOutputKind::DynamicPicExe => "dynamic-pic-exe",
+ LinkOutputKind::StaticNoPicExe => "static-nopic-exe",
+ LinkOutputKind::StaticPicExe => "static-pic-exe",
+ LinkOutputKind::DynamicDylib => "dynamic-dylib",
+ LinkOutputKind::StaticDylib => "static-dylib",
+ LinkOutputKind::WasiReactorExe => "wasi-reactor-exe",
+ }
+ }
+
+ pub(super) fn from_str(s: &str) -> Option<LinkOutputKind> {
+ Some(match s {
+ "dynamic-nopic-exe" => LinkOutputKind::DynamicNoPicExe,
+ "dynamic-pic-exe" => LinkOutputKind::DynamicPicExe,
+ "static-nopic-exe" => LinkOutputKind::StaticNoPicExe,
+ "static-pic-exe" => LinkOutputKind::StaticPicExe,
+ "dynamic-dylib" => LinkOutputKind::DynamicDylib,
+ "static-dylib" => LinkOutputKind::StaticDylib,
+ "wasi-reactor-exe" => LinkOutputKind::WasiReactorExe,
+ _ => return None,
+ })
+ }
+}
+
+impl fmt::Display for LinkOutputKind {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str(self.as_str())
+ }
+}
+
+pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
+
+#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
+pub enum SplitDebuginfo {
+ /// Split debug-information is disabled, meaning that on supported platforms
+ /// you can find all debug information in the executable itself. This is
+ /// only supported for ELF effectively.
+ ///
+ /// * Windows - not supported
+ /// * macOS - don't run `dsymutil`
+ /// * ELF - `.dwarf_*` sections
+ Off,
+
+ /// Split debug-information can be found in a "packed" location separate
+ /// from the final artifact. This is supported on all platforms.
+ ///
+ /// * Windows - `*.pdb`
+ /// * macOS - `*.dSYM` (run `dsymutil`)
+ /// * ELF - `*.dwp` (run `rust-llvm-dwp`)
+ Packed,
+
+ /// Split debug-information can be found in individual object files on the
+ /// filesystem. The main executable may point to the object files.
+ ///
+ /// * Windows - not supported
+ /// * macOS - supported, scattered object files
+ /// * ELF - supported, scattered `*.dwo` or `*.o` files (see `SplitDwarfKind`)
+ Unpacked,
+}
+
+impl SplitDebuginfo {
+ fn as_str(&self) -> &'static str {
+ match self {
+ SplitDebuginfo::Off => "off",
+ SplitDebuginfo::Packed => "packed",
+ SplitDebuginfo::Unpacked => "unpacked",
+ }
+ }
+}
+
+impl FromStr for SplitDebuginfo {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<SplitDebuginfo, ()> {
+ Ok(match s {
+ "off" => SplitDebuginfo::Off,
+ "unpacked" => SplitDebuginfo::Unpacked,
+ "packed" => SplitDebuginfo::Packed,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl ToJson for SplitDebuginfo {
+ fn to_json(&self) -> Json {
+ self.as_str().to_json()
+ }
+}
+
+impl fmt::Display for SplitDebuginfo {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str(self.as_str())
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum StackProbeType {
+ /// Don't emit any stack probes.
+ None,
+ /// It is harmless to use this option even on targets that do not have backend support for
+ /// stack probes as the failure mode is the same as if no stack-probe option was specified in
+ /// the first place.
+ Inline,
+ /// Call `__rust_probestack` whenever stack needs to be probed.
+ Call,
+ /// Use inline option for LLVM versions later than specified in `min_llvm_version_for_inline`
+ /// and call `__rust_probestack` otherwise.
+ InlineOrCall { min_llvm_version_for_inline: (u32, u32, u32) },
+}
+
+impl StackProbeType {
+ fn from_json(json: &Json) -> Result<Self, String> {
+ let object = json.as_object().ok_or_else(|| "expected a JSON object")?;
+ let kind = object
+ .get("kind")
+ .and_then(|o| o.as_str())
+ .ok_or_else(|| "expected `kind` to be a string")?;
+ match kind {
+ "none" => Ok(StackProbeType::None),
+ "inline" => Ok(StackProbeType::Inline),
+ "call" => Ok(StackProbeType::Call),
+ "inline-or-call" => {
+ let min_version = object
+ .get("min-llvm-version-for-inline")
+ .and_then(|o| o.as_array())
+ .ok_or_else(|| "expected `min-llvm-version-for-inline` to be an array")?;
+ let mut iter = min_version.into_iter().map(|v| {
+ let int = v.as_u64().ok_or_else(
+ || "expected `min-llvm-version-for-inline` values to be integers",
+ )?;
+ u32::try_from(int)
+ .map_err(|_| "`min-llvm-version-for-inline` values don't convert to u32")
+ });
+ let min_llvm_version_for_inline = (
+ iter.next().unwrap_or(Ok(11))?,
+ iter.next().unwrap_or(Ok(0))?,
+ iter.next().unwrap_or(Ok(0))?,
+ );
+ Ok(StackProbeType::InlineOrCall { min_llvm_version_for_inline })
+ }
+ _ => Err(String::from(
+ "`kind` expected to be one of `none`, `inline`, `call` or `inline-or-call`",
+ )),
+ }
+ }
+}
+
+impl ToJson for StackProbeType {
+ fn to_json(&self) -> Json {
+ Json::Object(match self {
+ StackProbeType::None => {
+ [(String::from("kind"), "none".to_json())].into_iter().collect()
+ }
+ StackProbeType::Inline => {
+ [(String::from("kind"), "inline".to_json())].into_iter().collect()
+ }
+ StackProbeType::Call => {
+ [(String::from("kind"), "call".to_json())].into_iter().collect()
+ }
+ StackProbeType::InlineOrCall { min_llvm_version_for_inline: (maj, min, patch) } => [
+ (String::from("kind"), "inline-or-call".to_json()),
+ (
+ String::from("min-llvm-version-for-inline"),
+ Json::Array(vec![maj.to_json(), min.to_json(), patch.to_json()]),
+ ),
+ ]
+ .into_iter()
+ .collect(),
+ })
+ }
+}
+
+bitflags::bitflags! {
+ #[derive(Default, Encodable, Decodable)]
+ pub struct SanitizerSet: u8 {
+ const ADDRESS = 1 << 0;
+ const LEAK = 1 << 1;
+ const MEMORY = 1 << 2;
+ const THREAD = 1 << 3;
+ const HWADDRESS = 1 << 4;
+ const CFI = 1 << 5;
+ const MEMTAG = 1 << 6;
+ const SHADOWCALLSTACK = 1 << 7;
+ }
+}
+
+impl SanitizerSet {
+ /// Return sanitizer's name
+ ///
+ /// Returns none if the flags is a set of sanitizers numbering not exactly one.
+ pub fn as_str(self) -> Option<&'static str> {
+ Some(match self {
+ SanitizerSet::ADDRESS => "address",
+ SanitizerSet::CFI => "cfi",
+ SanitizerSet::LEAK => "leak",
+ SanitizerSet::MEMORY => "memory",
+ SanitizerSet::MEMTAG => "memtag",
+ SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
+ SanitizerSet::THREAD => "thread",
+ SanitizerSet::HWADDRESS => "hwaddress",
+ _ => return None,
+ })
+ }
+}
+
+/// Formats a sanitizer set as a comma separated list of sanitizers' names.
+impl fmt::Display for SanitizerSet {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut first = true;
+ for s in *self {
+ let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {:?}", s));
+ if !first {
+ f.write_str(", ")?;
+ }
+ f.write_str(name)?;
+ first = false;
+ }
+ Ok(())
+ }
+}
+
+impl IntoIterator for SanitizerSet {
+ type Item = SanitizerSet;
+ type IntoIter = std::vec::IntoIter<SanitizerSet>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ [
+ SanitizerSet::ADDRESS,
+ SanitizerSet::CFI,
+ SanitizerSet::LEAK,
+ SanitizerSet::MEMORY,
+ SanitizerSet::MEMTAG,
+ SanitizerSet::SHADOWCALLSTACK,
+ SanitizerSet::THREAD,
+ SanitizerSet::HWADDRESS,
+ ]
+ .iter()
+ .copied()
+ .filter(|&s| self.contains(s))
+ .collect::<Vec<_>>()
+ .into_iter()
+ }
+}
+
+impl<CTX> HashStable<CTX> for SanitizerSet {
+ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+ self.bits().hash_stable(ctx, hasher);
+ }
+}
+
+impl ToJson for SanitizerSet {
+ fn to_json(&self) -> Json {
+ self.into_iter()
+ .map(|v| Some(v.as_str()?.to_json()))
+ .collect::<Option<Vec<_>>>()
+ .unwrap_or_default()
+ .to_json()
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum FramePointer {
+ /// Forces the machine code generator to always preserve the frame pointers.
+ Always,
+ /// Forces the machine code generator to preserve the frame pointers except for the leaf
+ /// functions (i.e. those that don't call other functions).
+ NonLeaf,
+ /// Allows the machine code generator to omit the frame pointers.
+ ///
+ /// This option does not guarantee that the frame pointers will be omitted.
+ MayOmit,
+}
+
+impl FromStr for FramePointer {
+ type Err = ();
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Ok(match s {
+ "always" => Self::Always,
+ "non-leaf" => Self::NonLeaf,
+ "may-omit" => Self::MayOmit,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl ToJson for FramePointer {
+ fn to_json(&self) -> Json {
+ match *self {
+ Self::Always => "always",
+ Self::NonLeaf => "non-leaf",
+ Self::MayOmit => "may-omit",
+ }
+ .to_json()
+ }
+}
+
+/// Controls use of stack canaries.
+#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
+pub enum StackProtector {
+ /// Disable stack canary generation.
+ None,
+
+ /// On LLVM, mark all generated LLVM functions with the `ssp` attribute (see
+ /// llvm/docs/LangRef.rst). This triggers stack canary generation in
+ /// functions which contain an array of a byte-sized type with more than
+ /// eight elements.
+ Basic,
+
+ /// On LLVM, mark all generated LLVM functions with the `sspstrong`
+ /// attribute (see llvm/docs/LangRef.rst). This triggers stack canary
+ /// generation in functions which either contain an array, or which take
+ /// the address of a local variable.
+ Strong,
+
+ /// Generate stack canaries in all functions.
+ All,
+}
+
+impl StackProtector {
+ fn as_str(&self) -> &'static str {
+ match self {
+ StackProtector::None => "none",
+ StackProtector::Basic => "basic",
+ StackProtector::Strong => "strong",
+ StackProtector::All => "all",
+ }
+ }
+}
+
+impl FromStr for StackProtector {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<StackProtector, ()> {
+ Ok(match s {
+ "none" => StackProtector::None,
+ "basic" => StackProtector::Basic,
+ "strong" => StackProtector::Strong,
+ "all" => StackProtector::All,
+ _ => return Err(()),
+ })
+ }
+}
+
+impl fmt::Display for StackProtector {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str(self.as_str())
+ }
+}
+
+macro_rules! supported_targets {
+ ( $(($( $triple:literal, )+ $module:ident ),)+ ) => {
+ $(mod $module;)+
+
+ /// List of supported targets
+ pub const TARGETS: &[&str] = &[$($($triple),+),+];
+
+ fn load_builtin(target: &str) -> Option<Target> {
+ let mut t = match target {
+ $( $($triple)|+ => $module::target(), )+
+ _ => return None,
+ };
+ t.is_builtin = true;
+ debug!("got builtin target: {:?}", t);
+ Some(t)
+ }
+
+ #[cfg(test)]
+ mod tests {
+ mod tests_impl;
+
+ // Cannot put this into a separate file without duplication, make an exception.
+ $(
+ #[test] // `#[test]`
+ fn $module() {
+ tests_impl::test_target(super::$module::target());
+ }
+ )+
+ }
+ };
+}
+
+supported_targets! {
+ ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
+ ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
+ ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
+ ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
+ ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
+ ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
+ ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
+ ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
+ ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
+ ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
+ ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
+ ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
+ ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
+ ("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-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
+ ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
+ ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
+ ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
+ ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
+ ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
+ ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
+ ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
+ ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
+ ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
+ ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
+ ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
+ ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
+ ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
+ ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
+ ("armv5te-unknown-linux-uclibceabi", armv5te_unknown_linux_uclibceabi),
+ ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi),
+ ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
+ ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf),
+ ("thumbv7neon-unknown-linux-musleabihf", thumbv7neon_unknown_linux_musleabihf),
+ ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi),
+ ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
+ ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
+ ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
+ ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
+ ("i686-unknown-linux-musl", i686_unknown_linux_musl),
+ ("i586-unknown-linux-musl", i586_unknown_linux_musl),
+ ("mips-unknown-linux-musl", mips_unknown_linux_musl),
+ ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl),
+ ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
+ ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
+ ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
+
+ ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
+ ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
+
+ ("i686-linux-android", i686_linux_android),
+ ("x86_64-linux-android", x86_64_linux_android),
+ ("arm-linux-androideabi", arm_linux_androideabi),
+ ("armv7-linux-androideabi", armv7_linux_androideabi),
+ ("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),
+ ("i686-unknown-freebsd", i686_unknown_freebsd),
+ ("powerpc-unknown-freebsd", powerpc_unknown_freebsd),
+ ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
+ ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
+ ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd),
+ ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
+
+ ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
+
+ ("aarch64-unknown-openbsd", aarch64_unknown_openbsd),
+ ("i686-unknown-openbsd", i686_unknown_openbsd),
+ ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
+ ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
+ ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
+
+ ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
+ ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
+ ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf),
+ ("i686-unknown-netbsd", i686_unknown_netbsd),
+ ("powerpc-unknown-netbsd", powerpc_unknown_netbsd),
+ ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
+ ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
+
+ ("i686-unknown-haiku", i686_unknown_haiku),
+ ("x86_64-unknown-haiku", x86_64_unknown_haiku),
+
+ ("aarch64-apple-darwin", aarch64_apple_darwin),
+ ("x86_64-apple-darwin", x86_64_apple_darwin),
+ ("i686-apple-darwin", i686_apple_darwin),
+
+ ("aarch64-fuchsia", aarch64_fuchsia),
+ ("x86_64-fuchsia", x86_64_fuchsia),
+
+ ("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328),
+
+ ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
+
+ ("aarch64-unknown-redox", aarch64_unknown_redox),
+ ("x86_64-unknown-redox", x86_64_unknown_redox),
+
+ ("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),
+ ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
+ ("aarch64-apple-tvos", aarch64_apple_tvos),
+ ("x86_64-apple-tvos", x86_64_apple_tvos),
+
+ ("armv7k-apple-watchos", armv7k_apple_watchos),
+ ("arm64_32-apple-watchos", arm64_32_apple_watchos),
+ ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
+ ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
+
+ ("armebv7r-none-eabi", armebv7r_none_eabi),
+ ("armebv7r-none-eabihf", armebv7r_none_eabihf),
+ ("armv7r-none-eabi", armv7r_none_eabi),
+ ("armv7r-none-eabihf", armv7r_none_eabihf),
+
+ ("x86_64-pc-solaris", x86_64_pc_solaris),
+ ("x86_64-sun-solaris", x86_64_sun_solaris),
+ ("sparcv9-sun-solaris", sparcv9_sun_solaris),
+
+ ("x86_64-unknown-illumos", x86_64_unknown_illumos),
+
+ ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
+ ("i686-pc-windows-gnu", i686_pc_windows_gnu),
+ ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
+ ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
+
+ ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
+ ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm),
+
+ ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
+ ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
+ ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
+ ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
+ ("i686-pc-windows-msvc", i686_pc_windows_msvc),
+ ("i686-uwp-windows-msvc", i686_uwp_windows_msvc),
+ ("i586-pc-windows-msvc", i586_pc_windows_msvc),
+ ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc),
+ ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc),
+
+ ("asmjs-unknown-emscripten", asmjs_unknown_emscripten),
+ ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
+ ("wasm32-unknown-unknown", wasm32_unknown_unknown),
+ ("wasm32-wasi", wasm32_wasi),
+ ("wasm64-unknown-unknown", wasm64_unknown_unknown),
+
+ ("thumbv6m-none-eabi", thumbv6m_none_eabi),
+ ("thumbv7m-none-eabi", thumbv7m_none_eabi),
+ ("thumbv7em-none-eabi", thumbv7em_none_eabi),
+ ("thumbv7em-none-eabihf", thumbv7em_none_eabihf),
+ ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi),
+ ("thumbv8m.main-none-eabi", thumbv8m_main_none_eabi),
+ ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),
+
+ ("armv7a-none-eabi", armv7a_none_eabi),
+ ("armv7a-none-eabihf", armv7a_none_eabihf),
+
+ ("msp430-none-elf", msp430_none_elf),
+
+ ("aarch64-unknown-hermit", aarch64_unknown_hermit),
+ ("x86_64-unknown-hermit", x86_64_unknown_hermit),
+
+ ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
+ ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
+ ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
+ ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
+ ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
+ ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf),
+ ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
+ ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
+ ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
+ ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
+ ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
+ ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
+
+ ("aarch64-unknown-none", aarch64_unknown_none),
+ ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
+
+ ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
+
+ ("x86_64-unknown-uefi", x86_64_unknown_uefi),
+ ("i686-unknown-uefi", i686_unknown_uefi),
+ ("aarch64-unknown-uefi", aarch64_unknown_uefi),
+
+ ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
+
+ ("i686-wrs-vxworks", i686_wrs_vxworks),
+ ("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
+ ("armv7-wrs-vxworks-eabihf", armv7_wrs_vxworks_eabihf),
+ ("aarch64-wrs-vxworks", aarch64_wrs_vxworks),
+ ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
+ ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
+ ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
+
+ ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
+ ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
+ ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),
+
+ ("mipsel-sony-psp", mipsel_sony_psp),
+ ("mipsel-unknown-none", mipsel_unknown_none),
+ ("thumbv4t-none-eabi", thumbv4t_none_eabi),
+
+ ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
+ ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
+ ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
+
+ ("bpfeb-unknown-none", bpfeb_unknown_none),
+ ("bpfel-unknown-none", bpfel_unknown_none),
+
+ ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
+
+ ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
+
+ ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
+ ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
+
+ ("x86_64-unknown-none", x86_64_unknown_none),
+
+ ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),
+}
+
+/// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
+macro_rules! cvs {
+ () => {
+ ::std::borrow::Cow::Borrowed(&[])
+ };
+ ($($x:expr),+ $(,)?) => {
+ ::std::borrow::Cow::Borrowed(&[
+ $(
+ ::std::borrow::Cow::Borrowed($x),
+ )*
+ ])
+ };
+}
+
+pub(crate) use cvs;
+
+/// Warnings encountered when parsing the target `json`.
+///
+/// Includes fields that weren't recognized and fields that don't have the expected type.
+#[derive(Debug, PartialEq)]
+pub struct TargetWarnings {
+ unused_fields: Vec<String>,
+ incorrect_type: Vec<String>,
+}
+
+impl TargetWarnings {
+ pub fn empty() -> Self {
+ Self { unused_fields: Vec::new(), incorrect_type: Vec::new() }
+ }
+
+ pub fn warning_messages(&self) -> Vec<String> {
+ let mut warnings = vec![];
+ if !self.unused_fields.is_empty() {
+ warnings.push(format!(
+ "target json file contains unused fields: {}",
+ self.unused_fields.join(", ")
+ ));
+ }
+ if !self.incorrect_type.is_empty() {
+ warnings.push(format!(
+ "target json file contains fields whose value doesn't have the correct json type: {}",
+ self.incorrect_type.join(", ")
+ ));
+ }
+ warnings
+ }
+}
+
+/// Everything `rustc` knows about how to compile for a specific target.
+///
+/// Every field here must be specified, and has no default value.
+#[derive(PartialEq, Clone, Debug)]
+pub struct Target {
+ /// Target triple to pass to LLVM.
+ pub llvm_target: StaticCow<str>,
+ /// Number of bits in a pointer. Influences the `target_pointer_width` `cfg` variable.
+ pub pointer_width: u32,
+ /// Architecture to use for ABI considerations. Valid options include: "x86",
+ /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others.
+ pub arch: StaticCow<str>,
+ /// [Data layout](https://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
+ pub data_layout: StaticCow<str>,
+ /// Optional settings with defaults.
+ pub options: TargetOptions,
+}
+
+pub trait HasTargetSpec {
+ fn target_spec(&self) -> &Target;
+}
+
+impl HasTargetSpec for Target {
+ #[inline]
+ fn target_spec(&self) -> &Target {
+ self
+ }
+}
+
+type StaticCow<T> = Cow<'static, T>;
+
+/// Optional aspects of a target specification.
+///
+/// This has an implementation of `Default`, see each field for what the default is. In general,
+/// these try to take "minimal defaults" that don't assume anything about the runtime they run in.
+///
+/// `TargetOptions` as a separate structure is mostly an implementation detail of `Target`
+/// construction, all its fields logically belong to `Target` and available from `Target`
+/// through `Deref` impls.
+#[derive(PartialEq, Clone, Debug)]
+pub struct TargetOptions {
+ /// Whether the target is built-in or loaded from a custom target specification.
+ pub is_builtin: bool,
+
+ /// Used as the `target_endian` `cfg` variable. Defaults to little endian.
+ pub endian: Endian,
+ /// Width of c_int type. Defaults to "32".
+ pub c_int_width: StaticCow<str>,
+ /// OS name to use for conditional compilation (`target_os`). Defaults to "none".
+ /// "none" implies a bare metal target without `std` library.
+ /// A couple of targets having `std` also use "unknown" as an `os` value,
+ /// but they are exceptions.
+ pub os: StaticCow<str>,
+ /// Environment name to use for conditional compilation (`target_env`). Defaults to "".
+ pub env: StaticCow<str>,
+ /// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance, `"eabi"`
+ /// or `"eabihf"`. Defaults to "".
+ pub abi: StaticCow<str>,
+ /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
+ pub vendor: StaticCow<str>,
+ /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
+ /// on the command line. Defaults to `LinkerFlavor::Gcc`.
+ pub linker_flavor: LinkerFlavor,
+
+ /// Linker to invoke
+ pub linker: Option<StaticCow<str>>,
+
+ /// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker
+ /// without clarifying its flavor in any way.
+ pub lld_flavor: LldFlavor,
+
+ /// Linker arguments that are passed *before* any user-defined libraries.
+ pub pre_link_args: LinkArgs,
+ /// Objects to link before and after all other object code.
+ pub pre_link_objects: CrtObjects,
+ pub post_link_objects: CrtObjects,
+ /// Same as `(pre|post)_link_objects`, but when we fail to pull the objects with help of the
+ /// target's native gcc and fall back to the "self-contained" mode and pull them manually.
+ /// See `crt_objects.rs` for some more detailed documentation.
+ pub pre_link_objects_fallback: CrtObjects,
+ pub post_link_objects_fallback: CrtObjects,
+ /// Which logic to use to determine whether to fall back to the "self-contained" mode or not.
+ pub crt_objects_fallback: Option<CrtObjectsFallback>,
+
+ /// Linker arguments that are unconditionally passed after any
+ /// user-defined but before post-link objects. Standard platform
+ /// libraries that should be always be linked to, usually go here.
+ pub late_link_args: LinkArgs,
+ /// Linker arguments used in addition to `late_link_args` if at least one
+ /// Rust dependency is dynamically linked.
+ pub late_link_args_dynamic: LinkArgs,
+ /// Linker arguments used in addition to `late_link_args` if all Rust
+ /// dependencies are statically linked.
+ pub late_link_args_static: LinkArgs,
+ /// Linker arguments that are unconditionally passed *after* any
+ /// user-defined libraries.
+ pub post_link_args: LinkArgs,
+ /// Optional link script applied to `dylib` and `executable` crate types.
+ /// This is a string containing the script, not a path. Can only be applied
+ /// to linkers where `linker_is_gnu` is true.
+ pub link_script: Option<StaticCow<str>>,
+
+ /// Environment variables to be set for the linker invocation.
+ pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
+ /// Environment variables to be removed for the linker invocation.
+ pub link_env_remove: StaticCow<[StaticCow<str>]>,
+
+ /// Extra arguments to pass to the external assembler (when used)
+ pub asm_args: StaticCow<[StaticCow<str>]>,
+
+ /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults
+ /// to "generic".
+ pub cpu: StaticCow<str>,
+ /// Default target features to pass to LLVM. These features will *always* be
+ /// passed, and cannot be disabled even via `-C`. Corresponds to `llc
+ /// -mattr=$features`.
+ pub features: StaticCow<str>,
+ /// Whether dynamic linking is available on this target. Defaults to false.
+ pub dynamic_linking: bool,
+ /// If dynamic linking is available, whether only cdylibs are supported.
+ pub only_cdylib: bool,
+ /// Whether executables are available on this target. Defaults to true.
+ pub executables: bool,
+ /// Relocation model to use in object file. Corresponds to `llc
+ /// -relocation-model=$relocation_model`. Defaults to `Pic`.
+ pub relocation_model: RelocModel,
+ /// Code model to use. Corresponds to `llc -code-model=$code_model`.
+ /// Defaults to `None` which means "inherited from the base LLVM target".
+ pub code_model: Option<CodeModel>,
+ /// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec"
+ /// and "local-exec". This is similar to the -ftls-model option in GCC/Clang.
+ pub tls_model: TlsModel,
+ /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false.
+ pub disable_redzone: bool,
+ /// Frame pointer mode for this target. Defaults to `MayOmit`.
+ pub frame_pointer: FramePointer,
+ /// Emit each function in its own section. Defaults to true.
+ pub function_sections: bool,
+ /// String to prepend to the name of every dynamic library. Defaults to "lib".
+ pub dll_prefix: StaticCow<str>,
+ /// String to append to the name of every dynamic library. Defaults to ".so".
+ pub dll_suffix: StaticCow<str>,
+ /// String to append to the name of every executable.
+ pub exe_suffix: StaticCow<str>,
+ /// String to prepend to the name of every static library. Defaults to "lib".
+ pub staticlib_prefix: StaticCow<str>,
+ /// String to append to the name of every static library. Defaults to ".a".
+ pub staticlib_suffix: StaticCow<str>,
+ /// Values of the `target_family` cfg set for this target.
+ ///
+ /// Common options are: "unix", "windows". Defaults to no families.
+ ///
+ /// See <https://doc.rust-lang.org/reference/conditional-compilation.html#target_family>.
+ pub families: StaticCow<[StaticCow<str>]>,
+ /// Whether the target toolchain's ABI supports returning small structs as an integer.
+ pub abi_return_struct_as_int: bool,
+ /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS,
+ /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false.
+ pub is_like_osx: bool,
+ /// Whether the target toolchain is like Solaris's.
+ /// Only useful for compiling against Illumos/Solaris,
+ /// as they have a different set of linker flags. Defaults to false.
+ pub is_like_solaris: bool,
+ /// Whether the target is like Windows.
+ /// This is a combination of several more specific properties represented as a single flag:
+ /// - The target uses a Windows ABI,
+ /// - uses PE/COFF as a format for object code,
+ /// - uses Windows-style dllexport/dllimport for shared libraries,
+ /// - uses import libraries and .def files for symbol exports,
+ /// - executables support setting a subsystem.
+ pub is_like_windows: bool,
+ /// Whether the target is like MSVC.
+ /// This is a combination of several more specific properties represented as a single flag:
+ /// - The target has all the properties from `is_like_windows`
+ /// (for in-tree targets "is_like_msvc ⇒ is_like_windows" is ensured by a unit test),
+ /// - has some MSVC-specific Windows ABI properties,
+ /// - uses a link.exe-like linker,
+ /// - uses CodeView/PDB for debuginfo and natvis for its visualization,
+ /// - uses SEH-based unwinding,
+ /// - supports control flow guard mechanism.
+ pub is_like_msvc: bool,
+ /// Whether a target toolchain is like WASM.
+ pub is_like_wasm: bool,
+ /// Default supported version of DWARF on this platform.
+ /// Useful because some platforms (osx, bsd) only want up to DWARF2.
+ pub default_dwarf_version: u32,
+ /// Whether the linker support GNU-like arguments such as -O. Defaults to true.
+ pub linker_is_gnu: bool,
+ /// The MinGW toolchain has a known issue that prevents it from correctly
+ /// handling COFF object files with more than 2<sup>15</sup> sections. Since each weak
+ /// symbol needs its own COMDAT section, weak linkage implies a large
+ /// number sections that easily exceeds the given limit for larger
+ /// codebases. Consequently we want a way to disallow weak linkage on some
+ /// platforms.
+ pub allows_weak_linkage: bool,
+ /// Whether the linker support rpaths or not. Defaults to false.
+ pub has_rpath: bool,
+ /// Whether to disable linking to the default libraries, typically corresponds
+ /// to `-nodefaultlibs`. Defaults to true.
+ pub no_default_libraries: bool,
+ /// Dynamically linked executables can be compiled as position independent
+ /// if the default relocation model of position independent code is not
+ /// changed. This is a requirement to take advantage of ASLR, as otherwise
+ /// the functions in the executable are not randomized and can be used
+ /// during an exploit of a vulnerability in any code.
+ pub position_independent_executables: bool,
+ /// Executables that are both statically linked and position-independent are supported.
+ pub static_position_independent_executables: bool,
+ /// Determines if the target always requires using the PLT for indirect
+ /// library calls or not. This controls the default value of the `-Z plt` flag.
+ pub needs_plt: bool,
+ /// Either partial, full, or off. Full RELRO makes the dynamic linker
+ /// resolve all symbols at startup and marks the GOT read-only before
+ /// starting the program, preventing overwriting the GOT.
+ pub relro_level: RelroLevel,
+ /// Format that archives should be emitted in. This affects whether we use
+ /// LLVM to assemble an archive or fall back to the system linker, and
+ /// currently only "gnu" is used to fall into LLVM. Unknown strings cause
+ /// the system linker to be used.
+ pub archive_format: StaticCow<str>,
+ /// Is asm!() allowed? Defaults to true.
+ pub allow_asm: bool,
+ /// Whether the runtime startup code requires the `main` function be passed
+ /// `argc` and `argv` values.
+ pub main_needs_argc_argv: bool,
+
+ /// 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'.
+ pub obj_is_bitcode: bool,
+ /// Whether the target requires that emitted object code includes bitcode.
+ pub forces_embed_bitcode: bool,
+ /// Content of the LLVM cmdline section associated with embedded bitcode.
+ pub bitcode_llvm_cmdline: StaticCow<str>,
+
+ /// Don't use this field; instead use the `.min_atomic_width()` method.
+ pub min_atomic_width: Option<u64>,
+
+ /// Don't use this field; instead use the `.max_atomic_width()` method.
+ pub max_atomic_width: Option<u64>,
+
+ /// Whether the target supports atomic CAS operations natively
+ pub atomic_cas: bool,
+
+ /// Panic strategy: "unwind" or "abort"
+ pub panic_strategy: PanicStrategy,
+
+ /// Whether or not linking dylibs to a static CRT is allowed.
+ pub crt_static_allows_dylibs: bool,
+ /// Whether or not the CRT is statically linked by default.
+ pub crt_static_default: bool,
+ /// Whether or not crt-static is respected by the compiler (or is a no-op).
+ pub crt_static_respected: bool,
+
+ /// The implementation of stack probes to use.
+ pub stack_probes: StackProbeType,
+
+ /// The minimum alignment for global symbols.
+ pub min_global_align: Option<u64>,
+
+ /// Default number of codegen units to use in debug mode
+ pub default_codegen_units: Option<u64>,
+
+ /// Whether to generate trap instructions in places where optimization would
+ /// otherwise produce control flow that falls through into unrelated memory.
+ pub trap_unreachable: bool,
+
+ /// This target requires everything to be compiled with LTO to emit a final
+ /// executable, aka there is no native linker for this target.
+ pub requires_lto: bool,
+
+ /// This target has no support for threads.
+ pub singlethread: bool,
+
+ /// Whether library functions call lowering/optimization is disabled in LLVM
+ /// for this target unconditionally.
+ pub no_builtins: bool,
+
+ /// The default visibility for symbols in this target should be "hidden"
+ /// rather than "default"
+ pub default_hidden_visibility: bool,
+
+ /// Whether a .debug_gdb_scripts section will be added to the output object file
+ pub emit_debug_gdb_scripts: bool,
+
+ /// Whether or not to unconditionally `uwtable` attributes on functions,
+ /// typically because the platform needs to unwind for things like stack
+ /// unwinders.
+ pub requires_uwtable: bool,
+
+ /// Whether or not to emit `uwtable` attributes on functions if `-C force-unwind-tables`
+ /// is not specified and `uwtable` is not required on this target.
+ pub default_uwtable: bool,
+
+ /// Whether or not SIMD types are passed by reference in the Rust ABI,
+ /// typically required if a target can be compiled with a mixed set of
+ /// target features. This is `true` by default, and `false` for targets like
+ /// wasm32 where the whole program either has simd or not.
+ pub simd_types_indirect: bool,
+
+ /// Pass a list of symbol which should be exported in the dylib to the linker.
+ pub limit_rdylib_exports: bool,
+
+ /// If set, have the linker export exactly these symbols, instead of using
+ /// the usual logic to figure this out from the crate itself.
+ pub override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
+
+ /// Determines how or whether the MergeFunctions LLVM pass should run for
+ /// this target. Either "disabled", "trampolines", or "aliases".
+ /// The MergeFunctions pass is generally useful, but some targets may need
+ /// to opt out. The default is "aliases".
+ ///
+ /// Workaround for: <https://github.com/rust-lang/rust/issues/57356>
+ pub merge_functions: MergeFunctions,
+
+ /// Use platform dependent mcount function
+ pub mcount: StaticCow<str>,
+
+ /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
+ pub llvm_abiname: StaticCow<str>,
+
+ /// Whether or not RelaxElfRelocation flag will be passed to the linker
+ pub relax_elf_relocations: bool,
+
+ /// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
+ pub llvm_args: StaticCow<[StaticCow<str>]>,
+
+ /// Whether to use legacy .ctors initialization hooks rather than .init_array. Defaults
+ /// to false (uses .init_array).
+ pub use_ctors_section: bool,
+
+ /// Whether the linker is instructed to add a `GNU_EH_FRAME` ELF header
+ /// used to locate unwinding information is passed
+ /// (only has effect if the linker is `ld`-like).
+ pub eh_frame_header: bool,
+
+ /// Is true if the target is an ARM architecture using thumb v1 which allows for
+ /// thumb and arm interworking.
+ pub has_thumb_interworking: bool,
+
+ /// How to handle split debug information, if at all. Specifying `None` has
+ /// target-specific meaning.
+ pub split_debuginfo: SplitDebuginfo,
+
+ /// The sanitizers supported by this target
+ ///
+ /// Note that the support here is at a codegen level. If the machine code with sanitizer
+ /// enabled can generated on this target, but the necessary supporting libraries are not
+ /// distributed with the target, the sanitizer should still appear in this list for the target.
+ pub supported_sanitizers: SanitizerSet,
+
+ /// If present it's a default value to use for adjusting the C ABI.
+ pub default_adjusted_cabi: Option<Abi>,
+
+ /// Minimum number of bits in #[repr(C)] enum. Defaults to 32.
+ pub c_enum_min_bits: u64,
+
+ /// Whether or not the DWARF `.debug_aranges` section should be generated.
+ pub generate_arange_section: bool,
+
+ /// 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,
+}
+
+/// Add arguments for the given flavor and also for its "twin" flavors
+/// that have a compatible command line interface.
+fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
+ let mut insert = |flavor| {
+ link_args.entry(flavor).or_default().extend(args.iter().copied().map(Cow::Borrowed))
+ };
+ insert(flavor);
+ match flavor {
+ LinkerFlavor::Ld => insert(LinkerFlavor::Lld(LldFlavor::Ld)),
+ LinkerFlavor::Msvc => insert(LinkerFlavor::Lld(LldFlavor::Link)),
+ LinkerFlavor::Lld(LldFlavor::Wasm) => {}
+ LinkerFlavor::Lld(lld_flavor) => {
+ panic!("add_link_args: use non-LLD flavor for {:?}", lld_flavor)
+ }
+ LinkerFlavor::Gcc
+ | LinkerFlavor::Em
+ | LinkerFlavor::L4Bender
+ | LinkerFlavor::BpfLinker
+ | LinkerFlavor::PtxLinker => {}
+ }
+}
+
+impl TargetOptions {
+ fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
+ let mut link_args = LinkArgs::new();
+ add_link_args(&mut link_args, flavor, args);
+ link_args
+ }
+
+ fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
+ add_link_args(&mut self.pre_link_args, flavor, args);
+ }
+
+ fn add_post_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
+ add_link_args(&mut self.post_link_args, flavor, args);
+ }
+}
+
+impl Default for TargetOptions {
+ /// Creates a set of "sane defaults" for any target. This is still
+ /// incomplete, and if used for compilation, will certainly not work.
+ fn default() -> TargetOptions {
+ TargetOptions {
+ is_builtin: false,
+ endian: Endian::Little,
+ c_int_width: "32".into(),
+ os: "none".into(),
+ env: "".into(),
+ abi: "".into(),
+ vendor: "unknown".into(),
+ linker_flavor: LinkerFlavor::Gcc,
+ linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
+ lld_flavor: LldFlavor::Ld,
+ pre_link_args: LinkArgs::new(),
+ post_link_args: LinkArgs::new(),
+ link_script: None,
+ asm_args: cvs![],
+ cpu: "generic".into(),
+ features: "".into(),
+ dynamic_linking: false,
+ only_cdylib: false,
+ executables: true,
+ relocation_model: RelocModel::Pic,
+ code_model: None,
+ tls_model: TlsModel::GeneralDynamic,
+ disable_redzone: false,
+ frame_pointer: FramePointer::MayOmit,
+ function_sections: true,
+ dll_prefix: "lib".into(),
+ dll_suffix: ".so".into(),
+ exe_suffix: "".into(),
+ staticlib_prefix: "lib".into(),
+ staticlib_suffix: ".a".into(),
+ families: cvs![],
+ abi_return_struct_as_int: false,
+ is_like_osx: false,
+ is_like_solaris: false,
+ is_like_windows: false,
+ is_like_msvc: false,
+ is_like_wasm: false,
+ default_dwarf_version: 4,
+ linker_is_gnu: true,
+ allows_weak_linkage: true,
+ has_rpath: false,
+ no_default_libraries: true,
+ position_independent_executables: false,
+ static_position_independent_executables: false,
+ needs_plt: false,
+ relro_level: RelroLevel::None,
+ pre_link_objects: Default::default(),
+ post_link_objects: Default::default(),
+ pre_link_objects_fallback: Default::default(),
+ post_link_objects_fallback: Default::default(),
+ crt_objects_fallback: None,
+ late_link_args: LinkArgs::new(),
+ late_link_args_dynamic: LinkArgs::new(),
+ late_link_args_static: LinkArgs::new(),
+ link_env: cvs![],
+ link_env_remove: cvs![],
+ archive_format: "gnu".into(),
+ main_needs_argc_argv: true,
+ allow_asm: true,
+ has_thread_local: false,
+ obj_is_bitcode: false,
+ forces_embed_bitcode: false,
+ bitcode_llvm_cmdline: "".into(),
+ min_atomic_width: None,
+ max_atomic_width: None,
+ atomic_cas: true,
+ panic_strategy: PanicStrategy::Unwind,
+ crt_static_allows_dylibs: false,
+ crt_static_default: false,
+ crt_static_respected: false,
+ stack_probes: StackProbeType::None,
+ min_global_align: None,
+ default_codegen_units: None,
+ trap_unreachable: true,
+ requires_lto: false,
+ singlethread: false,
+ no_builtins: false,
+ default_hidden_visibility: false,
+ emit_debug_gdb_scripts: true,
+ requires_uwtable: false,
+ default_uwtable: false,
+ simd_types_indirect: true,
+ limit_rdylib_exports: true,
+ override_export_symbols: None,
+ merge_functions: MergeFunctions::Aliases,
+ mcount: "mcount".into(),
+ llvm_abiname: "".into(),
+ relax_elf_relocations: false,
+ llvm_args: cvs![],
+ use_ctors_section: false,
+ eh_frame_header: true,
+ has_thumb_interworking: false,
+ split_debuginfo: SplitDebuginfo::Off,
+ supported_sanitizers: SanitizerSet::empty(),
+ default_adjusted_cabi: None,
+ c_enum_min_bits: 32,
+ generate_arange_section: true,
+ supports_stack_protector: true,
+ }
+ }
+}
+
+/// `TargetOptions` being a separate type is basically an implementation detail of `Target` that is
+/// used for providing defaults. Perhaps there's a way to merge `TargetOptions` into `Target` so
+/// this `Deref` implementation is no longer necessary.
+impl Deref for Target {
+ type Target = TargetOptions;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ &self.options
+ }
+}
+impl DerefMut for Target {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.options
+ }
+}
+
+impl Target {
+ /// Given a function ABI, turn it into the correct ABI for this target.
+ pub fn adjust_abi(&self, abi: Abi) -> Abi {
+ match abi {
+ Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi),
+ Abi::System { unwind } if self.is_like_windows && self.arch == "x86" => {
+ Abi::Stdcall { unwind }
+ }
+ Abi::System { unwind } => Abi::C { unwind },
+ Abi::EfiApi if self.arch == "x86_64" => Abi::Win64 { unwind: false },
+ Abi::EfiApi => Abi::C { unwind: false },
+
+ // See commentary in `is_abi_supported`.
+ Abi::Stdcall { .. } | Abi::Thiscall { .. } if self.arch == "x86" => abi,
+ Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => Abi::C { unwind },
+ Abi::Fastcall { .. } if self.arch == "x86" => abi,
+ Abi::Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
+ Abi::Fastcall { unwind } | Abi::Vectorcall { unwind } => Abi::C { unwind },
+
+ abi => abi,
+ }
+ }
+
+ /// Returns a None if the UNSUPPORTED_CALLING_CONVENTIONS lint should be emitted
+ pub fn is_abi_supported(&self, abi: Abi) -> Option<bool> {
+ use Abi::*;
+ Some(match abi {
+ Rust
+ | C { .. }
+ | System { .. }
+ | RustIntrinsic
+ | RustCall
+ | PlatformIntrinsic
+ | Unadjusted
+ | Cdecl { .. }
+ | EfiApi
+ | RustCold => true,
+ X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
+ Aapcs { .. } => "arm" == self.arch,
+ CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
+ Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
+ PtxKernel => self.arch == "nvptx64",
+ Msp430Interrupt => self.arch == "msp430",
+ AmdGpuKernel => self.arch == "amdgcn",
+ AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
+ Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]),
+ Thiscall { .. } => self.arch == "x86",
+ // On windows these fall-back to platform native calling convention (C) when the
+ // architecture is not supported.
+ //
+ // This is I believe a historical accident that has occurred as part of Microsoft
+ // striving to allow most of the code to "just" compile when support for 64-bit x86
+ // was added and then later again, when support for ARM architectures was added.
+ //
+ // This is well documented across MSDN. Support for this in Rust has been added in
+ // #54576. This makes much more sense in context of Microsoft's C++ than it does in
+ // Rust, but there isn't much leeway remaining here to change it back at the time this
+ // comment has been written.
+ //
+ // Following are the relevant excerpts from the MSDN documentation.
+ //
+ // > The __vectorcall calling convention is only supported in native code on x86 and
+ // x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above.
+ // > ...
+ // > On ARM machines, __vectorcall is accepted and ignored by the compiler.
+ //
+ // -- https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-160
+ //
+ // > On ARM and x64 processors, __stdcall is accepted and ignored by the compiler;
+ //
+ // -- https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160
+ //
+ // > In most cases, keywords or compiler switches that specify an unsupported
+ // > convention on a particular platform are ignored, and the platform default
+ // > convention is used.
+ //
+ // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
+ Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } if self.is_like_windows => true,
+ // Outside of Windows we want to only support these calling conventions for the
+ // architectures for which these calling conventions are actually well defined.
+ Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true,
+ Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
+ // Return a `None` for other cases so that we know to emit a future compat lint.
+ Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } => return None,
+ })
+ }
+
+ /// Minimum integer size in bits that this target can perform atomic
+ /// operations on.
+ pub fn min_atomic_width(&self) -> u64 {
+ self.min_atomic_width.unwrap_or(8)
+ }
+
+ /// Maximum integer size in bits that this target can perform atomic
+ /// operations on.
+ pub fn max_atomic_width(&self) -> u64 {
+ self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
+ }
+
+ /// Loads a target descriptor from a JSON object.
+ pub fn from_json(obj: Json) -> Result<(Target, TargetWarnings), String> {
+ // While ugly, this code must remain this way to retain
+ // compatibility with existing JSON fields and the internal
+ // expected naming of the Target and TargetOptions structs.
+ // To ensure compatibility is retained, the built-in targets
+ // are round-tripped through this code to catch cases where
+ // the JSON parser is not updated to match the structs.
+
+ let mut obj = match obj {
+ Value::Object(obj) => obj,
+ _ => return Err("Expected JSON object for target")?,
+ };
+
+ let mut get_req_field = |name: &str| {
+ obj.remove(name)
+ .and_then(|j| j.as_str().map(str::to_string))
+ .ok_or_else(|| format!("Field {} in target specification is required", name))
+ };
+
+ let mut base = Target {
+ llvm_target: get_req_field("llvm-target")?.into(),
+ pointer_width: get_req_field("target-pointer-width")?
+ .parse::<u32>()
+ .map_err(|_| "target-pointer-width must be an integer".to_string())?,
+ data_layout: get_req_field("data-layout")?.into(),
+ arch: get_req_field("arch")?.into(),
+ options: Default::default(),
+ };
+
+ let mut incorrect_type = vec![];
+
+ macro_rules! key {
+ ($key_name:ident) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(s) = obj.remove(&name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) {
+ base.$key_name = s;
+ }
+ } );
+ ($key_name:ident = $json_name:expr) => ( {
+ let name = $json_name;
+ if let Some(s) = obj.remove(name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) {
+ base.$key_name = s;
+ }
+ } );
+ ($key_name:ident, bool) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) {
+ base.$key_name = s;
+ }
+ } );
+ ($key_name:ident, u64) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(s) = obj.remove(&name).and_then(|j| Json::as_u64(&j)) {
+ base.$key_name = s;
+ }
+ } );
+ ($key_name:ident, u32) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) {
+ if s < 1 || s > 5 {
+ return Err("Not a valid DWARF version number".into());
+ }
+ base.$key_name = s as u32;
+ }
+ } );
+ ($key_name:ident, Option<u64>) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) {
+ base.$key_name = Some(s);
+ }
+ } );
+ ($key_name:ident, MergeFunctions) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ match s.parse::<MergeFunctions>() {
+ Ok(mergefunc) => base.$key_name = mergefunc,
+ _ => return Some(Err(format!("'{}' is not a valid value for \
+ merge-functions. Use 'disabled', \
+ 'trampolines', or 'aliases'.",
+ s))),
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, RelocModel) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ match s.parse::<RelocModel>() {
+ Ok(relocation_model) => base.$key_name = relocation_model,
+ _ => return Some(Err(format!("'{}' is not a valid relocation model. \
+ Run `rustc --print relocation-models` to \
+ see the list of supported values.", s))),
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, CodeModel) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ match s.parse::<CodeModel>() {
+ Ok(code_model) => base.$key_name = Some(code_model),
+ _ => return Some(Err(format!("'{}' is not a valid code model. \
+ Run `rustc --print code-models` to \
+ see the list of supported values.", s))),
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, TlsModel) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ match s.parse::<TlsModel>() {
+ Ok(tls_model) => base.$key_name = tls_model,
+ _ => return Some(Err(format!("'{}' is not a valid TLS model. \
+ Run `rustc --print tls-models` to \
+ see the list of supported values.", s))),
+ }
+ 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| {
+ match s {
+ "unwind" => base.$key_name = PanicStrategy::Unwind,
+ "abort" => base.$key_name = PanicStrategy::Abort,
+ _ => return Some(Err(format!("'{}' is not a valid value for \
+ panic-strategy. Use 'unwind' or 'abort'.",
+ s))),
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, RelroLevel) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ match s.parse::<RelroLevel>() {
+ Ok(level) => base.$key_name = level,
+ _ => return Some(Err(format!("'{}' is not a valid value for \
+ relro-level. Use 'full', 'partial, or 'off'.",
+ s))),
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, SplitDebuginfo) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ match s.parse::<SplitDebuginfo>() {
+ Ok(level) => base.$key_name = level,
+ _ => return Some(Err(format!("'{}' is not a valid value for \
+ split-debuginfo. Use 'off' or 'dsymutil'.",
+ s))),
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, list) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(j) = obj.remove(&name) {
+ if let Some(v) = j.as_array() {
+ base.$key_name = v.iter()
+ .map(|a| a.as_str().unwrap().to_string().into())
+ .collect();
+ } else {
+ incorrect_type.push(name)
+ }
+ }
+ } );
+ ($key_name:ident, opt_list) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(j) = obj.remove(&name) {
+ if let Some(v) = j.as_array() {
+ base.$key_name = Some(v.iter()
+ .map(|a| a.as_str().unwrap().to_string().into())
+ .collect());
+ } else {
+ incorrect_type.push(name)
+ }
+ }
+ } );
+ ($key_name:ident, optional) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(o) = obj.remove(&name) {
+ base.$key_name = o
+ .as_str()
+ .map(|s| s.to_string().into());
+ }
+ } );
+ ($key_name:ident, LldFlavor) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ if let Some(flavor) = LldFlavor::from_str(&s) {
+ base.$key_name = flavor;
+ } else {
+ return Some(Err(format!(
+ "'{}' is not a valid value for lld-flavor. \
+ Use 'darwin', 'gnu', 'link' or 'wasm.",
+ s)))
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, LinkerFlavor) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ match LinkerFlavor::from_str(s) {
+ Some(linker_flavor) => base.$key_name = linker_flavor,
+ _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \
+ Use {}", s, LinkerFlavor::one_of()))),
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, StackProbeType) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| match StackProbeType::from_json(&o) {
+ Ok(v) => {
+ base.$key_name = v;
+ Some(Ok(()))
+ },
+ Err(s) => Some(Err(
+ format!("`{:?}` is not a valid value for `{}`: {}", o, name, s)
+ )),
+ }).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, SanitizerSet) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(o) = obj.remove(&name) {
+ if let Some(a) = o.as_array() {
+ for s in a {
+ base.$key_name |= match s.as_str() {
+ Some("address") => SanitizerSet::ADDRESS,
+ Some("cfi") => SanitizerSet::CFI,
+ Some("leak") => SanitizerSet::LEAK,
+ Some("memory") => SanitizerSet::MEMORY,
+ Some("memtag") => SanitizerSet::MEMTAG,
+ Some("shadow-call-stack") => SanitizerSet::SHADOWCALLSTACK,
+ Some("thread") => SanitizerSet::THREAD,
+ Some("hwaddress") => SanitizerSet::HWADDRESS,
+ Some(s) => return Err(format!("unknown sanitizer {}", s)),
+ _ => return Err(format!("not a string: {:?}", s)),
+ };
+ }
+ } else {
+ incorrect_type.push(name)
+ }
+ }
+ Ok::<(), String>(())
+ } );
+
+ ($key_name:ident, crt_objects_fallback) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ match s.parse::<CrtObjectsFallback>() {
+ Ok(fallback) => base.$key_name = Some(fallback),
+ _ => return Some(Err(format!("'{}' is not a valid CRT objects fallback. \
+ Use 'musl', 'mingw' or 'wasm'", s))),
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, link_objects) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(val) = obj.remove(&name) {
+ let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
+ JSON object with fields per CRT object kind.", name))?;
+ let mut args = CrtObjects::new();
+ for (k, v) in obj {
+ let kind = LinkOutputKind::from_str(&k).ok_or_else(|| {
+ format!("{}: '{}' is not a valid value for CRT object kind. \
+ Use '(dynamic,static)-(nopic,pic)-exe' or \
+ '(dynamic,static)-dylib' or 'wasi-reactor-exe'", name, k)
+ })?;
+
+ let v = v.as_array().ok_or_else(||
+ format!("{}.{}: expected a JSON array", name, k)
+ )?.iter().enumerate()
+ .map(|(i,s)| {
+ let s = s.as_str().ok_or_else(||
+ format!("{}.{}[{}]: expected a JSON string", name, k, i))?;
+ Ok(s.to_string().into())
+ })
+ .collect::<Result<Vec<_>, String>>()?;
+
+ args.insert(kind, v);
+ }
+ base.$key_name = args;
+ }
+ } );
+ ($key_name:ident, link_args) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(val) = obj.remove(&name) {
+ let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
+ JSON object with fields per linker-flavor.", name))?;
+ let mut args = LinkArgs::new();
+ for (k, v) in obj {
+ let flavor = LinkerFlavor::from_str(&k).ok_or_else(|| {
+ format!("{}: '{}' is not a valid value for linker-flavor. \
+ Use 'em', 'gcc', 'ld' or 'msvc'", name, k)
+ })?;
+
+ let v = v.as_array().ok_or_else(||
+ format!("{}.{}: expected a JSON array", name, k)
+ )?.iter().enumerate()
+ .map(|(i,s)| {
+ let s = s.as_str().ok_or_else(||
+ format!("{}.{}[{}]: expected a JSON string", name, k, i))?;
+ Ok(s.to_string().into())
+ })
+ .collect::<Result<Vec<_>, String>>()?;
+
+ args.insert(flavor, v);
+ }
+ base.$key_name = args;
+ }
+ } );
+ ($key_name:ident, env) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(o) = obj.remove(&name) {
+ if let Some(a) = o.as_array() {
+ for o in a {
+ if let Some(s) = o.as_str() {
+ let p = s.split('=').collect::<Vec<_>>();
+ if p.len() == 2 {
+ let k = p[0].to_string();
+ let v = p[1].to_string();
+ base.$key_name.to_mut().push((k.into(), v.into()));
+ }
+ }
+ }
+ } else {
+ incorrect_type.push(name)
+ }
+ }
+ } );
+ ($key_name:ident, Option<Abi>) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ match lookup_abi(s) {
+ Some(abi) => base.$key_name = Some(abi),
+ _ => return Some(Err(format!("'{}' is not a valid value for abi", s))),
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, TargetFamilies) => ( {
+ if let Some(value) = obj.remove("target-family") {
+ if let Some(v) = value.as_array() {
+ base.$key_name = v.iter()
+ .map(|a| a.as_str().unwrap().to_string().into())
+ .collect();
+ } else if let Some(v) = value.as_str() {
+ base.$key_name = vec![v.to_string().into()].into();
+ }
+ }
+ } );
+ }
+
+ if let Some(j) = obj.remove("target-endian") {
+ if let Some(s) = j.as_str() {
+ base.endian = s.parse()?;
+ } else {
+ incorrect_type.push("target-endian".into())
+ }
+ }
+
+ if let Some(fp) = obj.remove("frame-pointer") {
+ if let Some(s) = fp.as_str() {
+ base.frame_pointer = s
+ .parse()
+ .map_err(|()| format!("'{}' is not a valid value for frame-pointer", s))?;
+ } else {
+ incorrect_type.push("frame-pointer".into())
+ }
+ }
+
+ key!(is_builtin, bool);
+ key!(c_int_width = "target-c-int-width");
+ key!(os);
+ key!(env);
+ key!(abi);
+ key!(vendor);
+ key!(linker_flavor, LinkerFlavor)?;
+ key!(linker, optional);
+ key!(lld_flavor, LldFlavor)?;
+ key!(pre_link_objects, link_objects);
+ key!(post_link_objects, link_objects);
+ key!(pre_link_objects_fallback, link_objects);
+ key!(post_link_objects_fallback, link_objects);
+ key!(crt_objects_fallback, crt_objects_fallback)?;
+ key!(pre_link_args, link_args);
+ key!(late_link_args, link_args);
+ key!(late_link_args_dynamic, link_args);
+ key!(late_link_args_static, link_args);
+ key!(post_link_args, link_args);
+ key!(link_script, optional);
+ key!(link_env, env);
+ key!(link_env_remove, list);
+ key!(asm_args, list);
+ key!(cpu);
+ key!(features);
+ key!(dynamic_linking, bool);
+ key!(only_cdylib, bool);
+ key!(executables, bool);
+ key!(relocation_model, RelocModel)?;
+ key!(code_model, CodeModel)?;
+ key!(tls_model, TlsModel)?;
+ key!(disable_redzone, bool);
+ key!(function_sections, bool);
+ key!(dll_prefix);
+ key!(dll_suffix);
+ key!(exe_suffix);
+ key!(staticlib_prefix);
+ key!(staticlib_suffix);
+ key!(families, TargetFamilies);
+ key!(abi_return_struct_as_int, bool);
+ key!(is_like_osx, bool);
+ key!(is_like_solaris, bool);
+ key!(is_like_windows, bool);
+ key!(is_like_msvc, bool);
+ key!(is_like_wasm, bool);
+ key!(default_dwarf_version, u32);
+ key!(linker_is_gnu, bool);
+ key!(allows_weak_linkage, bool);
+ key!(has_rpath, bool);
+ key!(no_default_libraries, bool);
+ key!(position_independent_executables, bool);
+ key!(static_position_independent_executables, bool);
+ key!(needs_plt, bool);
+ key!(relro_level, RelroLevel)?;
+ key!(archive_format);
+ key!(allow_asm, bool);
+ key!(main_needs_argc_argv, bool);
+ key!(has_thread_local, bool);
+ key!(obj_is_bitcode, bool);
+ key!(forces_embed_bitcode, bool);
+ key!(bitcode_llvm_cmdline);
+ key!(max_atomic_width, Option<u64>);
+ key!(min_atomic_width, Option<u64>);
+ key!(atomic_cas, bool);
+ key!(panic_strategy, PanicStrategy)?;
+ key!(crt_static_allows_dylibs, bool);
+ key!(crt_static_default, bool);
+ key!(crt_static_respected, bool);
+ key!(stack_probes, StackProbeType)?;
+ key!(min_global_align, Option<u64>);
+ key!(default_codegen_units, Option<u64>);
+ key!(trap_unreachable, bool);
+ key!(requires_lto, bool);
+ key!(singlethread, bool);
+ key!(no_builtins, bool);
+ key!(default_hidden_visibility, bool);
+ key!(emit_debug_gdb_scripts, bool);
+ key!(requires_uwtable, bool);
+ key!(default_uwtable, bool);
+ key!(simd_types_indirect, bool);
+ key!(limit_rdylib_exports, bool);
+ key!(override_export_symbols, opt_list);
+ key!(merge_functions, MergeFunctions)?;
+ key!(mcount = "target-mcount");
+ key!(llvm_abiname);
+ key!(relax_elf_relocations, bool);
+ key!(llvm_args, list);
+ key!(use_ctors_section, bool);
+ key!(eh_frame_header, bool);
+ key!(has_thumb_interworking, bool);
+ key!(split_debuginfo, SplitDebuginfo)?;
+ key!(supported_sanitizers, SanitizerSet)?;
+ key!(default_adjusted_cabi, Option<Abi>)?;
+ key!(c_enum_min_bits, u64);
+ key!(generate_arange_section, bool);
+ key!(supports_stack_protector, bool);
+
+ if base.is_builtin {
+ // This can cause unfortunate ICEs later down the line.
+ return Err("may not set is_builtin for targets not built-in".into());
+ }
+ // Each field should have been read using `Json::remove` so any keys remaining are unused.
+ let remaining_keys = obj.keys();
+ Ok((
+ base,
+ TargetWarnings { unused_fields: remaining_keys.cloned().collect(), incorrect_type },
+ ))
+ }
+
+ /// Load a built-in target
+ pub fn expect_builtin(target_triple: &TargetTriple) -> Target {
+ match *target_triple {
+ TargetTriple::TargetTriple(ref target_triple) => {
+ load_builtin(target_triple).expect("built-in target")
+ }
+ TargetTriple::TargetJson { .. } => {
+ panic!("built-in targets doens't support target-paths")
+ }
+ }
+ }
+
+ /// Search for a JSON file specifying the given target triple.
+ ///
+ /// If none is found in `$RUST_TARGET_PATH`, look for a file called `target.json` inside the
+ /// sysroot under the target-triple's `rustlib` directory. Note that it could also just be a
+ /// bare filename already, so also check for that. If one of the hardcoded targets we know
+ /// about, just return it directly.
+ ///
+ /// The error string could come from any of the APIs called, including filesystem access and
+ /// JSON decoding.
+ pub fn search(
+ target_triple: &TargetTriple,
+ sysroot: &Path,
+ ) -> Result<(Target, TargetWarnings), String> {
+ use std::env;
+ use std::fs;
+
+ fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
+ let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
+ let obj = serde_json::from_str(&contents).map_err(|e| e.to_string())?;
+ Target::from_json(obj)
+ }
+
+ match *target_triple {
+ TargetTriple::TargetTriple(ref target_triple) => {
+ // check if triple is in list of built-in targets
+ if let Some(t) = load_builtin(target_triple) {
+ return Ok((t, TargetWarnings::empty()));
+ }
+
+ // search for a file named `target_triple`.json in RUST_TARGET_PATH
+ let path = {
+ let mut target = target_triple.to_string();
+ target.push_str(".json");
+ PathBuf::from(target)
+ };
+
+ let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default();
+
+ for dir in env::split_paths(&target_path) {
+ let p = dir.join(&path);
+ if p.is_file() {
+ return load_file(&p);
+ }
+ }
+
+ // 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 p = PathBuf::from_iter([
+ Path::new(sysroot),
+ Path::new(&rustlib_path),
+ Path::new("target.json"),
+ ]);
+ if p.is_file() {
+ return load_file(&p);
+ }
+
+ Err(format!("Could not find specification for target {:?}", target_triple))
+ }
+ TargetTriple::TargetJson { ref contents, .. } => {
+ let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?;
+ Target::from_json(obj)
+ }
+ }
+ }
+}
+
+impl ToJson for Target {
+ fn to_json(&self) -> Json {
+ let mut d = serde_json::Map::new();
+ let default: TargetOptions = Default::default();
+
+ macro_rules! target_val {
+ ($attr:ident) => {{
+ let name = (stringify!($attr)).replace("_", "-");
+ d.insert(name, self.$attr.to_json());
+ }};
+ }
+
+ macro_rules! target_option_val {
+ ($attr:ident) => {{
+ let name = (stringify!($attr)).replace("_", "-");
+ if default.$attr != self.$attr {
+ d.insert(name, self.$attr.to_json());
+ }
+ }};
+ ($attr:ident, $key_name:expr) => {{
+ let name = $key_name;
+ if default.$attr != self.$attr {
+ d.insert(name.into(), self.$attr.to_json());
+ }
+ }};
+ (link_args - $attr:ident) => {{
+ let name = (stringify!($attr)).replace("_", "-");
+ if default.$attr != self.$attr {
+ let obj = self
+ .$attr
+ .iter()
+ .map(|(k, v)| (k.desc().to_string(), v.clone()))
+ .collect::<BTreeMap<_, _>>();
+ d.insert(name, obj.to_json());
+ }
+ }};
+ (env - $attr:ident) => {{
+ let name = (stringify!($attr)).replace("_", "-");
+ if default.$attr != self.$attr {
+ let obj = self
+ .$attr
+ .iter()
+ .map(|&(ref k, ref v)| format!("{k}={v}"))
+ .collect::<Vec<_>>();
+ d.insert(name, obj.to_json());
+ }
+ }};
+ }
+
+ target_val!(llvm_target);
+ d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json());
+ target_val!(arch);
+ target_val!(data_layout);
+
+ target_option_val!(is_builtin);
+ target_option_val!(endian, "target-endian");
+ target_option_val!(c_int_width, "target-c-int-width");
+ target_option_val!(os);
+ target_option_val!(env);
+ target_option_val!(abi);
+ target_option_val!(vendor);
+ target_option_val!(linker_flavor);
+ target_option_val!(linker);
+ target_option_val!(lld_flavor);
+ target_option_val!(pre_link_objects);
+ target_option_val!(post_link_objects);
+ target_option_val!(pre_link_objects_fallback);
+ target_option_val!(post_link_objects_fallback);
+ target_option_val!(crt_objects_fallback);
+ target_option_val!(link_args - pre_link_args);
+ target_option_val!(link_args - late_link_args);
+ target_option_val!(link_args - late_link_args_dynamic);
+ target_option_val!(link_args - late_link_args_static);
+ target_option_val!(link_args - post_link_args);
+ target_option_val!(link_script);
+ target_option_val!(env - link_env);
+ target_option_val!(link_env_remove);
+ target_option_val!(asm_args);
+ target_option_val!(cpu);
+ target_option_val!(features);
+ target_option_val!(dynamic_linking);
+ target_option_val!(only_cdylib);
+ target_option_val!(executables);
+ target_option_val!(relocation_model);
+ target_option_val!(code_model);
+ target_option_val!(tls_model);
+ target_option_val!(disable_redzone);
+ target_option_val!(frame_pointer);
+ target_option_val!(function_sections);
+ target_option_val!(dll_prefix);
+ target_option_val!(dll_suffix);
+ target_option_val!(exe_suffix);
+ target_option_val!(staticlib_prefix);
+ target_option_val!(staticlib_suffix);
+ target_option_val!(families, "target-family");
+ target_option_val!(abi_return_struct_as_int);
+ target_option_val!(is_like_osx);
+ target_option_val!(is_like_solaris);
+ target_option_val!(is_like_windows);
+ target_option_val!(is_like_msvc);
+ target_option_val!(is_like_wasm);
+ target_option_val!(default_dwarf_version);
+ target_option_val!(linker_is_gnu);
+ target_option_val!(allows_weak_linkage);
+ target_option_val!(has_rpath);
+ target_option_val!(no_default_libraries);
+ target_option_val!(position_independent_executables);
+ target_option_val!(static_position_independent_executables);
+ target_option_val!(needs_plt);
+ target_option_val!(relro_level);
+ target_option_val!(archive_format);
+ target_option_val!(allow_asm);
+ target_option_val!(main_needs_argc_argv);
+ target_option_val!(has_thread_local);
+ target_option_val!(obj_is_bitcode);
+ target_option_val!(forces_embed_bitcode);
+ target_option_val!(bitcode_llvm_cmdline);
+ target_option_val!(min_atomic_width);
+ target_option_val!(max_atomic_width);
+ target_option_val!(atomic_cas);
+ target_option_val!(panic_strategy);
+ target_option_val!(crt_static_allows_dylibs);
+ target_option_val!(crt_static_default);
+ target_option_val!(crt_static_respected);
+ target_option_val!(stack_probes);
+ target_option_val!(min_global_align);
+ target_option_val!(default_codegen_units);
+ target_option_val!(trap_unreachable);
+ target_option_val!(requires_lto);
+ target_option_val!(singlethread);
+ target_option_val!(no_builtins);
+ target_option_val!(default_hidden_visibility);
+ target_option_val!(emit_debug_gdb_scripts);
+ target_option_val!(requires_uwtable);
+ target_option_val!(default_uwtable);
+ target_option_val!(simd_types_indirect);
+ target_option_val!(limit_rdylib_exports);
+ target_option_val!(override_export_symbols);
+ target_option_val!(merge_functions);
+ target_option_val!(mcount, "target-mcount");
+ target_option_val!(llvm_abiname);
+ target_option_val!(relax_elf_relocations);
+ target_option_val!(llvm_args);
+ target_option_val!(use_ctors_section);
+ target_option_val!(eh_frame_header);
+ target_option_val!(has_thumb_interworking);
+ target_option_val!(split_debuginfo);
+ target_option_val!(supported_sanitizers);
+ target_option_val!(c_enum_min_bits);
+ target_option_val!(generate_arange_section);
+ target_option_val!(supports_stack_protector);
+
+ if let Some(abi) = self.default_adjusted_cabi {
+ d.insert("default-adjusted-cabi".into(), Abi::name(abi).to_json());
+ }
+
+ Json::Object(d)
+ }
+}
+
+/// Either a target triple string or a path to a JSON file.
+#[derive(Clone, Debug)]
+pub enum TargetTriple {
+ TargetTriple(String),
+ TargetJson {
+ /// Warning: This field may only be used by rustdoc. Using it anywhere else will lead to
+ /// inconsistencies as it is discarded during serialization.
+ path_for_rustdoc: PathBuf,
+ triple: String,
+ contents: String,
+ },
+}
+
+// Use a manual implementation to ignore the path field
+impl PartialEq for TargetTriple {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (Self::TargetTriple(l0), Self::TargetTriple(r0)) => l0 == r0,
+ (
+ Self::TargetJson { path_for_rustdoc: _, triple: l_triple, contents: l_contents },
+ Self::TargetJson { path_for_rustdoc: _, triple: r_triple, contents: r_contents },
+ ) => l_triple == r_triple && l_contents == r_contents,
+ _ => false,
+ }
+ }
+}
+
+// Use a manual implementation to ignore the path field
+impl Hash for TargetTriple {
+ fn hash<H: Hasher>(&self, state: &mut H) -> () {
+ match self {
+ TargetTriple::TargetTriple(triple) => {
+ 0u8.hash(state);
+ triple.hash(state)
+ }
+ TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => {
+ 1u8.hash(state);
+ triple.hash(state);
+ contents.hash(state)
+ }
+ }
+ }
+}
+
+// Use a manual implementation to prevent encoding the target json file path in the crate metadata
+impl<S: Encoder> Encodable<S> for TargetTriple {
+ fn encode(&self, s: &mut S) {
+ match self {
+ TargetTriple::TargetTriple(triple) => s.emit_enum_variant(0, |s| s.emit_str(triple)),
+ TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => s
+ .emit_enum_variant(1, |s| {
+ s.emit_str(triple);
+ s.emit_str(contents)
+ }),
+ }
+ }
+}
+
+impl<D: Decoder> Decodable<D> for TargetTriple {
+ fn decode(d: &mut D) -> Self {
+ match d.read_usize() {
+ 0 => TargetTriple::TargetTriple(d.read_str().to_owned()),
+ 1 => TargetTriple::TargetJson {
+ path_for_rustdoc: PathBuf::new(),
+ triple: d.read_str().to_owned(),
+ contents: d.read_str().to_owned(),
+ },
+ _ => {
+ panic!("invalid enum variant tag while decoding `TargetTriple`, expected 0..2");
+ }
+ }
+ }
+}
+
+impl TargetTriple {
+ /// Creates a target triple from the passed target triple string.
+ pub fn from_triple(triple: &str) -> Self {
+ TargetTriple::TargetTriple(triple.into())
+ }
+
+ /// Creates a target triple from the passed target path.
+ pub fn from_path(path: &Path) -> Result<Self, io::Error> {
+ let canonicalized_path = path.canonicalize()?;
+ let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
+ io::Error::new(
+ io::ErrorKind::InvalidInput,
+ format!("target path {:?} is not a valid file: {}", canonicalized_path, err),
+ )
+ })?;
+ let triple = canonicalized_path
+ .file_stem()
+ .expect("target path must not be empty")
+ .to_str()
+ .expect("target path must be valid unicode")
+ .to_owned();
+ Ok(TargetTriple::TargetJson { path_for_rustdoc: canonicalized_path, triple, contents })
+ }
+
+ /// Returns a string triple for this target.
+ ///
+ /// If this target is a path, the file name (without extension) is returned.
+ pub fn triple(&self) -> &str {
+ match *self {
+ TargetTriple::TargetTriple(ref triple)
+ | TargetTriple::TargetJson { ref triple, .. } => triple,
+ }
+ }
+
+ /// Returns an extended string triple for this target.
+ ///
+ /// If this target is a path, a hash of the path is appended to the triple returned
+ /// by `triple()`.
+ pub fn debug_triple(&self) -> String {
+ use std::collections::hash_map::DefaultHasher;
+
+ match self {
+ TargetTriple::TargetTriple(triple) => triple.to_owned(),
+ TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents: content } => {
+ let mut hasher = DefaultHasher::new();
+ content.hash(&mut hasher);
+ let hash = hasher.finish();
+ format!("{}-{}", triple, hash)
+ }
+ }
+ }
+}
+
+impl fmt::Display for TargetTriple {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}", self.debug_triple())
+ }
+}
diff --git a/compiler/rustc_target/src/spec/msp430_none_elf.rs b/compiler/rustc_target/src/spec/msp430_none_elf.rs
new file mode 100644
index 000000000..6b09386ae
--- /dev/null
+++ b/compiler/rustc_target/src/spec/msp430_none_elf.rs
@@ -0,0 +1,59 @@
+use crate::spec::{cvs, PanicStrategy, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "msp430-none-elf".into(),
+ pointer_width: 16,
+ data_layout: "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16".into(),
+ arch: "msp430".into(),
+
+ options: TargetOptions {
+ c_int_width: "16".into(),
+
+ // The LLVM backend currently can't generate object files. To
+ // workaround this LLVM generates assembly files which then we feed
+ // to gcc to get object files. For this reason we have a hard
+ // dependency on this specific gcc.
+ asm_args: cvs!["-mcpu=msp430"],
+ linker: Some("msp430-elf-gcc".into()),
+ linker_is_gnu: false,
+
+ // There are no atomic CAS instructions available in the MSP430
+ // instruction set, and the LLVM backend doesn't currently support
+ // compiler fences so the Atomic* API is missing on this target.
+ // When the LLVM backend gains support for compile fences uncomment
+ // the `singlethread: true` line and set `max_atomic_width` to
+ // `Some(16)`.
+ max_atomic_width: Some(0),
+ atomic_cas: false,
+ // singlethread: true,
+
+ // Because these devices have very little resources having an
+ // unwinder is too onerous so we default to "abort" because the
+ // "unwind" strategy is very rare.
+ panic_strategy: PanicStrategy::Abort,
+
+ // Similarly, one almost always never wants to use relocatable
+ // code because of the extra costs it involves.
+ relocation_model: RelocModel::Static,
+
+ // Right now we invoke an external assembler and this isn't
+ // compatible with multiple codegen units, and plus we probably
+ // don't want to invoke that many gcc instances.
+ default_codegen_units: Some(1),
+
+ // Since MSP430 doesn't meaningfully support faulting on illegal
+ // instructions, LLVM generates a call to abort() function instead
+ // of a trap instruction. Such calls are 4 bytes long, and that is
+ // too much overhead for such small target.
+ trap_unreachable: false,
+
+ // See the thumb_base.rs file for an explanation of this value
+ emit_debug_gdb_scripts: false,
+
+ eh_frame_header: false,
+
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/msvc_base.rs b/compiler/rustc_target/src/spec/msvc_base.rs
new file mode 100644
index 000000000..edb30b72b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/msvc_base.rs
@@ -0,0 +1,24 @@
+use crate::spec::{LinkerFlavor, LldFlavor, SplitDebuginfo, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ // Suppress the verbose logo and authorship debugging output, which would needlessly
+ // clog any log files.
+ let pre_link_args = TargetOptions::link_args(LinkerFlavor::Msvc, &["/NOLOGO"]);
+
+ TargetOptions {
+ linker_flavor: LinkerFlavor::Msvc,
+ is_like_windows: true,
+ is_like_msvc: true,
+ lld_flavor: LldFlavor::Link,
+ linker_is_gnu: false,
+ pre_link_args,
+ abi_return_struct_as_int: true,
+ emit_debug_gdb_scripts: false,
+
+ // Currently this is the only supported method of debuginfo on MSVC
+ // where `*.pdb` files show up next to the final artifact.
+ split_debuginfo: SplitDebuginfo::Packed,
+
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/netbsd_base.rs b/compiler/rustc_target/src/spec/netbsd_base.rs
new file mode 100644
index 000000000..be94ea234
--- /dev/null
+++ b/compiler/rustc_target/src/spec/netbsd_base.rs
@@ -0,0 +1,16 @@
+use crate::spec::{cvs, RelroLevel, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "netbsd".into(),
+ dynamic_linking: true,
+ families: cvs!["unix"],
+ no_default_libraries: false,
+ has_rpath: true,
+ position_independent_executables: true,
+ relro_level: RelroLevel::Full,
+ use_ctors_section: true,
+ default_dwarf_version: 2,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
new file mode 100644
index 000000000..1c5b68001
--- /dev/null
+++ b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
@@ -0,0 +1,53 @@
+use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ arch: "nvptx64".into(),
+ data_layout: "e-i64:64-i128:128-v16:16-v32:32-n16:32:64".into(),
+ llvm_target: "nvptx64-nvidia-cuda".into(),
+ pointer_width: 64,
+
+ options: TargetOptions {
+ os: "cuda".into(),
+ vendor: "nvidia".into(),
+ linker_flavor: LinkerFlavor::PtxLinker,
+ // The linker can be installed from `crates.io`.
+ linker: Some("rust-ptx-linker".into()),
+ linker_is_gnu: false,
+
+ // With `ptx-linker` approach, it can be later overridden via link flags.
+ cpu: "sm_30".into(),
+
+ // FIXME: create tests for the atomics.
+ max_atomic_width: Some(64),
+
+ // Unwinding on CUDA is neither feasible nor useful.
+ panic_strategy: PanicStrategy::Abort,
+
+ // Needed to use `dylib` and `bin` crate types and the linker.
+ dynamic_linking: true,
+
+ // Avoid using dylib because it contain metadata not supported
+ // by LLVM NVPTX backend.
+ only_cdylib: true,
+
+ // Let the `ptx-linker` to handle LLVM lowering into MC / assembly.
+ obj_is_bitcode: true,
+
+ // Convenient and predicable naming scheme.
+ dll_prefix: "".into(),
+ dll_suffix: ".ptx".into(),
+ exe_suffix: ".ptx".into(),
+
+ // Disable MergeFunctions LLVM optimisation pass because it can
+ // produce kernel functions that call other kernel functions.
+ // This behavior is not supported by PTX ISA.
+ merge_functions: MergeFunctions::Disabled,
+
+ // The LLVM backend does not support stack canaries for this target
+ supports_stack_protector: false,
+
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/openbsd_base.rs b/compiler/rustc_target/src/spec/openbsd_base.rs
new file mode 100644
index 000000000..e7db14e05
--- /dev/null
+++ b/compiler/rustc_target/src/spec/openbsd_base.rs
@@ -0,0 +1,16 @@
+use crate::spec::{cvs, FramePointer, RelroLevel, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "openbsd".into(),
+ dynamic_linking: true,
+ families: cvs!["unix"],
+ has_rpath: true,
+ abi_return_struct_as_int: true,
+ position_independent_executables: true,
+ frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit...
+ relro_level: RelroLevel::Full,
+ default_dwarf_version: 2,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
new file mode 100644
index 000000000..803453c4a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
@@ -0,0 +1,17 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::freebsd_base::opts();
+ base.cpu = "ppc64".into();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "powerpc64-unknown-freebsd".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i64:64-n32:64".into(),
+ arch: "powerpc64".into(),
+ options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
new file mode 100644
index 000000000..5413c4f33
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
@@ -0,0 +1,21 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, RelroLevel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.cpu = "ppc64".into();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.max_atomic_width = Some(64);
+
+ // ld.so in at least RHEL6 on ppc64 has a bug related to BIND_NOW, so only enable partial RELRO
+ // for now. https://github.com/rust-lang/rust/pull/43170#issuecomment-315411474
+ base.relro_level = RelroLevel::Partial;
+
+ Target {
+ llvm_target: "powerpc64-unknown-linux-gnu".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+ arch: "powerpc64".into(),
+ options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
new file mode 100644
index 000000000..159335eb6
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
@@ -0,0 +1,17 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.cpu = "ppc64".into();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "powerpc64-unknown-linux-musl".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+ arch: "powerpc64".into(),
+ options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
new file mode 100644
index 000000000..b7420d232
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
@@ -0,0 +1,17 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::vxworks_base::opts();
+ base.cpu = "ppc64".into();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "powerpc64-unknown-linux-gnu".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+ arch: "powerpc64".into(),
+ options: TargetOptions { endian: Endian::Big, ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
new file mode 100644
index 000000000..a3d180043
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
@@ -0,0 +1,16 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::freebsd_base::opts();
+ base.cpu = "ppc64le".into();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "powerpc64le-unknown-freebsd".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i64:64-n32:64".into(),
+ arch: "powerpc64".into(),
+ options: TargetOptions { mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
new file mode 100644
index 000000000..e18ff3be4
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
@@ -0,0 +1,16 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.cpu = "ppc64le".into();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "powerpc64le-unknown-linux-gnu".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+ arch: "powerpc64".into(),
+ options: TargetOptions { mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
new file mode 100644
index 000000000..b84943d23
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
@@ -0,0 +1,16 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.cpu = "ppc64le".into();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "powerpc64le-unknown-linux-musl".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
+ arch: "powerpc64".into(),
+ options: TargetOptions { mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
new file mode 100644
index 000000000..516b2de37
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
@@ -0,0 +1,23 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::freebsd_base::opts();
+ // Extra hint to linker that we are generating secure-PLT code.
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--target=powerpc-unknown-freebsd13.0"]);
+ base.max_atomic_width = Some(32);
+
+ Target {
+ llvm_target: "powerpc-unknown-freebsd13.0".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+ arch: "powerpc".into(),
+ options: TargetOptions {
+ endian: Endian::Big,
+ features: "+secure-plt".into(),
+ relocation_model: RelocModel::Pic,
+ mcount: "_mcount".into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
new file mode 100644
index 000000000..6686a0bbf
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
@@ -0,0 +1,16 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ base.max_atomic_width = Some(32);
+
+ Target {
+ llvm_target: "powerpc-unknown-linux-gnu".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+ arch: "powerpc".into(),
+ options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
new file mode 100644
index 000000000..6a250f4b5
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
@@ -0,0 +1,21 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe"]);
+ base.max_atomic_width = Some(32);
+
+ Target {
+ llvm_target: "powerpc-unknown-linux-gnuspe".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+ arch: "powerpc".into(),
+ options: TargetOptions {
+ abi: "spe".into(),
+ endian: Endian::Big,
+ mcount: "_mcount".into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
new file mode 100644
index 000000000..34200c679
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
@@ -0,0 +1,16 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ base.max_atomic_width = Some(32);
+
+ Target {
+ llvm_target: "powerpc-unknown-linux-musl".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+ arch: "powerpc".into(),
+ options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
new file mode 100644
index 000000000..60661ef9b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
@@ -0,0 +1,16 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::netbsd_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ base.max_atomic_width = Some(32);
+
+ Target {
+ llvm_target: "powerpc-unknown-netbsd".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+ arch: "powerpc".into(),
+ options: TargetOptions { endian: Endian::Big, mcount: "__mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
new file mode 100644
index 000000000..ad2c3d40f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
@@ -0,0 +1,16 @@
+use crate::abi::Endian;
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::openbsd_base::opts();
+ base.endian = Endian::Big;
+ base.max_atomic_width = Some(32);
+
+ Target {
+ llvm_target: "powerpc-unknown-openbsd".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+ arch: "powerpc".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
new file mode 100644
index 000000000..3f24966e0
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
@@ -0,0 +1,16 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::vxworks_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--secure-plt"]);
+ base.max_atomic_width = Some(32);
+
+ Target {
+ llvm_target: "powerpc-unknown-linux-gnu".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+ arch: "powerpc".into(),
+ options: TargetOptions { endian: Endian::Big, features: "+secure-plt".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
new file mode 100644
index 000000000..0f04f41f9
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
@@ -0,0 +1,22 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::vxworks_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe", "--secure-plt"]);
+ base.max_atomic_width = Some(32);
+
+ Target {
+ llvm_target: "powerpc-unknown-linux-gnuspe".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-i64:64-n32".into(),
+ arch: "powerpc".into(),
+ options: TargetOptions {
+ abi: "spe".into(),
+ endian: Endian::Big,
+ // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2
+ features: "+secure-plt,+msync".into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/redox_base.rs b/compiler/rustc_target/src/spec/redox_base.rs
new file mode 100644
index 000000000..468fe4785
--- /dev/null
+++ b/compiler/rustc_target/src/spec/redox_base.rs
@@ -0,0 +1,17 @@
+use crate::spec::{cvs, RelroLevel, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "redox".into(),
+ env: "relibc".into(),
+ dynamic_linking: true,
+ families: cvs!["unix"],
+ has_rpath: true,
+ position_independent_executables: true,
+ relro_level: RelroLevel::Full,
+ has_thread_local: true,
+ crt_static_default: true,
+ crt_static_respected: true,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs
new file mode 100644
index 000000000..bffd377bc
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs
@@ -0,0 +1,18 @@
+use crate::spec::{CodeModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "riscv32-unknown-linux-gnu".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+ arch: "riscv32".into(),
+ options: TargetOptions {
+ code_model: Some(CodeModel::Medium),
+ cpu: "generic-rv32".into(),
+ features: "+m,+a,+f,+d,+c".into(),
+ llvm_abiname: "ilp32d".into(),
+ max_atomic_width: Some(32),
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs
new file mode 100644
index 000000000..c9f3acffb
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs
@@ -0,0 +1,18 @@
+use crate::spec::{CodeModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "riscv32-unknown-linux-musl".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+ arch: "riscv32".into(),
+ options: TargetOptions {
+ code_model: Some(CodeModel::Medium),
+ cpu: "generic-rv32".into(),
+ features: "+m,+a,+f,+d,+c".into(),
+ llvm_abiname: "ilp32d".into(),
+ max_atomic_width: Some(32),
+ ..super::linux_musl_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs
new file mode 100644
index 000000000..232139db6
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs
@@ -0,0 +1,24 @@
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+ llvm_target: "riscv32".into(),
+ pointer_width: 32,
+ arch: "riscv32".into(),
+
+ options: TargetOptions {
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ cpu: "generic-rv32".into(),
+ max_atomic_width: Some(0),
+ atomic_cas: false,
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ emit_debug_gdb_scripts: false,
+ eh_frame_header: false,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs
new file mode 100644
index 000000000..3e5d2887f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs
@@ -0,0 +1,25 @@
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+ llvm_target: "riscv32".into(),
+ pointer_width: 32,
+ arch: "riscv32".into(),
+
+ options: TargetOptions {
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ cpu: "generic-rv32".into(),
+ max_atomic_width: Some(0),
+ atomic_cas: false,
+ features: "+m".into(),
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ emit_debug_gdb_scripts: false,
+ eh_frame_header: false,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs
new file mode 100644
index 000000000..99317b9f1
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs
@@ -0,0 +1,24 @@
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+ llvm_target: "riscv32".into(),
+ pointer_width: 32,
+ arch: "riscv32".into(),
+
+ options: TargetOptions {
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ cpu: "generic-rv32".into(),
+ max_atomic_width: Some(32),
+ features: "+m,+a,+c".into(),
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ emit_debug_gdb_scripts: false,
+ eh_frame_header: false,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs b/compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs
new file mode 100644
index 000000000..a5de645c9
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs
@@ -0,0 +1,23 @@
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+ llvm_target: "riscv32".into(),
+ pointer_width: 32,
+ arch: "riscv32".into(),
+
+ options: TargetOptions {
+ os: "xous".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ cpu: "generic-rv32".into(),
+ max_atomic_width: Some(32),
+ features: "+m,+a,+c".into(),
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
new file mode 100644
index 000000000..03baef65c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
@@ -0,0 +1,36 @@
+use crate::spec::{cvs, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel};
+
+pub fn target() -> Target {
+ Target {
+ data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+ llvm_target: "riscv32".into(),
+ pointer_width: 32,
+ arch: "riscv32".into(),
+
+ options: TargetOptions {
+ families: cvs!["unix"],
+ os: "espidf".into(),
+ env: "newlib".into(),
+ vendor: "espressif".into(),
+ linker_flavor: LinkerFlavor::Gcc,
+ linker: Some("riscv32-esp-elf-gcc".into()),
+ cpu: "generic-rv32".into(),
+
+ // While the RiscV32IMC architecture does not natively support atomics, ESP-IDF does support
+ // the __atomic* and __sync* GCC builtins, so setting `max_atomic_width` to `Some(64)`
+ // and `atomic_cas` to `true` will cause the compiler to emit libcalls to these builtins.
+ //
+ // Support for atomics is necessary for the Rust STD library, which is supported by the ESP-IDF framework.
+ max_atomic_width: Some(64),
+ atomic_cas: true,
+
+ features: "+m,+c".into(),
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ emit_debug_gdb_scripts: false,
+ eh_frame_header: false,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs
new file mode 100644
index 000000000..bf510d204
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs
@@ -0,0 +1,25 @@
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+ llvm_target: "riscv32".into(),
+ pointer_width: 32,
+ arch: "riscv32".into(),
+
+ options: TargetOptions {
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ cpu: "generic-rv32".into(),
+ max_atomic_width: Some(0),
+ atomic_cas: false,
+ features: "+m,+c".into(),
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ emit_debug_gdb_scripts: false,
+ eh_frame_header: false,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs
new file mode 100644
index 000000000..0539eca6c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs
@@ -0,0 +1,18 @@
+use crate::spec::{CodeModel, Target, TargetOptions};
+
+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(),
+ arch: "riscv64".into(),
+ options: TargetOptions {
+ code_model: Some(CodeModel::Medium),
+ cpu: "generic-rv64".into(),
+ features: "+m,+a,+f,+d,+c".into(),
+ llvm_abiname: "lp64d".into(),
+ max_atomic_width: Some(64),
+ ..super::freebsd_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs
new file mode 100644
index 000000000..7d1bf228c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs
@@ -0,0 +1,18 @@
+use crate::spec::{CodeModel, Target, TargetOptions};
+
+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(),
+ arch: "riscv64".into(),
+ options: TargetOptions {
+ code_model: Some(CodeModel::Medium),
+ cpu: "generic-rv64".into(),
+ features: "+m,+a,+f,+d,+c".into(),
+ llvm_abiname: "lp64d".into(),
+ max_atomic_width: Some(64),
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
new file mode 100644
index 000000000..f04f8a48b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
@@ -0,0 +1,18 @@
+use crate::spec::{CodeModel, Target, TargetOptions};
+
+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(),
+ arch: "riscv64".into(),
+ options: TargetOptions {
+ code_model: Some(CodeModel::Medium),
+ cpu: "generic-rv64".into(),
+ features: "+m,+a,+f,+d,+c".into(),
+ llvm_abiname: "lp64d".into(),
+ max_atomic_width: Some(64),
+ ..super::linux_musl_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
new file mode 100644
index 000000000..03b3cfd1e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
@@ -0,0 +1,26 @@
+use crate::spec::{CodeModel, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+ llvm_target: "riscv64".into(),
+ pointer_width: 64,
+ arch: "riscv64".into(),
+
+ options: TargetOptions {
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ llvm_abiname: "lp64d".into(),
+ cpu: "generic-rv64".into(),
+ max_atomic_width: Some(64),
+ features: "+m,+a,+f,+d,+c".into(),
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ code_model: Some(CodeModel::Medium),
+ emit_debug_gdb_scripts: false,
+ eh_frame_header: false,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
new file mode 100644
index 000000000..2a94c9dd2
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
@@ -0,0 +1,25 @@
+use crate::spec::{CodeModel, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+
+pub fn target() -> Target {
+ Target {
+ data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+ llvm_target: "riscv64".into(),
+ pointer_width: 64,
+ arch: "riscv64".into(),
+
+ options: TargetOptions {
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ cpu: "generic-rv64".into(),
+ max_atomic_width: Some(64),
+ features: "+m,+a,+c".into(),
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ code_model: Some(CodeModel::Medium),
+ emit_debug_gdb_scripts: false,
+ eh_frame_header: false,
+ ..Default::default()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
new file mode 100644
index 000000000..8757bbed8
--- /dev/null
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
@@ -0,0 +1,23 @@
+use crate::abi::Endian;
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.endian = Endian::Big;
+ // z10 is the oldest CPU supported by LLVM
+ base.cpu = "z10".into();
+ // FIXME: The data_layout string below and the ABI implementation in
+ // cabi_s390x.rs are for now hard-coded to assume the no-vector ABI.
+ // Pass the -vector feature string to LLVM to respect this assumption.
+ base.features = "-vector".into();
+ base.max_atomic_width = Some(64);
+ base.min_global_align = Some(16);
+
+ Target {
+ llvm_target: "s390x-unknown-linux-gnu".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".into(),
+ arch: "s390x".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
new file mode 100644
index 000000000..4c855271a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
@@ -0,0 +1,24 @@
+use crate::abi::Endian;
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.endian = Endian::Big;
+ // z10 is the oldest CPU supported by LLVM
+ base.cpu = "z10".into();
+ // FIXME: The data_layout string below and the ABI implementation in
+ // cabi_s390x.rs are for now hard-coded to assume the no-vector ABI.
+ // Pass the -vector feature string to LLVM to respect this assumption.
+ base.features = "-vector".into();
+ base.max_atomic_width = Some(64);
+ base.min_global_align = Some(16);
+ base.static_position_independent_executables = true;
+
+ Target {
+ llvm_target: "s390x-unknown-linux-musl".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".into(),
+ arch: "s390x".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/solaris_base.rs b/compiler/rustc_target/src/spec/solaris_base.rs
new file mode 100644
index 000000000..b7e8e8cf7
--- /dev/null
+++ b/compiler/rustc_target/src/spec/solaris_base.rs
@@ -0,0 +1,16 @@
+use crate::spec::{cvs, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "solaris".into(),
+ dynamic_linking: true,
+ has_rpath: true,
+ families: cvs!["unix"],
+ is_like_solaris: true,
+ linker_is_gnu: false,
+ limit_rdylib_exports: false, // Linker doesn't support this
+ eh_frame_header: false,
+
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/solid_base.rs b/compiler/rustc_target/src/spec/solid_base.rs
new file mode 100644
index 000000000..c585a6cd5
--- /dev/null
+++ b/compiler/rustc_target/src/spec/solid_base.rs
@@ -0,0 +1,13 @@
+use super::FramePointer;
+use crate::spec::TargetOptions;
+
+pub fn opts(kernel: &str) -> TargetOptions {
+ TargetOptions {
+ os: format!("solid_{}", kernel).into(),
+ vendor: "kmc".into(),
+ executables: false,
+ frame_pointer: FramePointer::NonLeaf,
+ has_thread_local: true,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
new file mode 100644
index 000000000..39efd8f30
--- /dev/null
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
@@ -0,0 +1,17 @@
+use crate::abi::Endian;
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.endian = Endian::Big;
+ base.cpu = "v9".into();
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "sparc64-unknown-linux-gnu".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+ arch: "sparc64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
new file mode 100644
index 000000000..836ab0e37
--- /dev/null
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
@@ -0,0 +1,17 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::netbsd_base::opts();
+ base.cpu = "v9".into();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "sparc64-unknown-netbsd".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+ arch: "sparc64".into(),
+ options: TargetOptions { endian: Endian::Big, mcount: "__mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
new file mode 100644
index 000000000..4a192df39
--- /dev/null
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
@@ -0,0 +1,18 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut base = super::openbsd_base::opts();
+ base.endian = Endian::Big;
+ base.cpu = "v9".into();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "sparc64-unknown-openbsd".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+ arch: "sparc64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
new file mode 100644
index 000000000..ea4fafa4b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
@@ -0,0 +1,18 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.endian = Endian::Big;
+ base.cpu = "v9".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-mv8plus"]);
+
+ Target {
+ llvm_target: "sparc-unknown-linux-gnu".into(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(),
+ arch: "sparc".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
new file mode 100644
index 000000000..aac09181a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
@@ -0,0 +1,24 @@
+use crate::abi::Endian;
+use crate::spec::{LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut base = super::solaris_base::opts();
+ base.endian = Endian::Big;
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // llvm calls this "v9"
+ base.cpu = "v9".into();
+ base.vendor = "sun".into();
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "sparcv9-sun-solaris".into(),
+ pointer_width: 64,
+ data_layout: "E-m:e-i64:64-n32:64-S128".into(),
+ // Use "sparc64" instead of "sparcv9" here, since the former is already
+ // used widely in the source base. If we ever needed ABI
+ // differentiation from the sparc64, we could, but that would probably
+ // just be confusing.
+ arch: "sparc64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs
new file mode 100644
index 000000000..1db6db78b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs
@@ -0,0 +1,135 @@
+use super::super::*;
+use std::assert_matches::assert_matches;
+
+// Test target self-consistency and JSON encoding/decoding roundtrip.
+pub(super) fn test_target(target: Target) {
+ target.check_consistency();
+ assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target));
+}
+
+impl Target {
+ 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");
+ assert_eq!(self.is_like_wasm, self.arch == "wasm32" || self.arch == "wasm64");
+ assert!(self.is_like_windows || !self.is_like_msvc);
+
+ // Check that default linker flavor and lld flavor are compatible
+ // with some other key properties.
+ assert_eq!(self.is_like_osx, matches!(self.lld_flavor, LldFlavor::Ld64));
+ assert_eq!(self.is_like_msvc, matches!(self.lld_flavor, LldFlavor::Link));
+ assert_eq!(self.is_like_wasm, matches!(self.lld_flavor, LldFlavor::Wasm));
+ assert_eq!(self.os == "l4re", matches!(self.linker_flavor, LinkerFlavor::L4Bender));
+ assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::Em));
+ assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::BpfLinker));
+ assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::PtxLinker));
+
+ for args in [
+ &self.pre_link_args,
+ &self.late_link_args,
+ &self.late_link_args_dynamic,
+ &self.late_link_args_static,
+ &self.post_link_args,
+ ] {
+ for (&flavor, flavor_args) in args {
+ assert!(!flavor_args.is_empty());
+ // Check that flavors mentioned in link args are compatible with the default flavor.
+ match (self.linker_flavor, self.lld_flavor) {
+ (
+ LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc,
+ LldFlavor::Ld,
+ ) => {
+ assert_matches!(
+ flavor,
+ LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc
+ )
+ }
+ (LinkerFlavor::Gcc, LldFlavor::Ld64) => {
+ assert_matches!(
+ flavor,
+ LinkerFlavor::Lld(LldFlavor::Ld64) | LinkerFlavor::Gcc
+ )
+ }
+ (LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link), LldFlavor::Link) => {
+ assert_matches!(
+ flavor,
+ LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link)
+ )
+ }
+ (LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc, LldFlavor::Wasm) => {
+ assert_matches!(
+ flavor,
+ LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc
+ )
+ }
+ (LinkerFlavor::L4Bender, LldFlavor::Ld) => {
+ assert_matches!(flavor, LinkerFlavor::L4Bender)
+ }
+ (LinkerFlavor::Em, LldFlavor::Wasm) => {
+ assert_matches!(flavor, LinkerFlavor::Em)
+ }
+ (LinkerFlavor::BpfLinker, LldFlavor::Ld) => {
+ assert_matches!(flavor, LinkerFlavor::BpfLinker)
+ }
+ (LinkerFlavor::PtxLinker, LldFlavor::Ld) => {
+ assert_matches!(flavor, LinkerFlavor::PtxLinker)
+ }
+ flavors => unreachable!("unexpected flavor combination: {:?}", flavors),
+ }
+
+ // Check that link args for cc and non-cc versions of flavors are consistent.
+ let check_noncc = |noncc_flavor| {
+ if let Some(noncc_args) = args.get(&noncc_flavor) {
+ for arg in flavor_args {
+ if let Some(suffix) = arg.strip_prefix("-Wl,") {
+ assert!(noncc_args.iter().any(|a| a == suffix));
+ }
+ }
+ }
+ };
+ match self.linker_flavor {
+ LinkerFlavor::Gcc => match self.lld_flavor {
+ LldFlavor::Ld => {
+ check_noncc(LinkerFlavor::Ld);
+ check_noncc(LinkerFlavor::Lld(LldFlavor::Ld));
+ }
+ LldFlavor::Wasm => check_noncc(LinkerFlavor::Lld(LldFlavor::Wasm)),
+ LldFlavor::Ld64 | LldFlavor::Link => {}
+ },
+ _ => {}
+ }
+ }
+
+ // Check that link args for lld and non-lld versions of flavors are consistent.
+ assert_eq!(args.get(&LinkerFlavor::Ld), args.get(&LinkerFlavor::Lld(LldFlavor::Ld)));
+ assert_eq!(
+ args.get(&LinkerFlavor::Msvc),
+ args.get(&LinkerFlavor::Lld(LldFlavor::Link)),
+ );
+ }
+
+ assert!(
+ (self.pre_link_objects_fallback.is_empty()
+ && self.post_link_objects_fallback.is_empty())
+ || self.crt_objects_fallback.is_some()
+ );
+
+ // If your target really needs to deviate from the rules below,
+ // except it and document the reasons.
+ // Keep the default "unknown" vendor instead.
+ assert_ne!(self.vendor, "");
+ if !self.can_use_os_unknown() {
+ // Keep the default "none" for bare metal targets instead.
+ assert_ne!(self.os, "unknown");
+ }
+ }
+
+ // Add your target to the whitelist if it has `std` library
+ // and you certainly want "unknown" for the OS name.
+ fn can_use_os_unknown(&self) -> bool {
+ self.llvm_target == "wasm32-unknown-unknown"
+ || self.llvm_target == "wasm64-unknown-unknown"
+ || (self.env == "sgx" && self.vendor == "fortanix")
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs
new file mode 100644
index 000000000..049142b89
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumb_base.rs
@@ -0,0 +1,60 @@
+// These `thumbv*` targets cover the ARM Cortex-M family of processors which are widely used in
+// microcontrollers. Namely, all these processors:
+//
+// - Cortex-M0
+// - Cortex-M0+
+// - Cortex-M1
+// - Cortex-M3
+// - Cortex-M4(F)
+// - Cortex-M7(F)
+// - Cortex-M23
+// - Cortex-M33
+//
+// We have opted for these instead of one target per processor (e.g., `cortex-m0`, `cortex-m3`,
+// etc) because the differences between some processors like the cortex-m0 and cortex-m1 are almost
+// non-existent from the POV of codegen so it doesn't make sense to have separate targets for them.
+// And if differences exist between two processors under the same target, rustc flags can be used to
+// optimize for one processor or the other.
+//
+// Also, we have not chosen a single target (`arm-none-eabi`) like GCC does because this makes
+// difficult to integrate Rust code and C code. Targeting the Cortex-M4 requires different gcc flags
+// than the ones you would use for the Cortex-M0 and with a single target it'd be impossible to
+// differentiate one processor from the other.
+//
+// About arm vs thumb in the name. The Cortex-M devices only support the Thumb instruction set,
+// which is more compact (higher code density), and not the ARM instruction set. That's why LLVM
+// triples use thumb instead of arm. We follow suit because having thumb in the name let us
+// differentiate these targets from our other `arm(v7)-*-*-gnueabi(hf)` targets in the context of
+// build scripts / gcc flags.
+
+use crate::spec::TargetOptions;
+use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+
+pub fn opts() -> TargetOptions {
+ // See rust-lang/rfcs#1645 for a discussion about these defaults
+ TargetOptions {
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ // In most cases, LLD is good enough
+ linker: Some("rust-lld".into()),
+ // Because these devices have very little resources having an unwinder is too onerous so we
+ // default to "abort" because the "unwind" strategy is very rare.
+ panic_strategy: PanicStrategy::Abort,
+ // Similarly, one almost always never wants to use relocatable code because of the extra
+ // costs it involves.
+ relocation_model: RelocModel::Static,
+ // When this section is added a volatile load to its start address is also generated. This
+ // volatile load is a footgun as it can end up loading an invalid memory address, depending
+ // on how the user set up their linker scripts. This section adds pretty printer for stuff
+ // like std::Vec, which is not that used in no-std context, so it's best to left it out
+ // until we figure a way to add the pretty printers without requiring a volatile load cf.
+ // rust-lang/rust#44993.
+ emit_debug_gdb_scripts: false,
+ // LLVM is eager to trash the link register when calling `noreturn` functions, which
+ // breaks debugging. Preserve LR by default to prevent that from happening.
+ frame_pointer: FramePointer::Always,
+ // ARM supports multiple ABIs for enums, the linux one matches the default of 32 here
+ // but any arm-none or thumb-none target will be defaulted to 8 on GCC and clang
+ c_enum_min_bits: 8,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
new file mode 100644
index 000000000..7125d141a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
@@ -0,0 +1,69 @@
+//! Targets the ARMv4T, with code as `t32` code by default.
+//!
+//! Primarily of use for the GBA, but usable with other devices too.
+//!
+//! Please ping @Lokathor if changes are needed.
+//!
+//! This target profile assumes that you have the ARM binutils in your path
+//! (specifically the linker, `arm-none-eabi-ld`). They can be obtained for free
+//! for all major OSes from the ARM developer's website, and they may also be
+//! available in your system's package manager. Unfortunately, the standard
+//! linker that Rust uses (`lld`) only supports as far back as `ARMv5TE`, so we
+//! must use the GNU `ld` linker.
+//!
+//! **Important:** This target profile **does not** specify a linker script. You
+//! just get the default link script when you build a binary for this target.
+//! The default link script is very likely wrong, so you should use
+//! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
+
+use crate::spec::{
+ cvs, FramePointer, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions,
+};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "thumbv4t-none-eabi".into(),
+ pointer_width: 32,
+ arch: "arm".into(),
+ /* Data layout args are '-' separated:
+ * little endian
+ * stack is 64-bit aligned (EABI)
+ * pointers are 32-bit
+ * i64 must be 64-bit aligned (EABI)
+ * mangle names with ELF style
+ * native integers are 32-bit
+ * All other elements are default
+ */
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ linker_flavor: LinkerFlavor::Ld,
+ linker: Some("arm-none-eabi-ld".into()),
+
+ // extra args passed to the external assembler (assuming `arm-none-eabi-as`):
+ // * activate t32/a32 interworking
+ // * use arch ARMv4T
+ // * use little-endian
+ asm_args: cvs!["-mthumb-interwork", "-march=armv4t", "-mlittle-endian",],
+
+ // minimum extra features, these cannot be disabled via -C
+ features: "+soft-float,+strict-align".into(),
+
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ // suggested from thumb_base, rust-lang/rust#44993.
+ emit_debug_gdb_scripts: false,
+ // suggested from thumb_base, with no-os gcc/clang use 8-bit enums
+ c_enum_min_bits: 8,
+ frame_pointer: FramePointer::MayOmit,
+
+ main_needs_argc_argv: false,
+
+ // don't have atomic compare-and-swap
+ atomic_cas: false,
+ has_thumb_interworking: true,
+
+ ..super::thumb_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs
new file mode 100644
index 000000000..2546ab9b7
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs
@@ -0,0 +1,23 @@
+// Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture)
+
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "thumbv6m-none-eabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ abi: "eabi".into(),
+ // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them
+ // with +strict-align.
+ features: "+strict-align".into(),
+ // There are no atomic CAS instructions available in the instruction set of the ARMv6-M
+ // architecture
+ atomic_cas: false,
+ ..super::thumb_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
new file mode 100644
index 000000000..4d09d3a4d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
@@ -0,0 +1,28 @@
+use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::windows_msvc_base::opts();
+ // Prevent error LNK2013: BRANCH24(T) fixup overflow
+ // The LBR optimization tries to eliminate branch islands,
+ // but if the displacement is larger than can fit
+ // in the instruction, this error will occur. The linker
+ // should be smart enough to insert branch islands only
+ // where necessary, but this is not the observed behavior.
+ // Disabling the LBR optimization works around the issue.
+ base.add_pre_link_args(LinkerFlavor::Msvc, &["/OPT:NOLBR"]);
+
+ Target {
+ llvm_target: "thumbv7a-pc-windows-msvc".into(),
+ pointer_width: 32,
+ data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ features: "+vfp3,+neon".into(),
+ max_atomic_width: Some(64),
+ // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
+ // implemented for windows/arm in LLVM
+ panic_strategy: PanicStrategy::Abort,
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs
new file mode 100644
index 000000000..65c2f5a70
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs
@@ -0,0 +1,18 @@
+use crate::spec::{PanicStrategy, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "thumbv7a-pc-windows-msvc".into(),
+ pointer_width: 32,
+ data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ features: "+vfp3,+neon".into(),
+ max_atomic_width: Some(64),
+ // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
+ // implemented for windows/arm in LLVM
+ panic_strategy: PanicStrategy::Abort,
+ ..super::windows_uwp_msvc_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs
new file mode 100644
index 000000000..000e5f2d3
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs
@@ -0,0 +1,27 @@
+// Targets the Cortex-M4 and Cortex-M7 processors (ARMv7E-M)
+//
+// This target assumes that the device doesn't have a FPU (Floating Point Unit) and lowers all the
+// floating point operations to software routines (intrinsics).
+//
+// As such, this target uses the "soft" calling convention (ABI) where floating point values are
+// passed to/from subroutines via general purpose registers (R0, R1, etc.).
+//
+// To opt-in to hardware accelerated floating point operations, you can use, for example,
+// `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`.
+
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "thumbv7em-none-eabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ abi: "eabi".into(),
+ max_atomic_width: Some(32),
+ ..super::thumb_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs b/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs
new file mode 100644
index 000000000..39a72564e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs
@@ -0,0 +1,36 @@
+// Targets the Cortex-M4F and Cortex-M7F processors (ARMv7E-M)
+//
+// This target assumes that the device does have a FPU (Floating Point Unit) and lowers all (single
+// precision) floating point operations to hardware instructions.
+//
+// Additionally, this target uses the "hard" floating convention (ABI) where floating point values
+// are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.).
+//
+// To opt into double precision hardware support, use the `-C target-feature=+fp64` flag.
+
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "thumbv7em-none-eabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
+ // Cortex-M7 (vfp5)
+ // `-d32` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
+ // available
+ // `-fp64` The Cortex-M4 only supports single precision floating point operations
+ // whereas in the Cortex-M7 double precision is optional
+ //
+ // Reference:
+ // ARMv7-M Architecture Reference Manual - A2.5 The optional floating-point extension
+ features: "+vfp4,-d32,-fp64".into(),
+ max_atomic_width: Some(32),
+ ..super::thumb_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs
new file mode 100644
index 000000000..ab25cde66
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs
@@ -0,0 +1,18 @@
+// Targets the Cortex-M3 processor (ARMv7-M)
+
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "thumbv7m-none-eabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ abi: "eabi".into(),
+ max_atomic_width: Some(32),
+ ..super::thumb_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
new file mode 100644
index 000000000..4cad9e183
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
@@ -0,0 +1,26 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+// This target if is for the Android v7a ABI in thumb mode with
+// NEON unconditionally enabled and, therefore, with 32 FPU registers
+// enabled as well. See section A2.6.2 on page A2-56 in
+// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
+
+// See https://developer.android.com/ndk/guides/abis.html#v7a
+// for target ABI requirements.
+
+pub fn target() -> Target {
+ let mut base = super::android_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-march=armv7-a"]);
+ Target {
+ llvm_target: "armv7-none-linux-android".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabi".into(),
+ features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(),
+ max_atomic_width: Some(64),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs
new file mode 100644
index 000000000..28c81340a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs
@@ -0,0 +1,23 @@
+use crate::spec::{Target, TargetOptions};
+
+// This target is for glibc Linux on ARMv7 with thumb mode enabled
+// (for consistency with Android and Debian-based distributions)
+// and with NEON unconditionally enabled and, therefore, with 32 FPU
+// registers enabled as well. See section A2.6.2 on page A2-56 in
+// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ // Info about features at https://wiki.debian.org/ArmHardFloatPort
+ features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(),
+ max_atomic_width: Some(64),
+ ..super::linux_gnu_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs
new file mode 100644
index 000000000..2c375ab22
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs
@@ -0,0 +1,29 @@
+use crate::spec::{Target, TargetOptions};
+
+// This target is for musl Linux on ARMv7 with thumb mode enabled
+// (for consistency with Android and Debian-based distributions)
+// and with NEON unconditionally enabled and, therefore, with 32 FPU
+// registers enabled as well. See section A2.6.2 on page A2-56 in
+// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
+
+pub fn target() -> Target {
+ Target {
+ // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+ // uses it to determine the calling convention and float ABI, and LLVM
+ // doesn't support the "musleabihf" value.
+ llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ // Most of these settings are copied from the thumbv7neon_unknown_linux_gnueabihf
+ // target.
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(),
+ max_atomic_width: Some(64),
+ mcount: "\u{1}mcount".into(),
+ ..super::linux_musl_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs
new file mode 100644
index 000000000..756b1834c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs
@@ -0,0 +1,21 @@
+// Targets the Cortex-M23 processor (Baseline ARMv8-M)
+
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "thumbv8m.base-none-eabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ abi: "eabi".into(),
+ // ARMv8-M baseline doesn't support unaligned loads/stores so we disable them
+ // with +strict-align.
+ features: "+strict-align".into(),
+ max_atomic_width: Some(32),
+ ..super::thumb_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs
new file mode 100644
index 000000000..4b6268546
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs
@@ -0,0 +1,19 @@
+// Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
+// without the Floating Point extension.
+
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "thumbv8m.main-none-eabi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ abi: "eabi".into(),
+ max_atomic_width: Some(32),
+ ..super::thumb_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs
new file mode 100644
index 000000000..86c25f9e4
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs
@@ -0,0 +1,25 @@
+// Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
+// with the Floating Point extension.
+
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "thumbv8m.main-none-eabihf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+ arch: "arm".into(),
+
+ options: TargetOptions {
+ abi: "eabihf".into(),
+ // If the Floating Point extension is implemented in the Cortex-M33
+ // processor, the Cortex-M33 Technical Reference Manual states that
+ // the FPU uses the FPv5 architecture, single-precision instructions
+ // and 16 D registers.
+ // These parameters map to the following LLVM features.
+ features: "+fp-armv8,-fp64,-d32".into(),
+ max_atomic_width: Some(32),
+ ..super::thumb_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/uefi_msvc_base.rs
new file mode 100644
index 000000000..aee8eb2e3
--- /dev/null
+++ b/compiler/rustc_target/src/spec/uefi_msvc_base.rs
@@ -0,0 +1,51 @@
+// This defines a base target-configuration for native UEFI systems. The UEFI specification has
+// quite detailed sections on the ABI of all the supported target architectures. In almost all
+// cases it simply follows what Microsoft Windows does. Hence, whenever in doubt, see the MSDN
+// documentation.
+// UEFI uses COFF/PE32+ format for binaries. All binaries must be statically linked. No dynamic
+// linker is supported. As native to COFF, binaries are position-dependent, but will be relocated
+// by the loader if the pre-chosen memory location is already in use.
+// UEFI forbids running code on anything but the boot-CPU. No interrupts are allowed other than
+// the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all
+// code runs in the same environment, no process separation is supported.
+
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, StackProbeType, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ let mut base = super::msvc_base::opts();
+
+ base.add_pre_link_args(
+ LinkerFlavor::Msvc,
+ &[
+ // Non-standard subsystems have no default entry-point in PE+ files. We have to define
+ // one. "efi_main" seems to be a common choice amongst other implementations and the
+ // spec.
+ "/entry:efi_main",
+ // COFF images have a "Subsystem" field in their header, which defines what kind of
+ // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION,
+ // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION,
+ // which is very likely the most common option. Individual projects can override this
+ // with custom linker flags.
+ // The subsystem-type only has minor effects on the application. It defines the memory
+ // regions the application is loaded into (runtime-drivers need to be put into
+ // reserved areas), as well as whether a return from the entry-point is treated as
+ // exit (default for applications).
+ "/subsystem:efi_application",
+ ],
+ );
+
+ TargetOptions {
+ os: "uefi".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
+ disable_redzone: true,
+ exe_suffix: ".efi".into(),
+ allows_weak_linkage: false,
+ panic_strategy: PanicStrategy::Abort,
+ // LLVM does not emit inline assembly because the LLVM target does not get considered as…
+ // "Windows".
+ stack_probes: StackProbeType::Call,
+ singlethread: true,
+ linker: Some("rust-lld".into()),
+ ..base
+ }
+}
diff --git a/compiler/rustc_target/src/spec/vxworks_base.rs b/compiler/rustc_target/src/spec/vxworks_base.rs
new file mode 100644
index 000000000..aa4784b63
--- /dev/null
+++ b/compiler/rustc_target/src/spec/vxworks_base.rs
@@ -0,0 +1,21 @@
+use crate::spec::{cvs, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "vxworks".into(),
+ env: "gnu".into(),
+ vendor: "wrs".into(),
+ linker: Some("wr-c++".into()),
+ exe_suffix: ".vxe".into(),
+ dynamic_linking: true,
+ families: cvs!["unix"],
+ has_rpath: true,
+ has_thread_local: true,
+ crt_static_default: true,
+ crt_static_respected: true,
+ crt_static_allows_dylibs: true,
+ // VxWorks needs to implement this to support profiling
+ mcount: "_mcount".into(),
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
new file mode 100644
index 000000000..c7e7d2210
--- /dev/null
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
@@ -0,0 +1,34 @@
+use super::{cvs, wasm_base};
+use super::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+ // Reset flags for non-Em flavors back to empty to satisfy sanity checking tests.
+ let pre_link_args = LinkArgs::new();
+ let post_link_args = TargetOptions::link_args(
+ LinkerFlavor::Em,
+ &["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"],
+ );
+
+ let opts = TargetOptions {
+ os: "emscripten".into(),
+ linker_flavor: LinkerFlavor::Em,
+ // emcc emits two files - a .js file to instantiate the wasm and supply platform
+ // functionality, and a .wasm file.
+ exe_suffix: ".js".into(),
+ linker: None,
+ pre_link_args,
+ post_link_args,
+ relocation_model: RelocModel::Pic,
+ panic_strategy: PanicStrategy::Unwind,
+ no_default_libraries: false,
+ families: cvs!["unix", "wasm"],
+ ..wasm_base::options()
+ };
+ Target {
+ llvm_target: "wasm32-unknown-emscripten".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20".into(),
+ arch: "wasm32".into(),
+ options: opts,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
new file mode 100644
index 000000000..4e2927dd9
--- /dev/null
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
@@ -0,0 +1,64 @@
+//! A "bare wasm" target representing a WebAssembly output that makes zero
+//! assumptions about its environment.
+//!
+//! The `wasm32-unknown-unknown` target is intended to encapsulate use cases
+//! that do not rely on any imported functionality. The binaries generated are
+//! entirely self-contained by default when using the standard library. Although
+//! the standard library is available, most of it returns an error immediately
+//! (e.g. trying to create a TCP stream or something like that).
+//!
+//! This target is more or less managed by the Rust and WebAssembly Working
+//! Group nowadays at <https://github.com/rustwasm>.
+
+use super::wasm_base;
+use super::{LinkerFlavor, LldFlavor, Target};
+use crate::spec::abi::Abi;
+
+pub fn target() -> Target {
+ let mut options = wasm_base::options();
+ options.os = "unknown".into();
+ options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
+
+ // This is a default for backwards-compatibility with the original
+ // definition of this target oh-so-long-ago. Once the "wasm" ABI is
+ // stable and the wasm-bindgen project has switched to using it then there's
+ // no need for this and it can be removed.
+ //
+ // Currently this is the reason that this target's ABI is mismatched with
+ // clang's ABI. This means that, in the limit, you can't merge C and Rust
+ // code on this target due to this ABI mismatch.
+ options.default_adjusted_cabi = Some(Abi::Wasm);
+
+ options.add_pre_link_args(
+ LinkerFlavor::Lld(LldFlavor::Wasm),
+ &[
+ // 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(
+ LinkerFlavor::Gcc,
+ &[
+ // Make sure clang uses LLD as its linker and is configured appropriately
+ // otherwise
+ "--target=wasm32-unknown-unknown",
+ "-Wl,--no-entry",
+ "-Wl,--export-dynamic",
+ ],
+ );
+
+ Target {
+ llvm_target: "wasm32-unknown-unknown".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+ arch: "wasm32".into(),
+ options,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs
new file mode 100644
index 000000000..280457d68
--- /dev/null
+++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs
@@ -0,0 +1,112 @@
+//! The `wasm32-wasi` target is a new and still (as of April 2019) an
+//! experimental target. The definition in this file is likely to be tweaked
+//! over time and shouldn't be relied on too much.
+//!
+//! The `wasi` target is a proposal to define a standardized set of syscalls
+//! that WebAssembly files can interoperate with. This set of syscalls is
+//! intended to empower WebAssembly binaries with native capabilities such as
+//! filesystem access, network access, etc.
+//!
+//! You can see more about the proposal at <https://wasi.dev>.
+//!
+//! The Rust target definition here is interesting in a few ways. We want to
+//! serve two use cases here with this target:
+//!
+//! * First, we want Rust usage of the target to be as hassle-free as possible,
+//! ideally avoiding the need to configure and install a local wasm32-wasi
+//! toolchain.
+//!
+//! * Second, one of the primary use cases of LLVM's new wasm backend and the
+//! wasm support in LLD is that any compiled language can interoperate with
+//! any other. To that the `wasm32-wasi` target is the first with a viable C
+//! standard library and sysroot common definition, so we want Rust and C/C++
+//! code to interoperate when compiled to `wasm32-unknown-unknown`.
+//!
+//! You'll note, however, that the two goals above are somewhat at odds with one
+//! another. To attempt to solve both use cases in one go we define a target
+//! that (ab)uses the `crt-static` target feature to indicate which one you're
+//! in.
+//!
+//! ## No interop with C required
+//!
+//! By default the `crt-static` target feature is enabled, and when enabled
+//! this means that the bundled version of `libc.a` found in `liblibc.rlib`
+//! is used. This isn't intended really for interoperation with a C because it
+//! may be the case that Rust's bundled C library is incompatible with a
+//! foreign-compiled C library. In this use case, though, we use `rust-lld` and
+//! some copied crt startup object files to ensure that you can download the
+//! wasi target for Rust and you're off to the races, no further configuration
+//! necessary.
+//!
+//! All in all, by default, no external dependencies are required. You can
+//! compile `wasm32-wasi` binaries straight out of the box. You can't, however,
+//! reliably interoperate with C code in this mode (yet).
+//!
+//! ## Interop with C required
+//!
+//! For the second goal we repurpose the `target-feature` flag, meaning that
+//! you'll need to do a few things to have C/Rust code interoperate.
+//!
+//! 1. All Rust code needs to be compiled with `-C target-feature=-crt-static`,
+//! indicating that the bundled C standard library in the Rust sysroot will
+//! not be used.
+//!
+//! 2. If you're using rustc to build a linked artifact then you'll need to
+//! specify `-C linker` to a `clang` binary that supports
+//! `wasm32-wasi` and is configured with the `wasm32-wasi` sysroot. This
+//! will cause Rust code to be linked against the libc.a that the specified
+//! `clang` provides.
+//!
+//! 3. If you're building a staticlib and integrating Rust code elsewhere, then
+//! compiling with `-C target-feature=-crt-static` is all you need to do.
+//!
+//! You can configure the linker via Cargo using the
+//! `CARGO_TARGET_WASM32_WASI_LINKER` env var. Be sure to also set
+//! `CC_wasm32-wasi` if any crates in the dependency graph are using the `cc`
+//! crate.
+//!
+//! ## Remember, this is all in flux
+//!
+//! The wasi target is **very** new in its specification. It's likely going to
+//! be a long effort to get it standardized and stable. We'll be following it as
+//! 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::wasm_base;
+use super::{crt_objects, LinkerFlavor, LldFlavor, Target};
+
+pub fn target() -> Target {
+ let mut options = wasm_base::options();
+
+ options.os = "wasi".into();
+ options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
+ options.add_pre_link_args(LinkerFlavor::Gcc, &["--target=wasm32-wasi"]);
+
+ options.pre_link_objects_fallback = crt_objects::pre_wasi_fallback();
+ options.post_link_objects_fallback = crt_objects::post_wasi_fallback();
+
+ // 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
+ // will be used, but this means that default usage of this target doesn't
+ // need an external compiler but it's still interoperable with an external
+ // compiler if configured correctly.
+ options.crt_static_default = true;
+ options.crt_static_respected = true;
+
+ // Allow `+crt-static` to create a "cdylib" output which is just a wasm file
+ // without a main function.
+ options.crt_static_allows_dylibs = true;
+
+ // WASI's `sys::args::init` function ignores its arguments; instead,
+ // `args::args()` makes the WASI API calls itself.
+ options.main_needs_argc_argv = false;
+
+ Target {
+ llvm_target: "wasm32-wasi".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+ arch: "wasm32".into(),
+ options,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
new file mode 100644
index 000000000..5211f7707
--- /dev/null
+++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
@@ -0,0 +1,49 @@
+//! A "bare wasm" target representing a WebAssembly output that makes zero
+//! assumptions about its environment.
+//!
+//! The `wasm64-unknown-unknown` target is intended to encapsulate use cases
+//! that do not rely on any imported functionality. The binaries generated are
+//! entirely self-contained by default when using the standard library. Although
+//! the standard library is available, most of it returns an error immediately
+//! (e.g. trying to create a TCP stream or something like that).
+
+use super::wasm_base;
+use super::{LinkerFlavor, LldFlavor, Target};
+
+pub fn target() -> Target {
+ let mut options = wasm_base::options();
+ options.os = "unknown".into();
+ options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
+
+ options.add_pre_link_args(
+ LinkerFlavor::Lld(LldFlavor::Wasm),
+ &[
+ // For now this target just never has an entry symbol no matter the output
+ // type, so unconditionally pass this.
+ "--no-entry",
+ "-mwasm64",
+ ],
+ );
+ options.add_pre_link_args(
+ LinkerFlavor::Gcc,
+ &[
+ // Make sure clang uses LLD as its linker and is configured appropriately
+ // otherwise
+ "--target=wasm64-unknown-unknown",
+ "-Wl,--no-entry",
+ ],
+ );
+
+ // Any engine that implements wasm64 will surely implement the rest of these
+ // features since they were all merged into the official spec by the time
+ // wasm64 was designed.
+ options.features = "+bulk-memory,+mutable-globals,+sign-ext,+nontrapping-fptoint".into();
+
+ Target {
+ llvm_target: "wasm64-unknown-unknown".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+ arch: "wasm64".into(),
+ options,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs
new file mode 100644
index 000000000..9216d3e7b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/wasm_base.rs
@@ -0,0 +1,129 @@
+use super::crt_objects::CrtObjectsFallback;
+use super::{cvs, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel};
+
+pub fn options() -> TargetOptions {
+ macro_rules! args {
+ ($prefix:literal) => {
+ &[
+ // By default LLD only gives us one page of stack (64k) which is a
+ // little small. Default to a larger stack closer to other PC platforms
+ // (1MB) and users can always inject their own link-args to override this.
+ concat!($prefix, "-z"),
+ concat!($prefix, "stack-size=1048576"),
+ // By default LLD's memory layout is:
+ //
+ // 1. First, a blank page
+ // 2. Next, all static data
+ // 3. Finally, the main stack (which grows down)
+ //
+ // This has the unfortunate consequence that on stack overflows you
+ // corrupt static data and can cause some exceedingly weird bugs. To
+ // help detect this a little sooner we instead request that the stack is
+ // placed before static data.
+ //
+ // This means that we'll generate slightly larger binaries as references
+ // to static data will take more bytes in the ULEB128 encoding, but
+ // stack overflow will be guaranteed to trap as it underflows instead of
+ // corrupting static data.
+ concat!($prefix, "--stack-first"),
+ // FIXME we probably shouldn't pass this but instead pass an explicit list
+ // of symbols we'll allow to be undefined. We don't currently have a
+ // mechanism of knowing, however, which symbols are intended to be imported
+ // from the environment and which are intended to be imported from other
+ // objects linked elsewhere. This is a coarse approximation but is sure to
+ // hide some bugs and frustrate someone at some point, so we should ideally
+ // work towards a world where we can explicitly list symbols that are
+ // supposed to be imported and have all other symbols generate errors if
+ // they remain undefined.
+ concat!($prefix, "--allow-undefined"),
+ // Rust code should never have warnings, and warnings are often
+ // indicative of bugs, let's prevent them.
+ concat!($prefix, "--fatal-warnings"),
+ // LLD only implements C++-like demangling, which doesn't match our own
+ // mangling scheme. Tell LLD to not demangle anything and leave it up to
+ // us to demangle these symbols later. Currently rustc does not perform
+ // further demangling, but tools like twiggy and wasm-bindgen are intended
+ // to do so.
+ concat!($prefix, "--no-demangle"),
+ ]
+ };
+ }
+
+ let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::Lld(LldFlavor::Wasm), args!(""));
+ super::add_link_args(&mut pre_link_args, LinkerFlavor::Gcc, args!("-Wl,"));
+
+ TargetOptions {
+ is_like_wasm: true,
+ families: cvs!["wasm"],
+
+ // we allow dynamic linking, but only cdylibs. Basically we allow a
+ // final library artifact that exports some symbols (a wasm module) but
+ // we don't allow intermediate `dylib` crate types
+ dynamic_linking: true,
+ only_cdylib: true,
+
+ // relatively self-explanatory!
+ exe_suffix: ".wasm".into(),
+ dll_prefix: "".into(),
+ dll_suffix: ".wasm".into(),
+ eh_frame_header: false,
+
+ max_atomic_width: Some(64),
+
+ // Unwinding doesn't work right now, so the whole target unconditionally
+ // defaults to panic=abort. Note that this is guaranteed to change in
+ // the future once unwinding is implemented. Don't rely on this as we're
+ // basically guaranteed to change it once WebAssembly supports
+ // exceptions.
+ panic_strategy: PanicStrategy::Abort,
+
+ // Wasm doesn't have atomics yet, so tell LLVM that we're in a single
+ // threaded model which will legalize atomics to normal operations.
+ singlethread: true,
+
+ // no dynamic linking, no need for default visibility!
+ default_hidden_visibility: true,
+
+ // Symbol visibility takes care of this for the WebAssembly.
+ // Additionally the only known linker, LLD, doesn't support the script
+ // arguments just yet
+ limit_rdylib_exports: false,
+
+ // we use the LLD shipped with the Rust toolchain by default
+ linker: Some("rust-lld".into()),
+ lld_flavor: LldFlavor::Wasm,
+ linker_is_gnu: false,
+
+ pre_link_args,
+
+ crt_objects_fallback: Some(CrtObjectsFallback::Wasm),
+
+ // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when
+ // PIC code is implemented this has quite a drastic effect if it stays
+ // at the default, `pic`. In an effort to keep wasm binaries as minimal
+ // as possible we're defaulting to `static` for now, but the hope is
+ // that eventually we can ship a `pic`-compatible standard library which
+ // works with `static` as well (or works with some method of generating
+ // non-relative calls and such later on).
+ relocation_model: RelocModel::Static,
+
+ // When the atomics feature is activated then these two keys matter,
+ // otherwise they're basically ignored by the standard library. In this
+ // mode, however, the `#[thread_local]` attribute works (i.e.
+ // `has_thread_local`) and we need to get it to work by specifying
+ // `local-exec` as that's all that's implemented in LLVM today for wasm.
+ has_thread_local: true,
+ tls_model: TlsModel::LocalExec,
+
+ // gdb scripts don't work on wasm blobs
+ emit_debug_gdb_scripts: false,
+
+ // There's more discussion of this at
+ // https://bugs.llvm.org/show_bug.cgi?id=52442 but the general result is
+ // that this isn't useful for wasm and has tricky issues with
+ // representation, so this is disabled.
+ generate_arange_section: false,
+
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs
new file mode 100644
index 000000000..90e0af3e3
--- /dev/null
+++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs
@@ -0,0 +1,91 @@
+use crate::spec::crt_objects::{self, CrtObjectsFallback};
+use crate::spec::{cvs, LinkerFlavor, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ let mut pre_link_args = TargetOptions::link_args(
+ LinkerFlavor::Ld,
+ &[
+ // Enable ASLR
+ "--dynamicbase",
+ // ASLR will rebase it anyway so leaving that option enabled only leads to confusion
+ "--disable-auto-image-base",
+ ],
+ );
+ super::add_link_args(
+ &mut pre_link_args,
+ LinkerFlavor::Gcc,
+ &[
+ // Tell GCC to avoid linker plugins, because we are not bundling
+ // them with Windows installer, and Rust does its own LTO anyways.
+ "-fno-use-linker-plugin",
+ "-Wl,--dynamicbase",
+ "-Wl,--disable-auto-image-base",
+ ],
+ );
+
+ // Order of `late_link_args*` was found through trial and error to work with various
+ // mingw-w64 versions (not tested on the CI). It's expected to change from time to time.
+ let mingw_libs = &[
+ "-lmsvcrt",
+ "-lmingwex",
+ "-lmingw32",
+ "-lgcc", // alas, mingw* libraries above depend on libgcc
+ // mingw's msvcrt is a weird hybrid import library and static library.
+ // And it seems that the linker fails to use import symbols from msvcrt
+ // that are required from functions in msvcrt in certain cases. For example
+ // `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
+ // The library is purposely listed twice to fix that.
+ //
+ // See https://github.com/rust-lang/rust/pull/47483 for some more details.
+ "-lmsvcrt",
+ "-luser32",
+ "-lkernel32",
+ ];
+ let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Ld, mingw_libs);
+ super::add_link_args(&mut late_link_args, LinkerFlavor::Gcc, mingw_libs);
+ // If any of our crates are dynamically linked then we need to use
+ // the shared libgcc_s-dw2-1.dll. This is required to support
+ // unwinding across DLL boundaries.
+ let dynamic_unwind_libs = &["-lgcc_s"];
+ let mut late_link_args_dynamic =
+ TargetOptions::link_args(LinkerFlavor::Ld, dynamic_unwind_libs);
+ super::add_link_args(&mut late_link_args_dynamic, LinkerFlavor::Gcc, dynamic_unwind_libs);
+ // If all of our crates are statically linked then we can get away
+ // with statically linking the libgcc unwinding code. This allows
+ // binaries to be redistributed without the libgcc_s-dw2-1.dll
+ // dependency, but unfortunately break unwinding across DLL
+ // boundaries when unwinding across FFI boundaries.
+ let static_unwind_libs = &["-lgcc_eh", "-l:libpthread.a"];
+ let mut late_link_args_static = TargetOptions::link_args(LinkerFlavor::Ld, static_unwind_libs);
+ super::add_link_args(&mut late_link_args_static, LinkerFlavor::Gcc, static_unwind_libs);
+
+ TargetOptions {
+ os: "windows".into(),
+ env: "gnu".into(),
+ vendor: "pc".into(),
+ // FIXME(#13846) this should be enabled for windows
+ function_sections: false,
+ linker: Some("gcc".into()),
+ dynamic_linking: true,
+ dll_prefix: "".into(),
+ dll_suffix: ".dll".into(),
+ exe_suffix: ".exe".into(),
+ families: cvs!["windows"],
+ is_like_windows: true,
+ allows_weak_linkage: false,
+ pre_link_args,
+ pre_link_objects: crt_objects::pre_mingw(),
+ post_link_objects: crt_objects::post_mingw(),
+ pre_link_objects_fallback: crt_objects::pre_mingw_fallback(),
+ post_link_objects_fallback: crt_objects::post_mingw_fallback(),
+ crt_objects_fallback: Some(CrtObjectsFallback::Mingw),
+ late_link_args,
+ late_link_args_dynamic,
+ late_link_args_static,
+ abi_return_struct_as_int: true,
+ emit_debug_gdb_scripts: false,
+ requires_uwtable: true,
+ eh_frame_header: false,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
new file mode 100644
index 000000000..bae007dc9
--- /dev/null
+++ b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
@@ -0,0 +1,40 @@
+use crate::spec::{cvs, LinkerFlavor, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ // We cannot use `-nodefaultlibs` because compiler-rt has to be passed
+ // as a path since it's not added to linker search path by the default.
+ // There were attemts to make it behave like libgcc (so one can just use -l<name>)
+ // but LLVM maintainers rejected it: https://reviews.llvm.org/D51440
+ let pre_link_args =
+ TargetOptions::link_args(LinkerFlavor::Gcc, &["-nolibc", "--unwindlib=none"]);
+ // Order of `late_link_args*` does not matter with LLD.
+ let late_link_args = TargetOptions::link_args(
+ LinkerFlavor::Gcc,
+ &["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"],
+ );
+
+ TargetOptions {
+ os: "windows".into(),
+ env: "gnu".into(),
+ vendor: "pc".into(),
+ abi: "llvm".into(),
+ linker: Some("clang".into()),
+ dynamic_linking: true,
+ dll_prefix: "".into(),
+ dll_suffix: ".dll".into(),
+ exe_suffix: ".exe".into(),
+ families: cvs!["windows"],
+ is_like_windows: true,
+ allows_weak_linkage: false,
+ pre_link_args,
+ late_link_args,
+ abi_return_struct_as_int: true,
+ emit_debug_gdb_scripts: false,
+ requires_uwtable: true,
+ eh_frame_header: false,
+ no_default_libraries: false,
+ has_thread_local: true,
+
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/windows_msvc_base.rs b/compiler/rustc_target/src/spec/windows_msvc_base.rs
new file mode 100644
index 000000000..21062c337
--- /dev/null
+++ b/compiler/rustc_target/src/spec/windows_msvc_base.rs
@@ -0,0 +1,34 @@
+use crate::spec::{cvs, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ let base = super::msvc_base::opts();
+
+ TargetOptions {
+ os: "windows".into(),
+ env: "msvc".into(),
+ vendor: "pc".into(),
+ dynamic_linking: true,
+ dll_prefix: "".into(),
+ dll_suffix: ".dll".into(),
+ exe_suffix: ".exe".into(),
+ staticlib_prefix: "".into(),
+ staticlib_suffix: ".lib".into(),
+ families: cvs!["windows"],
+ crt_static_allows_dylibs: true,
+ crt_static_respected: true,
+ requires_uwtable: true,
+ // Currently we don't pass the /NODEFAULTLIB flag to the linker on MSVC
+ // as there's been trouble in the past of linking the C++ standard
+ // library required by LLVM. This likely needs to happen one day, but
+ // in general Windows is also a more controlled environment than
+ // Unix, so it's not necessarily as critical that this be implemented.
+ //
+ // Note that there are also some licensing worries about statically
+ // linking some libraries which require a specific agreement, so it may
+ // not ever be possible for us to pass this flag.
+ no_default_libraries: false,
+ has_thread_local: true,
+
+ ..base
+ }
+}
diff --git a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
new file mode 100644
index 000000000..fa69b919c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
@@ -0,0 +1,34 @@
+use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ let base = super::windows_gnu_base::opts();
+
+ // FIXME: This should be updated for the exception machinery changes from #67502
+ // and inherit from `windows_gnu_base`, at least partially.
+ let mingw_libs = &[
+ "-lwinstorecompat",
+ "-lruntimeobject",
+ "-lsynchronization",
+ "-lvcruntime140_app",
+ "-lucrt",
+ "-lwindowsapp",
+ "-lmingwex",
+ "-lmingw32",
+ ];
+ let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Ld, mingw_libs);
+ super::add_link_args(&mut late_link_args, LinkerFlavor::Gcc, mingw_libs);
+ // Reset the flags back to empty until the FIXME above is addressed.
+ let late_link_args_dynamic = LinkArgs::new();
+ let late_link_args_static = LinkArgs::new();
+
+ TargetOptions {
+ abi: "uwp".into(),
+ vendor: "uwp".into(),
+ limit_rdylib_exports: false,
+ late_link_args,
+ late_link_args_dynamic,
+ late_link_args_static,
+
+ ..base
+ }
+}
diff --git a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
new file mode 100644
index 000000000..f2573fc2d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
@@ -0,0 +1,11 @@
+use crate::spec::{LinkerFlavor, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+ let mut opts = super::windows_msvc_base::opts();
+
+ opts.abi = "uwp".into();
+ opts.vendor = "uwp".into();
+ opts.add_pre_link_args(LinkerFlavor::Msvc, &["/APPCONTAINER", "mincore.lib"]);
+
+ opts
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
new file mode 100644
index 000000000..dbd26899c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
@@ -0,0 +1,30 @@
+use crate::spec::TargetOptions;
+use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::apple_base::opts("macos");
+ 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.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ base.supported_sanitizers =
+ 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 arch = "x86_64";
+ let llvm_target = super::apple_base::macos_llvm_target(&arch);
+
+ Target {
+ llvm_target: llvm_target.into(),
+ pointer_width: 64,
+ data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: arch.into(),
+ options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
new file mode 100644
index 000000000..5e64ed0cf
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
@@ -0,0 +1,21 @@
+use super::apple_sdk_base::{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");
+
+ Target {
+ llvm_target: llvm_target.into(),
+ pointer_width: 64,
+ data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: TargetOptions {
+ max_atomic_width: Some(64),
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ stack_probes: StackProbeType::Call,
+ ..base
+ },
+ }
+}
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
new file mode 100644
index 000000000..2122bcd37
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
@@ -0,0 +1,23 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{LinkerFlavor, 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);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-target", llvm_target]);
+
+ Target {
+ llvm_target: llvm_target.into(),
+ pointer_width: 64,
+ data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: TargetOptions {
+ max_atomic_width: Some(64),
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ stack_probes: StackProbeType::Call,
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
new file mode 100644
index 000000000..a848c5a0a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
@@ -0,0 +1,18 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{StackProbeType, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let base = opts("tvos", Arch::X86_64);
+ 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(),
+ options: TargetOptions {
+ max_atomic_width: Some(64),
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ stack_probes: StackProbeType::Call,
+ ..base
+ },
+ }
+}
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
new file mode 100644
index 000000000..4dff3c2f2
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs
@@ -0,0 +1,35 @@
+use super::apple_sdk_base::{opts, 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);
+
+ Target {
+ llvm_target: llvm_target.into(),
+ pointer_width: 64,
+ data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: TargetOptions {
+ max_atomic_width: Some(64),
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ stack_probes: StackProbeType::Call,
+ forces_embed_bitcode: true,
+ // Taken from a clang build on Xcode 11.4.1.
+ // These arguments are not actually invoked - they just have
+ // to look right to pass App Store validation.
+ bitcode_llvm_cmdline: "-triple\0\
+ x86_64-apple-watchos5.0-simulator\0\
+ -emit-obj\0\
+ -disable-llvm-passes\0\
+ -target-abi\0\
+ darwinpcs\0\
+ -Os\0"
+ .into(),
+ ..base
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
new file mode 100644
index 000000000..9d597ea2e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
@@ -0,0 +1,84 @@
+use std::borrow::Cow;
+
+use crate::spec::cvs;
+
+use super::{LinkerFlavor, LldFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let pre_link_args = TargetOptions::link_args(
+ LinkerFlavor::Ld,
+ &[
+ "-e",
+ "elf_entry",
+ "-Bstatic",
+ "--gc-sections",
+ "-z",
+ "text",
+ "-z",
+ "norelro",
+ "--no-undefined",
+ "--error-unresolved-symbols",
+ "--no-undefined-version",
+ "-Bsymbolic",
+ "--export-dynamic",
+ // The following symbols are needed by libunwind, which is linked after
+ // libstd. Make sure they're included in the link.
+ "-u",
+ "__rust_abort",
+ "-u",
+ "__rust_c_alloc",
+ "-u",
+ "__rust_c_dealloc",
+ "-u",
+ "__rust_print_err",
+ "-u",
+ "__rust_rwlock_rdlock",
+ "-u",
+ "__rust_rwlock_unlock",
+ "-u",
+ "__rust_rwlock_wrlock",
+ ],
+ );
+
+ const EXPORT_SYMBOLS: &[&str] = &[
+ "sgx_entry",
+ "HEAP_BASE",
+ "HEAP_SIZE",
+ "RELA",
+ "RELACOUNT",
+ "ENCLAVE_SIZE",
+ "CFGDATA_BASE",
+ "DEBUG",
+ "EH_FRM_HDR_OFFSET",
+ "EH_FRM_HDR_LEN",
+ "EH_FRM_OFFSET",
+ "EH_FRM_LEN",
+ "TEXT_BASE",
+ "TEXT_SIZE",
+ ];
+ let opts = TargetOptions {
+ os: "unknown".into(),
+ env: "sgx".into(),
+ vendor: "fortanix".into(),
+ abi: "fortanix".into(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ max_atomic_width: Some(64),
+ cpu: "x86-64".into(),
+ features: "+rdrnd,+rdseed,+lvi-cfi,+lvi-load-hardening".into(),
+ llvm_args: cvs!["--x86-experimental-lvi-inline-asm-hardening"],
+ position_independent_executables: true,
+ pre_link_args,
+ override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(Cow::from).collect()),
+ relax_elf_relocations: true,
+ ..Default::default()
+ };
+ Target {
+ llvm_target: "x86_64-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: opts,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs
new file mode 100644
index 000000000..4f88fc350
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs
@@ -0,0 +1,19 @@
+use crate::spec::{SanitizerSet, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::fuchsia_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
+
+ Target {
+ llvm_target: "x86_64-fuchsia".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/x86_64_linux_android.rs
new file mode 100644
index 000000000..6d19cf265
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_linux_android.rs
@@ -0,0 +1,21 @@
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::android_base::opts();
+ base.cpu = "x86-64".into();
+ // https://developer.android.com/ndk/guides/abis.html#86-64
+ base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "x86_64-linux-android".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 { supported_sanitizers: SanitizerSet::ADDRESS, ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
new file mode 100644
index 000000000..0550b221f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
@@ -0,0 +1,21 @@
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::solaris_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.cpu = "x86-64".into();
+ base.vendor = "pc".into();
+ base.max_atomic_width = Some(64);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
+
+ Target {
+ llvm_target: "x86_64-pc-solaris".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
new file mode 100644
index 000000000..59a8cffca
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
@@ -0,0 +1,20 @@
+use crate::spec::{LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut base = super::windows_gnu_base::opts();
+ base.cpu = "x86-64".into();
+ // Use high-entropy 64 bit address space for ASLR
+ base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]);
+ base.max_atomic_width = Some(64);
+ base.linker = Some("x86_64-w64-mingw32-gcc".into());
+
+ Target {
+ llvm_target: "x86_64-pc-windows-gnu".into(),
+ pointer_width: 64,
+ data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs
new file mode 100644
index 000000000..d3909b389
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs
@@ -0,0 +1,18 @@
+use crate::spec::{LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut base = super::windows_gnullvm_base::opts();
+ base.cpu = "x86-64".into();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.max_atomic_width = Some(64);
+ base.linker = Some("x86_64-w64-mingw32-clang".into());
+
+ Target {
+ llvm_target: "x86_64-pc-windows-gnu".into(),
+ pointer_width: 64,
+ data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs
new file mode 100644
index 000000000..081806aa6
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs
@@ -0,0 +1,16 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::windows_msvc_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "x86_64-pc-windows-msvc".into(),
+ pointer_width: 64,
+ data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
new file mode 100644
index 000000000..cbe87589a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
@@ -0,0 +1,20 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::solaris_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.cpu = "x86-64".into();
+ base.vendor = "sun".into();
+ base.max_atomic_width = Some(64);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "x86_64-pc-solaris".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
new file mode 100644
index 000000000..746f64781
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
@@ -0,0 +1,19 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::dragonfly_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "x86_64-unknown-dragonfly".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
new file mode 100644
index 000000000..b30784ed6
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
@@ -0,0 +1,21 @@
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::freebsd_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ base.supported_sanitizers =
+ SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::MEMORY | SanitizerSet::THREAD;
+
+ Target {
+ llvm_target: "x86_64-unknown-freebsd".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
new file mode 100644
index 000000000..d6d033629
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
@@ -0,0 +1,21 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::haiku_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ // This option is required to build executables on Haiku x86_64
+ base.position_independent_executables = true;
+
+ Target {
+ llvm_target: "x86_64-unknown-haiku".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
new file mode 100644
index 000000000..d31530161
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
@@ -0,0 +1,19 @@
+use crate::spec::{StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::hermit_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.features = "+rdrnd,+rdseed".into();
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "x86_64-unknown-hermit".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
new file mode 100644
index 000000000..9f19c3a2b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
@@ -0,0 +1,20 @@
+use crate::spec::{LinkerFlavor, SanitizerSet, Target};
+
+pub fn target() -> Target {
+ let mut base = super::illumos_base::opts();
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-std=c99"]);
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
+
+ Target {
+ // LLVM does not currently have a separate illumos target,
+ // so we still pass Solaris to it
+ llvm_target: "x86_64-pc-solaris".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs
new file mode 100644
index 000000000..78189a0c0
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs
@@ -0,0 +1,19 @@
+use crate::spec::{PanicStrategy, Target};
+
+pub fn target() -> Target {
+ let mut base = super::l4re_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.crt_static_allows_dylibs = false;
+ base.dynamic_linking = false;
+ base.panic_strategy = PanicStrategy::Abort;
+
+ Target {
+ llvm_target: "x86_64-unknown-l4re-uclibc".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
new file mode 100644
index 000000000..956be0353
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
@@ -0,0 +1,25 @@
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ base.static_position_independent_executables = true;
+ base.supported_sanitizers = SanitizerSet::ADDRESS
+ | SanitizerSet::CFI
+ | SanitizerSet::LEAK
+ | SanitizerSet::MEMORY
+ | SanitizerSet::THREAD;
+
+ Target {
+ llvm_target: "x86_64-unknown-linux-gnu".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
new file mode 100644
index 000000000..140882747
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
@@ -0,0 +1,25 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::linux_gnu_base::opts();
+ base.cpu = "x86-64".into();
+ base.abi = "x32".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-mx32"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ base.has_thread_local = false;
+ // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
+ // breaks code gen. See LLVM bug 36743
+ base.needs_plt = true;
+
+ Target {
+ llvm_target: "x86_64-unknown-linux-gnux32".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+ i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
new file mode 100644
index 000000000..87e7784d1
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
@@ -0,0 +1,25 @@
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::linux_musl_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ base.static_position_independent_executables = true;
+ base.supported_sanitizers = SanitizerSet::ADDRESS
+ | SanitizerSet::CFI
+ | SanitizerSet::LEAK
+ | SanitizerSet::MEMORY
+ | SanitizerSet::THREAD;
+
+ Target {
+ llvm_target: "x86_64-unknown-linux-musl".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
new file mode 100644
index 000000000..d3a67619a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
@@ -0,0 +1,24 @@
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::netbsd_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ base.supported_sanitizers = SanitizerSet::ADDRESS
+ | SanitizerSet::CFI
+ | SanitizerSet::LEAK
+ | SanitizerSet::MEMORY
+ | SanitizerSet::THREAD;
+
+ Target {
+ llvm_target: "x86_64-unknown-netbsd".into(),
+ pointer_width: 64,
+ data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: TargetOptions { mcount: "__mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
new file mode 100644
index 000000000..809fd642d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
@@ -0,0 +1,40 @@
+// Generic x86-64 target for bare-metal code - Floating point disabled
+//
+// Can be used in conjunction with the `target-feature` and
+// `target-cpu` compiler flags to opt-in more hardware-specific
+// features.
+
+use super::{
+ CodeModel, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, RelroLevel, StackProbeType,
+ Target, TargetOptions,
+};
+
+pub fn target() -> Target {
+ let opts = TargetOptions {
+ cpu: "x86-64".into(),
+ max_atomic_width: Some(64),
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ stack_probes: StackProbeType::Call,
+ position_independent_executables: true,
+ static_position_independent_executables: true,
+ relro_level: RelroLevel::Full,
+ relocation_model: RelocModel::Pic,
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".into()),
+ features:
+ "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
+ .into(),
+ disable_redzone: true,
+ panic_strategy: PanicStrategy::Abort,
+ code_model: Some(CodeModel::Kernel),
+ ..Default::default()
+ };
+ Target {
+ 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: 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
new file mode 100644
index 000000000..593345a5f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
@@ -0,0 +1,28 @@
+// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for
+// generic Linux kernel options.
+
+use crate::spec::{CodeModel, LinkerFlavor, 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::Gcc, &["-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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
new file mode 100644
index 000000000..f50c6bcee
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
@@ -0,0 +1,19 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::openbsd_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "x86_64-unknown-openbsd".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
new file mode 100644
index 000000000..668ae9054
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
@@ -0,0 +1,19 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::redox_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+
+ Target {
+ llvm_target: "x86_64-unknown-redox".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,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
new file mode 100644
index 000000000..a7ae17839
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs
@@ -0,0 +1,36 @@
+// This defines the amd64 target for UEFI systems as described in the UEFI specification. See the
+// uefi-base module for generic UEFI options. On x86_64 systems (mostly called "x64" in the spec)
+// UEFI systems always run in long-mode, have the interrupt-controller pre-configured and force a
+// single-CPU execution.
+// 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;
+
+pub fn target() -> Target {
+ let mut base = super::uefi_msvc_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+
+ // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
+ // enable these CPU features explicitly before their first use, otherwise their instructions
+ // will trigger an exception. Rust does not inject any code that enables AVX/MMX/SSE
+ // instruction sets, so this must be done by the firmware. However, existing firmware is known
+ // to leave these uninitialized, thus triggering exceptions if we make use of them. Which is
+ // why we avoid them and instead use soft-floats. This is also what GRUB and friends did so
+ // far.
+ //
+ // If you initialize FP units yourself, you can override these flags with custom linker
+ // arguments, thus giving you access to full MMX/SSE acceleration.
+ base.features = "-mmx,-sse,+soft-float".into();
+
+ Target {
+ llvm_target: "x86_64-unknown-windows".into(),
+ pointer_width: 64,
+ data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
new file mode 100644
index 000000000..76d2013cf
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
@@ -0,0 +1,19 @@
+use crate::spec::{LinkerFlavor, Target};
+
+pub fn target() -> Target {
+ let mut base = super::windows_uwp_gnu_base::opts();
+ base.cpu = "x86-64".into();
+ // Use high-entropy 64 bit address space for ASLR
+ base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]);
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "x86_64-pc-windows-gnu".into(),
+ pointer_width: 64,
+ data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs
new file mode 100644
index 000000000..b2769350b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs
@@ -0,0 +1,16 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+ let mut base = super::windows_uwp_msvc_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+
+ Target {
+ llvm_target: "x86_64-pc-windows-msvc".into(),
+ pointer_width: 64,
+ data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: "x86_64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
new file mode 100644
index 000000000..129897495
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
@@ -0,0 +1,20 @@
+use crate::spec::{LinkerFlavor, StackProbeType, Target};
+
+pub fn target() -> Target {
+ let mut base = super::vxworks_base::opts();
+ base.cpu = "x86-64".into();
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ base.stack_probes = StackProbeType::Call;
+ base.disable_redzone = true;
+
+ Target {
+ llvm_target: "x86_64-unknown-linux-gnu".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,
+ }
+}