X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_target%2Fspec%2Fmod.rs;h=e853c07632f9043fb744750373580bca2e9e620c;hb=75561a56ac57c47762b5ddddf7bb2e6798d98e7c;hp=8f3097ad4233eb6796c072c28d6fbfbc2b24671c;hpb=4d11c3fe3065042c946cdb7e775ed999ab6f0031;p=rust.git diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 8f3097ad423..e853c07632f 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -265,6 +265,82 @@ fn to_json(&self) -> Json { } } +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum RelocModel { + Static, + Pic, + DynamicNoPic, + Ropi, + Rwpi, + RopiRwpi, +} + +impl FromStr for RelocModel { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(match s { + "static" => RelocModel::Static, + "pic" => RelocModel::Pic, + "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::DynamicNoPic => "dynamic-no-pic", + RelocModel::Ropi => "ropi", + RelocModel::Rwpi => "rwpi", + RelocModel::RopiRwpi => "ropi-rwpi", + } + .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 { + 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() + } +} + pub enum LoadTargetError { BuiltinTargetNotFound(String), Other(String), @@ -614,13 +690,13 @@ pub struct TargetOptions { /// libraries. Defaults to false. pub executables: bool, /// Relocation model to use in object file. Corresponds to `llc - /// -relocation-model=$relocation_model`. Defaults to "pic". - pub relocation_model: String, + /// -relocation-model=$relocation_model`. Defaults to `Pic`. + pub relocation_model: RelocModel, /// Code model to use. Corresponds to `llc -code-model=$code_model`. pub code_model: Option, /// 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: String, + 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, /// Eliminate frame pointers from stack frames if possible. Defaults to true. @@ -821,9 +897,9 @@ fn default() -> TargetOptions { dynamic_linking: false, only_cdylib: false, executables: false, - relocation_model: "pic".to_string(), + relocation_model: RelocModel::Pic, code_model: None, - tls_model: "global-dynamic".to_string(), + tls_model: TlsModel::GeneralDynamic, disable_redzone: false, eliminate_frame_pointer: true, function_sections: true, @@ -979,20 +1055,21 @@ pub fn from_json(obj: Json) -> TargetResult { macro_rules! key { ($key_name:ident) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).map(|o| o.as_string() - .map(|s| base.options.$key_name = s.to_string())); + if let Some(s) = obj.find(&name).and_then(Json::as_string) { + base.options.$key_name = s.to_string(); + } } ); ($key_name:ident, bool) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]) - .map(|o| o.as_boolean() - .map(|s| base.options.$key_name = s)); + if let Some(s) = obj.find(&name).and_then(Json::as_boolean) { + base.options.$key_name = s; + } } ); ($key_name:ident, Option) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]) - .map(|o| o.as_u64() - .map(|s| base.options.$key_name = Some(s))); + if let Some(s) = obj.find(&name).and_then(Json::as_u64) { + base.options.$key_name = Some(s); + } } ); ($key_name:ident, MergeFunctions) => ( { let name = (stringify!($key_name)).replace("_", "-"); @@ -1007,6 +1084,30 @@ macro_rules! key { Some(Ok(())) })).unwrap_or(Ok(())) } ); + ($key_name:ident, RelocModel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + match s.parse::() { + Ok(relocation_model) => base.options.$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, TlsModel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + match s.parse::() { + Ok(tls_model) => base.options.$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.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { @@ -1034,19 +1135,19 @@ macro_rules! key { } ); ($key_name:ident, list) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).map(|o| o.as_array() - .map(|v| base.options.$key_name = v.iter() - .map(|a| a.as_string().unwrap().to_string()).collect() - ) - ); + if let Some(v) = obj.find(&name).and_then(Json::as_array) { + base.options.$key_name = v.iter() + .map(|a| a.as_string().unwrap().to_string()) + .collect(); + } } ); ($key_name:ident, opt_list) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).map(|o| o.as_array() - .map(|v| base.options.$key_name = Some(v.iter() - .map(|a| a.as_string().unwrap().to_string()).collect()) - ) - ); + if let Some(v) = obj.find(&name).and_then(Json::as_array) { + base.options.$key_name = Some(v.iter() + .map(|a| a.as_string().unwrap().to_string()) + .collect()); + } } ); ($key_name:ident, optional) => ( { let name = (stringify!($key_name)).replace("_", "-"); @@ -1145,9 +1246,9 @@ macro_rules! key { key!(dynamic_linking, bool); key!(only_cdylib, bool); key!(executables, bool); - key!(relocation_model); + key!(relocation_model, RelocModel)?; key!(code_model, optional); - key!(tls_model); + key!(tls_model, TlsModel)?; key!(disable_redzone, bool); key!(eliminate_frame_pointer, bool); key!(function_sections, bool);