Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_target: Refactor target specifications related to Windows and UEFI #71030

Merged
merged 9 commits into from
Apr 15, 2020
15 changes: 6 additions & 9 deletions src/librustc_codegen_ssa/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_session::search_paths::PathKind;
/// need out of the shared crate context before we get rid of it.
use rustc_session::{filesearch, Session};
use rustc_span::symbol::Symbol;
use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
use rustc_target::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelroLevel};

use super::archive::ArchiveBuilder;
use super::command::Command;
Expand Down Expand Up @@ -182,7 +182,9 @@ fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> Command {
// To comply with the Windows App Certification Kit,
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
let t = &sess.target.target;
if flavor == LinkerFlavor::Msvc && t.target_vendor == "uwp" {
if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
&& t.target_vendor == "uwp"
{
if let Some(ref tool) = msvc_tool {
let original_path = tool.path();
if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
Expand Down Expand Up @@ -1530,13 +1532,8 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
cmd.debuginfo();

// OBJECT-FILES-NO, AUDIT-ORDER
// We want to, by default, prevent the compiler from accidentally leaking in
// any system libraries, so we may explicitly ask linkers to not link to any
// libraries by default. Note that this does not happen for windows because
// windows pulls in some large number of libraries and I couldn't quite
// figure out which subset we wanted.
//
// This is all naturally configurable via the standard methods as well.
// We want to prevent the compiler from accidentally leaking in any system libraries,
// so by default we tell linkers not to link to any default libraries.
if !sess.opts.cg.default_linker_libraries.unwrap_or(false)
&& sess.target.target.options.no_default_libraries
{
Expand Down
10 changes: 1 addition & 9 deletions src/librustc_codegen_ssa/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -631,15 +631,7 @@ impl<'a> Linker for MsvcLinker<'a> {
}

fn no_default_libraries(&mut self) {
// 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.
self.cmd.arg("/NODEFAULTLIB");
}

fn include_path(&mut self, path: &Path) {
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/armebv7r_none_eabi.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Targets the Big endian Cortex-R4/R5 processor (ARMv7-R)

use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
use std::default::Default;

pub fn target() -> TargetResult {
Ok(Target {
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/armebv7r_none_eabihf.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Targets the Cortex-R4F/R5F processor (ARMv7-R)

use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
use std::default::Default;

pub fn target() -> TargetResult {
Ok(Target {
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/armv7r_none_eabi.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R)

use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
use std::default::Default;

pub fn target() -> TargetResult {
Ok(Target {
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/armv7r_none_eabihf.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R)

use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
use std::default::Default;

pub fn target() -> TargetResult {
Ok(Target {
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/dragonfly_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/freebsd_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/fuchsia_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut pre_link_args = LinkArgs::new();
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/haiku_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{RelroLevel, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
TargetOptions {
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/hermit_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut pre_link_args = LinkArgs::new();
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/hermit_kernel_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut pre_link_args = LinkArgs::new();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_target/spec/i686_pc_windows_gnu.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::spec::{LinkerFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
let mut base = super::windows_base::opts();
let mut base = super::windows_gnu_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
base.eliminate_frame_pointer = false; // Required for backtraces
Expand Down
24 changes: 15 additions & 9 deletions src/librustc_target/spec/i686_pc_windows_msvc.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
use crate::spec::{LinkerFlavor, Target, TargetResult};
use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
let mut base = super::windows_msvc_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);

// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
// space available to x86 Windows binaries on x86_64.
base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push("/LARGEADDRESSAWARE".to_string());

// 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
base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push("/SAFESEH".to_string());
let pre_link_args_msvc = vec![
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
// space available to x86 Windows binaries on x86_64.
"/LARGEADDRESSAWARE".to_string(),
// 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".to_string(),
];
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);

Ok(Target {
llvm_target: "i686-pc-windows-msvc".to_string(),
Expand Down
7 changes: 1 addition & 6 deletions src/librustc_target/spec/i686_unknown_uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
let mut base = super::uefi_base::opts();
let mut base = super::uefi_msvc_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);

Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_target/spec/i686_uwp_windows_gnu.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::spec::{LinkerFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
let mut base = super::windows_uwp_base::opts();
let mut base = super::windows_uwp_gnu_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
base.eliminate_frame_pointer = false; // Required for backtraces
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/l4re_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions};
use std::default::Default;
//use std::process::Command;

// Use GCC to locate code for crt* libraries from the host, not from L4Re. Note
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/linux_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/linux_kernel_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelroLevel, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut pre_link_args = LinkArgs::new();
Expand Down
33 changes: 13 additions & 20 deletions src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
use crate::spec::abi::{lookup as lookup_abi, Abi};
use rustc_serialize::json::{Json, ToJson};
use std::collections::BTreeMap;
use std::default::Default;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::{fmt, io};
Expand All @@ -60,18 +59,19 @@ 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;
mod riscv_base;
mod solaris_base;
mod thumb_base;
mod uefi_base;
mod uefi_msvc_base;
mod vxworks_base;
mod wasm32_base;
mod windows_base;
mod windows_gnu_base;
mod windows_msvc_base;
mod windows_uwp_base;
mod windows_uwp_gnu_base;
mod windows_uwp_msvc_base;

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
Expand Down Expand Up @@ -309,23 +309,14 @@ macro_rules! supported_targets {
}

#[cfg(test)]
mod test_json_encode_decode {
use rustc_serialize::json::ToJson;
use super::Target;
$(use super::$module;)+
mod tests {
mod tests_impl;

// Cannot put this into a separate file without duplication, make an exception.
$(
#[test] // `#[test]` - this is hard to put into a separate file, make an exception
#[test] // `#[test]`
fn $module() {
// Grab the TargetResult struct. If we successfully retrieved
// a Target, then the test JSON encoding/decoding can run for this
// Target on this testing platform (i.e., checking the iOS targets
// only on a Mac test platform).
let _ = $module::target().map(|original| {
let as_json = original.to_json();
let parsed = Target::from_json(as_json).unwrap();
assert_eq!(original, parsed);
});
tests_impl::test_target(super::$module::target());
}
)+
}
Expand Down Expand Up @@ -538,7 +529,8 @@ pub struct Target {
pub arch: String,
/// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
pub data_layout: String,
/// Linker flavor
/// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
/// on the command line.
pub linker_flavor: LinkerFlavor,
/// Optional settings with defaults.
pub options: TargetOptions,
Expand Down Expand Up @@ -566,7 +558,8 @@ pub struct TargetOptions {
/// Linker to invoke
pub linker: Option<String>,

/// LLD flavor
/// 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.
Expand Down
35 changes: 35 additions & 0 deletions src/librustc_target/spec/msvc_base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
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,
abi_return_struct_as_int: true,
petrochenkov marked this conversation as resolved.
Show resolved Hide resolved
emit_debug_gdb_scripts: false,

..Default::default()
}
}
1 change: 0 additions & 1 deletion src/librustc_target/spec/netbsd_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/openbsd_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/redox_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
Expand Down
1 change: 0 additions & 1 deletion src/librustc_target/spec/solaris_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::spec::TargetOptions;
use std::default::Default;

pub fn opts() -> TargetOptions {
TargetOptions {
Expand Down
43 changes: 43 additions & 0 deletions src/librustc_target/spec/tests/tests_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use super::super::*;

pub(super) fn test_target(target: TargetResult) {
// Grab the TargetResult struct. If we successfully retrieved
// a Target, then the test JSON encoding/decoding can run for this
// Target on this testing platform (i.e., checking the iOS targets
// only on a Mac test platform).
if let Ok(original) = target {
original.check_consistency();
let as_json = original.to_json();
let parsed = Target::from_json(as_json).unwrap();
assert_eq!(original, parsed);
}
}

impl Target {
fn check_consistency(&self) {
// Check that LLD with the given flavor is treated identically to the linker it emulates.
// If you target really needs to deviate from the rules below, whitelist it
// and document the reasons.
assert_eq!(
self.linker_flavor == LinkerFlavor::Msvc
|| self.linker_flavor == LinkerFlavor::Lld(LldFlavor::Link),
self.options.lld_flavor == LldFlavor::Link,
);
for args in &[
&self.options.pre_link_args,
&self.options.pre_link_args_crt,
&self.options.late_link_args,
&self.options.late_link_args_dynamic,
&self.options.late_link_args_static,
&self.options.post_link_args,
] {
assert_eq!(
args.get(&LinkerFlavor::Msvc),
args.get(&LinkerFlavor::Lld(LldFlavor::Link)),
);
if args.contains_key(&LinkerFlavor::Msvc) {
assert_eq!(self.options.lld_flavor, LldFlavor::Link);
}
}
}
}
Loading