about summary refs log tree commit diff
path: root/src/librustc/session
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2016-04-08 16:18:40 -0700
committerAlex Crichton <alex@alexcrichton.com>2016-05-09 08:22:36 -0700
commit0ec321f7b541fcbfbf20286beb497e6d9d3352b2 (patch)
tree30abd6498f7e3ae65fa94057e2bd46f6c769fcf2 /src/librustc/session
parent32683ce1930ef1390f20e4ab72650e6804fd1c1b (diff)
downloadrust-0ec321f7b541fcbfbf20286beb497e6d9d3352b2.tar.gz
rust-0ec321f7b541fcbfbf20286beb497e6d9d3352b2.zip
rustc: Implement custom panic runtimes
This commit is an implementation of [RFC 1513] which allows applications to
alter the behavior of panics at compile time. A new compiler flag, `-C panic`,
is added and accepts the values `unwind` or `panic`, with the default being
`unwind`. This model affects how code is generated for the local crate, skipping
generation of landing pads with `-C panic=abort`.

[RFC 1513]: https://github.com/rust-lang/rfcs/blob/master/text/1513-less-unwinding.md

Panic implementations are then provided by crates tagged with
`#![panic_runtime]` and lazily required by crates with
`#![needs_panic_runtime]`. The panic strategy (`-C panic` value) of the panic
runtime must match the final product, and if the panic strategy is not `abort`
then the entire DAG must have the same panic strategy.

With the `-C panic=abort` strategy, users can expect a stable method to disable
generation of landing pads, improving optimization in niche scenarios,
decreasing compile time, and decreasing output binary size. With the `-C
panic=unwind` strategy users can expect the existing ability to isolate failure
in Rust code from the outside world.

Organizationally, this commit dismantles the `sys_common::unwind` module in
favor of some bits moving part of it to `libpanic_unwind` and the rest into the
`panicking` module in libstd. The custom panic runtime support is pretty similar
to the custom allocator support with the only major difference being how the
panic runtime is injected (takes the `-C panic` flag into account).
Diffstat (limited to 'src/librustc/session')
-rw-r--r--src/librustc/session/config.rs30
-rw-r--r--src/librustc/session/mod.rs11
2 files changed, 37 insertions, 4 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 1a2c1b9a095..82e5ce07b13 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -317,6 +317,21 @@ impl Passes {
     }
 }
 
+#[derive(Clone, PartialEq)]
+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
@@ -402,11 +417,13 @@ macro_rules! options {
             Some("a space-separated list of passes, or `all`");
         pub const parse_opt_uint: Option<&'static str> =
             Some("a number");
+        pub const parse_panic_strategy: Option<&'static str> =
+            Some("either `panic` or `abort`");
     }
 
     #[allow(dead_code)]
     mod $mod_set {
-        use super::{$struct_name, Passes, SomePasses, AllPasses};
+        use super::{$struct_name, Passes, SomePasses, AllPasses, PanicStrategy};
 
         $(
             pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
@@ -510,6 +527,15 @@ macro_rules! options {
                 }
             }
         }
+
+        fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
+            match v {
+                Some("unwind") => *slot = PanicStrategy::Unwind,
+                Some("abort") => *slot = PanicStrategy::Abort,
+                _ => return false
+            }
+            true
+        }
     }
 ) }
 
@@ -575,6 +601,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
         "explicitly enable the cfg(debug_assertions) directive"),
     inline_threshold: Option<usize> = (None, parse_opt_uint,
         "set the inlining threshold for"),
+    panic: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy,
+        "panic strategy to compile crate with"),
 }
 
 
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index edb1c4530c2..1bea01c4849 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -12,6 +12,7 @@ use lint;
 use middle::cstore::CrateStore;
 use middle::dependency_format;
 use session::search_paths::PathKind;
+use session::config::PanicStrategy;
 use ty::tls;
 use util::nodemap::{NodeMap, FnvHashMap};
 use mir::transform as mir_pass;
@@ -82,9 +83,11 @@ pub struct Session {
     /// operations such as auto-dereference and monomorphization.
     pub recursion_limit: Cell<usize>,
 
-    /// The metadata::creader module may inject an allocator dependency if it
-    /// didn't already find one, and this tracks what was injected.
+    /// The metadata::creader module may inject an allocator/panic_runtime
+    /// dependency if it didn't already find one, and this tracks what was
+    /// injected.
     pub injected_allocator: Cell<Option<ast::CrateNum>>,
+    pub injected_panic_runtime: Cell<Option<ast::CrateNum>>,
 
     /// Names of all bang-style macros and syntax extensions
     /// available in this crate
@@ -295,7 +298,8 @@ impl Session {
         self.opts.cg.lto
     }
     pub fn no_landing_pads(&self) -> bool {
-        self.opts.debugging_opts.no_landing_pads
+        self.opts.debugging_opts.no_landing_pads ||
+            self.opts.cg.panic == PanicStrategy::Abort
     }
     pub fn unstable_options(&self) -> bool {
         self.opts.debugging_opts.unstable_options
@@ -502,6 +506,7 @@ pub fn build_session_(sopts: config::Options,
         recursion_limit: Cell::new(64),
         next_node_id: Cell::new(1),
         injected_allocator: Cell::new(None),
+        injected_panic_runtime: Cell::new(None),
         available_macros: RefCell::new(HashSet::new()),
         imported_macro_spans: RefCell::new(HashMap::new()),
     };