rustc_target: Add some more target spec sanity checking

This commit is contained in:
Vadim Petrochenkov 2022-06-28 12:40:39 +03:00
parent 4065b89b1e
commit 2e83c22154
5 changed files with 60 additions and 17 deletions

View File

@ -1,4 +1,4 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, RelocModel, Target, TargetOptions};
/// A base target for AVR devices using the GNU toolchain. /// A base target for AVR devices using the GNU toolchain.
/// ///
@ -21,6 +21,7 @@ pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
late_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &["-lgcc"]), late_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &["-lgcc"]),
max_atomic_width: Some(0), max_atomic_width: Some(0),
atomic_cas: false, atomic_cas: false,
relocation_model: RelocModel::Static,
..TargetOptions::default() ..TargetOptions::default()
}, },
} }

View File

@ -1,4 +1,4 @@
use crate::spec::{cvs, LinkerFlavor, PanicStrategy, TargetOptions}; use crate::spec::{cvs, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions};
pub fn opts() -> TargetOptions { pub fn opts() -> TargetOptions {
TargetOptions { TargetOptions {
@ -9,6 +9,7 @@ pub fn opts() -> TargetOptions {
linker: Some("l4-bender".into()), linker: Some("l4-bender".into()),
linker_is_gnu: false, linker_is_gnu: false,
families: cvs!["unix"], families: cvs!["unix"],
relocation_model: RelocModel::Static,
..Default::default() ..Default::default()
} }
} }

View File

@ -837,15 +837,15 @@ impl fmt::Display for StackProtector {
} }
macro_rules! supported_targets { macro_rules! supported_targets {
( $(($( $triple:literal, )+ $module:ident ),)+ ) => { ( $(($triple:literal, $module:ident ),)+ ) => {
$(mod $module;)+ $(mod $module;)+
/// List of supported targets /// List of supported targets
pub const TARGETS: &[&str] = &[$($($triple),+),+]; pub const TARGETS: &[&str] = &[$($triple),+];
fn load_builtin(target: &str) -> Option<Target> { fn load_builtin(target: &str) -> Option<Target> {
let mut t = match target { let mut t = match target {
$( $($triple)|+ => $module::target(), )+ $( $triple => $module::target(), )+
_ => return None, _ => return None,
}; };
t.is_builtin = true; t.is_builtin = true;
@ -861,7 +861,7 @@ macro_rules! supported_targets {
$( $(
#[test] // `#[test]` #[test] // `#[test]`
fn $module() { fn $module() {
tests_impl::test_target(super::$module::target()); tests_impl::test_target(super::$module::target(), $triple);
} }
)+ )+
} }

View File

@ -2,18 +2,20 @@ use super::super::*;
use std::assert_matches::assert_matches; use std::assert_matches::assert_matches;
// Test target self-consistency and JSON encoding/decoding roundtrip. // Test target self-consistency and JSON encoding/decoding roundtrip.
pub(super) fn test_target(target: Target) { pub(super) fn test_target(target: Target, triple: &str) {
target.check_consistency(); target.check_consistency(triple);
assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target)); assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target));
} }
impl Target { impl Target {
fn check_consistency(&self) { fn check_consistency(&self, triple: &str) {
assert_eq!(self.is_like_osx, self.vendor == "apple"); 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_solaris, self.os == "solaris" || self.os == "illumos");
assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi"); 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_eq!(self.is_like_wasm, self.arch == "wasm32" || self.arch == "wasm64");
assert!(self.is_like_windows || !self.is_like_msvc); if self.is_like_msvc {
assert!(self.is_like_windows);
}
// Check that default linker flavor and lld flavor are compatible // Check that default linker flavor and lld flavor are compatible
// with some other key properties. // with some other key properties.
@ -94,8 +96,9 @@ impl Target {
check_noncc(LinkerFlavor::Ld); check_noncc(LinkerFlavor::Ld);
check_noncc(LinkerFlavor::Lld(LldFlavor::Ld)); check_noncc(LinkerFlavor::Lld(LldFlavor::Ld));
} }
LldFlavor::Ld64 => check_noncc(LinkerFlavor::Lld(LldFlavor::Ld64)),
LldFlavor::Wasm => check_noncc(LinkerFlavor::Lld(LldFlavor::Wasm)), LldFlavor::Wasm => check_noncc(LinkerFlavor::Lld(LldFlavor::Wasm)),
LldFlavor::Ld64 | LldFlavor::Link => {} LldFlavor::Link => {}
}, },
_ => {} _ => {}
} }
@ -109,20 +112,56 @@ impl Target {
); );
} }
assert!( if self.link_self_contained == LinkSelfContainedDefault::False {
(self.pre_link_objects_self_contained.is_empty() assert!(
&& self.post_link_objects_self_contained.is_empty()) self.pre_link_objects_self_contained.is_empty()
|| self.link_self_contained != LinkSelfContainedDefault::False && self.post_link_objects_self_contained.is_empty()
); );
}
// If your target really needs to deviate from the rules below, // If your target really needs to deviate from the rules below,
// except it and document the reasons. // except it and document the reasons.
// Keep the default "unknown" vendor instead. // Keep the default "unknown" vendor instead.
assert_ne!(self.vendor, ""); assert_ne!(self.vendor, "");
assert_ne!(self.os, "");
if !self.can_use_os_unknown() { if !self.can_use_os_unknown() {
// Keep the default "none" for bare metal targets instead. // Keep the default "none" for bare metal targets instead.
assert_ne!(self.os, "unknown"); assert_ne!(self.os, "unknown");
} }
// Check dynamic linking stuff
// BPF: when targeting user space vms (like rbpf), those can load dynamic libraries.
if self.os == "none" && self.arch != "bpf" {
assert!(!self.dynamic_linking);
}
if self.only_cdylib
|| self.crt_static_allows_dylibs
|| !self.late_link_args_dynamic.is_empty()
{
assert!(self.dynamic_linking);
}
// Apparently PIC was slow on wasm at some point, see comments in wasm_base.rs
if self.dynamic_linking && !(self.is_like_wasm && self.os != "emscripten") {
assert_eq!(self.relocation_model, RelocModel::Pic);
}
// PIEs are supported but not enabled by default with linuxkernel target.
if self.position_independent_executables && !triple.ends_with("-linuxkernel") {
assert_eq!(self.relocation_model, RelocModel::Pic);
}
if self.relocation_model == RelocModel::Pic {
assert!(self.dynamic_linking || self.position_independent_executables);
}
if self.static_position_independent_executables {
assert!(self.position_independent_executables);
}
if self.position_independent_executables {
assert!(self.executables);
}
// Check crt static stuff
if self.crt_static_default || self.crt_static_allows_dylibs {
assert!(self.crt_static_respected);
}
} }
// Add your target to the whitelist if it has `std` library // Add your target to the whitelist if it has `std` library

View File

@ -9,7 +9,8 @@
// the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all // 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. // code runs in the same environment, no process separation is supported.
use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, StackProbeType, TargetOptions}; use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy};
use crate::spec::{RelocModel, StackProbeType, TargetOptions};
pub fn opts() -> TargetOptions { pub fn opts() -> TargetOptions {
let mut base = super::msvc_base::opts(); let mut base = super::msvc_base::opts();
@ -46,6 +47,7 @@ pub fn opts() -> TargetOptions {
stack_probes: StackProbeType::Call, stack_probes: StackProbeType::Call,
singlethread: true, singlethread: true,
linker: Some("rust-lld".into()), linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
..base ..base
} }
} }