From 57870ea2ca2f9795e875d55d60df57d47e4a3eba Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 11 Apr 2020 17:30:09 +0300 Subject: [PATCH] rustc_target: Introduce `msvc_base` and inherit both `windows_msvc_base` and `uefi_msvc_base` from it. --- src/librustc_target/spec/i686_unknown_uefi.rs | 5 --- src/librustc_target/spec/mod.rs | 1 + src/librustc_target/spec/msvc_base.rs | 38 +++++++++++++++++++ src/librustc_target/spec/uefi_msvc_base.rs | 37 +++++++++--------- src/librustc_target/spec/windows_msvc_base.rs | 21 ++-------- .../spec/x86_64_unknown_uefi.rs | 5 --- 6 files changed, 59 insertions(+), 48 deletions(-) create mode 100644 src/librustc_target/spec/msvc_base.rs diff --git a/src/librustc_target/spec/i686_unknown_uefi.rs b/src/librustc_target/spec/i686_unknown_uefi.rs index bf3064f437ff..221d5f0785cd 100644 --- a/src/librustc_target/spec/i686_unknown_uefi.rs +++ b/src/librustc_target/spec/i686_unknown_uefi.rs @@ -23,11 +23,6 @@ pub fn target() -> TargetResult { // arguments, thus giving you access to full MMX/SSE acceleration. base.features = "-mmx,-sse,+soft-float".to_string(); - // UEFI mirrors the calling-conventions used on windows. In case of i686 this means small - // structs will be returned as int. This shouldn't matter much, since the restrictions placed - // by the UEFI specifications forbid any ABI to return structures. - base.abi_return_struct_as_int = true; - // Use -GNU here, because of the reason below: // Background and Problem: // If we use i686-unknown-windows, the LLVM IA32 MSVC generates compiler intrinsic diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index d0129b2cdd37..6ff812754aa7 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -59,6 +59,7 @@ mod l4re_base; mod linux_base; mod linux_kernel_base; mod linux_musl_base; +mod msvc_base; mod netbsd_base; mod openbsd_base; mod redox_base; diff --git a/src/librustc_target/spec/msvc_base.rs b/src/librustc_target/spec/msvc_base.rs new file mode 100644 index 000000000000..4d921b5d5fe1 --- /dev/null +++ b/src/librustc_target/spec/msvc_base.rs @@ -0,0 +1,38 @@ +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions}; + +pub fn opts() -> TargetOptions { + let pre_link_args_msvc = vec![ + // Suppress the verbose logo and authorship debugging output, which would needlessly + // clog any log files. + "/NOLOGO".to_string(), + // Tell the compiler that non-code sections can be marked as non-executable, + // including stack pages. + // UEFI is fully compatible to non-executable data pages. + // In fact, firmware might enforce this, so we better let the linker know about this, + // so it will fail if the compiler ever tries placing code on the stack + // (e.g., trampoline constructs and alike). + "/NXCOMPAT".to_string(), + ]; + let mut pre_link_args = LinkArgs::new(); + pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone()); + pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), pre_link_args_msvc); + + TargetOptions { + executables: true, + is_like_windows: true, + is_like_msvc: true, + // set VSLANG to 1033 can prevent link.exe from using + // language packs, and avoid generating Non-UTF-8 error + // messages if a link error occurred. + link_env: vec![("VSLANG".to_string(), "1033".to_string())], + lld_flavor: LldFlavor::Link, + pre_link_args, + // UEFI mirrors the calling-conventions used on windows. In case of x86-64 and i686 this + // means small structs will be returned as int. This shouldn't matter much, since the + // restrictions placed by the UEFI specifications forbid any ABI to return structures. + abi_return_struct_as_int: true, + emit_debug_gdb_scripts: false, + + ..Default::default() + } +} diff --git a/src/librustc_target/spec/uefi_msvc_base.rs b/src/librustc_target/spec/uefi_msvc_base.rs index 148658f4abb9..3f7c78c8e7d4 100644 --- a/src/librustc_target/spec/uefi_msvc_base.rs +++ b/src/librustc_target/spec/uefi_msvc_base.rs @@ -9,19 +9,12 @@ // 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::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions}; +use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions}; pub fn opts() -> TargetOptions { + let mut base = super::msvc_base::opts(); + let pre_link_args_msvc = vec![ - // Suppress the verbose logo and authorship debugging output, which would needlessly - // clog any log files. - "/NOLOGO".to_string(), - // UEFI is fully compatible to non-executable data pages. Tell the compiler that - // non-code sections can be marked as non-executable, including stack pages. In fact, - // firmware might enforce this, so we better let the linker know about this, so it - // will fail if the compiler ever tries placing code on the stack (e.g., trampoline - // constructs and alike). - "/NXCOMPAT".to_string(), // 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. @@ -37,25 +30,29 @@ pub fn opts() -> TargetOptions { // exit (default for applications). "/subsystem:efi_application".to_string(), ]; - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone()); - pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), pre_link_args_msvc); + base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone()); + base.pre_link_args + .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) + .unwrap() + .extend(pre_link_args_msvc); TargetOptions { - dynamic_linking: false, - executables: true, disable_redzone: true, exe_suffix: ".efi".to_string(), allows_weak_linkage: false, panic_strategy: PanicStrategy::Abort, stack_probes: true, singlethread: true, - emit_debug_gdb_scripts: false, - linker: Some("rust-lld".to_string()), - lld_flavor: LldFlavor::Link, - pre_link_args, + // FIXME: This should likely be `true` inherited from `msvc_base` + // because UEFI follows Windows ABI and uses PE/COFF. + // The `false` is probably causing ABI bugs right now. + is_like_windows: false, + // FIXME: This should likely be `true` inherited from `msvc_base` + // because UEFI follows Windows ABI and uses PE/COFF. + // The `false` is probably causing ABI bugs right now. + is_like_msvc: false, - ..Default::default() + ..base } } diff --git a/src/librustc_target/spec/windows_msvc_base.rs b/src/librustc_target/spec/windows_msvc_base.rs index 328cdec5492e..77171f8672e8 100644 --- a/src/librustc_target/spec/windows_msvc_base.rs +++ b/src/librustc_target/spec/windows_msvc_base.rs @@ -1,33 +1,18 @@ -use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions}; +use crate::spec::TargetOptions; pub fn opts() -> TargetOptions { - let pre_link_args_msvc = vec!["/NOLOGO".to_string(), "/NXCOMPAT".to_string()]; - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone()); - pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), pre_link_args_msvc); + let base = super::msvc_base::opts(); TargetOptions { - function_sections: true, dynamic_linking: true, - executables: true, dll_prefix: String::new(), dll_suffix: ".dll".to_string(), exe_suffix: ".exe".to_string(), staticlib_prefix: String::new(), staticlib_suffix: ".lib".to_string(), target_family: Some("windows".to_string()), - is_like_windows: true, - is_like_msvc: true, - // set VSLANG to 1033 can prevent link.exe from using - // language packs, and avoid generating Non-UTF-8 error - // messages if a link error occurred. - link_env: vec![("VSLANG".to_string(), "1033".to_string())], - lld_flavor: LldFlavor::Link, - pre_link_args, crt_static_allows_dylibs: true, crt_static_respected: true, - abi_return_struct_as_int: true, - emit_debug_gdb_scripts: false, 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 @@ -40,6 +25,6 @@ pub fn opts() -> TargetOptions { // not ever be possible for us to pass this flag. no_default_libraries: false, - ..Default::default() + ..base } } diff --git a/src/librustc_target/spec/x86_64_unknown_uefi.rs b/src/librustc_target/spec/x86_64_unknown_uefi.rs index 588de409d451..12edc29330a4 100644 --- a/src/librustc_target/spec/x86_64_unknown_uefi.rs +++ b/src/librustc_target/spec/x86_64_unknown_uefi.rs @@ -28,11 +28,6 @@ pub fn target() -> TargetResult { // places no locality-restrictions, so it fits well here. base.code_model = Some("large".to_string()); - // UEFI mirrors the calling-conventions used on windows. In case of x86-64 this means small - // structs will be returned as int. This shouldn't matter much, since the restrictions placed - // by the UEFI specifications forbid any ABI to return structures. - base.abi_return_struct_as_int = true; - Ok(Target { llvm_target: "x86_64-unknown-windows".to_string(), target_endian: "little".to_string(),