From cbb967f3169181f2afdd4bdcd3af4ff448008b2c Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 27 Sep 2016 21:26:08 -0500 Subject: [PATCH 1/2] add a panic-strategy field to the target specification Now a target can define its panic strategy in its specification. If a user doesn't specify a panic strategy via the command line, i.e. '-C panic', then the compiler will use the panic strategy defined by the target specification. Custom targets can pick their panic strategy via the "panic-strategy" field of their target specification JSON file. If omitted in the specification, the strategy defaults to "unwind". closes #36647 --- src/librustc/middle/cstore.rs | 2 +- src/librustc/middle/dependency_format.rs | 5 ++-- src/librustc/middle/weak_lang_items.rs | 5 ++-- src/librustc/session/config.rs | 34 +++++++++--------------- src/librustc/session/mod.rs | 11 +++++--- src/librustc_back/lib.rs | 28 +++++++++++++++++++ src/librustc_back/target/mod.rs | 21 +++++++++++++++ src/librustc_metadata/creader.rs | 4 +-- src/librustc_metadata/csearch.rs | 2 +- src/librustc_metadata/cstore.rs | 2 +- src/librustc_metadata/encoder.rs | 2 +- src/librustc_metadata/schema.rs | 2 +- 12 files changed, 82 insertions(+), 36 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 62e0de1ba6774..d4a69627109fb 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -32,7 +32,6 @@ use ty::{self, Ty, TyCtxt}; use mir::repr::Mir; use mir::mir_map::MirMap; use session::Session; -use session::config::PanicStrategy; use session::search_paths::PathKind; use util::nodemap::{NodeSet, DefIdMap}; use std::path::PathBuf; @@ -45,6 +44,7 @@ use syntax_pos::Span; use rustc_back::target::Target; use hir; use hir::intravisit::Visitor; +use rustc_back::PanicStrategy; pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown}; diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index c6908e11ed209..159b7256c7a27 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -64,9 +64,10 @@ use hir::def_id::CrateNum; use session; -use session::config::{self, PanicStrategy}; +use session::config; use middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic}; use util::nodemap::FnvHashMap; +use rustc_back::PanicStrategy; /// A list of dependencies for a certain crate type. /// @@ -357,7 +358,7 @@ fn verify_ok(sess: &session::Session, list: &[Linkage]) { // only one, but we perform validation here that all the panic strategy // compilation modes for the whole DAG are valid. if let Some((cnum, found_strategy)) = panic_runtime { - let desired_strategy = sess.opts.cg.panic.clone(); + let desired_strategy = sess.panic_strategy(); // First up, validate that our selected panic runtime is indeed exactly // our same strategy. diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index c2f275e6deaf8..aa75c7a572bc5 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -10,10 +10,11 @@ //! Validity checking for weak lang items -use session::config::{self, PanicStrategy}; +use session::config; use session::Session; use middle::lang_items; +use rustc_back::PanicStrategy; use syntax::ast; use syntax::parse::token::InternedString; use syntax_pos::Span; @@ -92,7 +93,7 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) { // symbols. Other panic runtimes ensure that the relevant symbols are // available to link things together, but they're never exercised. let mut whitelisted = HashSet::new(); - if sess.opts.cg.panic != PanicStrategy::Unwind { + if sess.panic_strategy() != PanicStrategy::Unwind { whitelisted.insert(lang_items::EhPersonalityLangItem); whitelisted.insert(lang_items::EhUnwindResumeLangItem); } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 2e01ec9b0a725..d4fa0f7d1f080 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -19,6 +19,7 @@ pub use self::DebugInfoLevel::*; use session::{early_error, early_warn, Session}; use session::search_paths::SearchPaths; +use rustc_back::PanicStrategy; use rustc_back::target::Target; use lint; use middle::cstore; @@ -493,21 +494,6 @@ impl Passes { } } -#[derive(Clone, PartialEq, Hash, RustcEncodable, RustcDecodable)] -pub enum PanicStrategy { - Unwind, - Abort, -} - -impl PanicStrategy { - pub fn desc(&self) -> &str { - match *self { - PanicStrategy::Unwind => "unwind", - PanicStrategy::Abort => "abort", - } - } -} - /// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all /// at once. The goal of this macro is to define an interface that can be /// programmatically used by the option parser in order to initialize the struct @@ -620,7 +606,8 @@ macro_rules! options { #[allow(dead_code)] mod $mod_set { - use super::{$struct_name, Passes, SomePasses, AllPasses, PanicStrategy}; + use super::{$struct_name, Passes, SomePasses, AllPasses}; + use rustc_back::PanicStrategy; $( pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { @@ -725,10 +712,10 @@ macro_rules! options { } } - fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool { + fn parse_panic_strategy(slot: &mut Option, v: Option<&str>) -> bool { match v { - Some("unwind") => *slot = PanicStrategy::Unwind, - Some("abort") => *slot = PanicStrategy::Abort, + Some("unwind") => *slot = Some(PanicStrategy::Unwind), + Some("abort") => *slot = Some(PanicStrategy::Abort), _ => return false } true @@ -800,7 +787,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "explicitly enable the cfg(debug_assertions) directive"), inline_threshold: Option = (None, parse_opt_uint, [TRACKED], "set the inlining threshold for"), - panic: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, + panic: Option = (None, parse_panic_strategy, [TRACKED], "panic strategy to compile crate with"), } @@ -1676,9 +1663,10 @@ mod dep_tracking { use std::collections::BTreeMap; use std::hash::{Hash, SipHasher}; use std::path::PathBuf; - use super::{Passes, PanicStrategy, CrateType, OptLevel, DebugInfoLevel, + use super::{Passes, CrateType, OptLevel, DebugInfoLevel, OutputTypes, Externs, ErrorOutputType}; use syntax::feature_gate::UnstableFeatures; + use rustc_back::PanicStrategy; pub trait DepTrackingHash { fn hash(&self, &mut SipHasher, ErrorOutputType); @@ -1717,6 +1705,7 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); + impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(CrateType); @@ -1783,7 +1772,8 @@ mod tests { use std::iter::FromIterator; use std::path::PathBuf; use std::rc::Rc; - use super::{OutputType, OutputTypes, Externs, PanicStrategy}; + use super::{OutputType, OutputTypes, Externs}; + use rustc_back::PanicStrategy; use syntax::{ast, attr}; use syntax::parse::token::InternedString; use syntax::codemap::dummy_spanned; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 268dbd70bb5bb..f048da4977765 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -15,7 +15,7 @@ use lint; use middle::cstore::CrateStore; use middle::dependency_format; use session::search_paths::PathKind; -use session::config::{DebugInfoLevel, PanicStrategy}; +use session::config::DebugInfoLevel; use ty::tls; use util::nodemap::{NodeMap, FnvHashMap}; use util::common::duration_to_secs_str; @@ -33,6 +33,7 @@ use syntax::{ast, codemap}; use syntax::feature_gate::AttributeType; use syntax_pos::{Span, MultiSpan}; +use rustc_back::PanicStrategy; use rustc_back::target::Target; use rustc_data_structures::flock; use llvm; @@ -306,9 +307,13 @@ impl Session { pub fn lto(&self) -> bool { self.opts.cg.lto } + /// Returns the panic strategy for this compile session. If the user explicitly selected one + /// using '-C panic', use that, otherwise use the panic strategy defined by the target. + pub fn panic_strategy(&self) -> PanicStrategy { + self.opts.cg.panic.unwrap_or(self.target.target.options.panic_strategy) + } pub fn no_landing_pads(&self) -> bool { - self.opts.debugging_opts.no_landing_pads || - self.opts.cg.panic == PanicStrategy::Abort + self.opts.debugging_opts.no_landing_pads || self.panic_strategy() == PanicStrategy::Abort } pub fn unstable_options(&self) -> bool { self.opts.debugging_opts.unstable_options diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index f7ae47d2e5e56..c0f358ca8017b 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -45,8 +45,36 @@ extern crate libc; extern crate serialize; #[macro_use] extern crate log; +extern crate serialize as rustc_serialize; // used by deriving + pub mod tempdir; pub mod sha2; pub mod target; pub mod slice; pub mod dynamic_lib; + +use serialize::json::{Json, ToJson}; + +#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] +pub enum PanicStrategy { + Unwind, + Abort, +} + +impl PanicStrategy { + pub fn desc(&self) -> &str { + match *self { + PanicStrategy::Unwind => "unwind", + PanicStrategy::Abort => "abort", + } + } +} + +impl ToJson for PanicStrategy { + fn to_json(&self) -> Json { + match *self { + PanicStrategy::Abort => "abort".to_json(), + PanicStrategy::Unwind => "unwind".to_json(), + } + } +} diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 756586602b45a..f085023de0f5c 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -50,6 +50,8 @@ use std::default::Default; use std::io::prelude::*; use syntax::abi::Abi; +use PanicStrategy; + mod android_base; mod apple_base; mod apple_ios_base; @@ -343,6 +345,9 @@ pub struct TargetOptions { /// Maximum integer size in bits that this target can perform atomic /// operations on. pub max_atomic_width: u64, + + /// Panic strategy: "unwind" or "abort" + pub panic_strategy: PanicStrategy, } impl Default for TargetOptions { @@ -392,6 +397,7 @@ impl Default for TargetOptions { has_elf_tls: false, obj_is_bitcode: false, max_atomic_width: 0, + panic_strategy: PanicStrategy::Unwind, } } } @@ -470,6 +476,19 @@ impl Target { .map(|o| o.as_u64() .map(|s| base.options.$key_name = s)); } ); + ($key_name:ident, PanicStrategy) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + match s { + "unwind" => base.options.$key_name = PanicStrategy::Unwind, + "abort" => base.options.$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, list) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).map(|o| o.as_array() @@ -530,6 +549,7 @@ impl Target { key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); key!(max_atomic_width, u64); + try!(key!(panic_strategy, PanicStrategy)); Ok(base) } @@ -672,6 +692,7 @@ impl ToJson for Target { target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); target_option_val!(max_atomic_width); + target_option_val!(panic_strategy); Json::Object(d) } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 71cc13aebb370..be908ff9d19d9 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -18,7 +18,7 @@ use schema::CrateRoot; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::svh::Svh; use rustc::session::{config, Session}; -use rustc::session::config::PanicStrategy; +use rustc_back::PanicStrategy; use rustc::session::search_paths::PathKind; use rustc::middle; use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate}; @@ -710,7 +710,7 @@ impl<'a> CrateReader<'a> { // The logic for finding the panic runtime here is pretty much the same // as the allocator case with the only addition that the panic strategy // compilation mode also comes into play. - let desired_strategy = self.sess.opts.cg.panic.clone(); + let desired_strategy = self.sess.panic_strategy(); let mut runtime_found = false; let mut needs_panic_runtime = attr::contains_name(&krate.attrs, "needs_panic_runtime"); diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 1f25136ffe1ac..16a5b5402fbe3 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -26,7 +26,7 @@ use rustc::hir::map::DefKey; use rustc::mir::repr::Mir; use rustc::mir::mir_map::MirMap; use rustc::util::nodemap::{NodeSet, DefIdMap}; -use rustc::session::config::PanicStrategy; +use rustc_back::PanicStrategy; use std::path::PathBuf; use syntax::ast; diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 0a1ff70a0497e..038d0f73d5ce8 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -19,7 +19,7 @@ use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId}; use rustc::hir::map::DefKey; use rustc::hir::svh::Svh; use rustc::middle::cstore::ExternCrate; -use rustc::session::config::PanicStrategy; +use rustc_back::PanicStrategy; use rustc_data_structures::indexed_vec::IndexVec; use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap, FnvHashSet}; diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0f067270b80f5..ca4fb77d95ad6 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1293,7 +1293,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { triple: tcx.sess.opts.target_triple.clone(), hash: link_meta.crate_hash, disambiguator: tcx.sess.local_crate_disambiguator().to_string(), - panic_strategy: tcx.sess.opts.cg.panic.clone(), + panic_strategy: tcx.sess.panic_strategy(), plugin_registrar_fn: tcx.sess.plugin_registrar_fn.get().map(|id| { tcx.map.local_def_id(id).index }), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index f4d1e8e17f842..58e18bc709e3c 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -18,7 +18,7 @@ use rustc::middle::cstore::{LinkagePreference, NativeLibraryKind}; use rustc::middle::lang_items; use rustc::mir; use rustc::ty::{self, Ty}; -use rustc::session::config::PanicStrategy; +use rustc_back::PanicStrategy; use rustc_serialize as serialize; use syntax::{ast, attr}; From 8a46e78e64dee2c85ba097081ddff027322e93d3 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 28 Sep 2016 10:57:31 -0500 Subject: [PATCH 2/2] fix librustc test: panic is Option now --- src/librustc/session/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index d4fa0f7d1f080..bbb32e58f12f5 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -2319,7 +2319,7 @@ mod tests { assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); - opts.cg.panic = PanicStrategy::Abort; + opts.cg.panic = Some(PanicStrategy::Abort); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); }