diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index ee3fabc58d53f..28e473a1383bf 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -68,15 +68,13 @@ pub enum OptLevel { SizeMin, // -Oz } +/// This is what the `LtoCli` values get mapped to after resolving defaults and +/// and taking other command line options into account. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum Lto { /// Don't do any LTO whatsoever No, - /// Do a full crate graph LTO. The flavor is determined by the compiler - /// (currently the default is "fat"). - Yes, - /// Do a full crate graph LTO with ThinLTO Thin, @@ -88,6 +86,23 @@ pub enum Lto { Fat, } +/// The different settings that the `-C lto` flag can have. +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum LtoCli { + /// `-C lto=no` + No, + /// `-C lto=yes` + Yes, + /// `-C lto` + NoParam, + /// `-C lto=thin` + Thin, + /// `-C lto=fat` + Fat, + /// No `-C lto` flag passed + Unspecified, +} + #[derive(Clone, PartialEq, Hash)] pub enum CrossLangLto { LinkerPlugin(PathBuf), @@ -801,7 +816,8 @@ macro_rules! options { pub const parse_unpretty: Option<&'static str> = Some("`string` or `string=string`"); pub const parse_lto: Option<&'static str> = - Some("one of `thin`, `fat`, or omitted"); + Some("either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \ + `fat`, or omitted"); pub const parse_cross_lang_lto: Option<&'static str> = Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \ or the path to the linker plugin"); @@ -809,7 +825,7 @@ macro_rules! options { #[allow(dead_code)] mod $mod_set { - use super::{$struct_name, Passes, Sanitizer, Lto, CrossLangLto}; + use super::{$struct_name, Passes, Sanitizer, LtoCli, CrossLangLto}; use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel}; use std::path::PathBuf; @@ -1002,11 +1018,23 @@ macro_rules! options { } } - fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool { + fn parse_lto(slot: &mut LtoCli, v: Option<&str>) -> bool { + if v.is_some() { + let mut bool_arg = None; + if parse_opt_bool(&mut bool_arg, v) { + *slot = if bool_arg.unwrap() { + LtoCli::Yes + } else { + LtoCli::No + }; + return true + } + } + *slot = match v { - None => Lto::Yes, - Some("thin") => Lto::Thin, - Some("fat") => Lto::Fat, + None => LtoCli::NoParam, + Some("thin") => LtoCli::Thin, + Some("fat") => LtoCli::Fat, Some(_) => return false, }; true @@ -1047,7 +1075,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "extra arguments to append to the linker invocation (space separated)"), link_dead_code: bool = (false, parse_bool, [UNTRACKED], "don't let linker strip dead code (turning it on can be used for code coverage)"), - lto: Lto = (Lto::No, parse_lto, [TRACKED], + lto: LtoCli = (LtoCli::Unspecified, parse_lto, [TRACKED], "perform LLVM link-time optimizations"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (rustc --print target-cpus for details)"), @@ -2373,8 +2401,8 @@ mod dep_tracking { use std::hash::Hash; use std::path::PathBuf; use std::collections::hash_map::DefaultHasher; - use super::{CrateType, DebugInfo, ErrorOutputType, Lto, OptLevel, OutputTypes, - Passes, Sanitizer, CrossLangLto}; + use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes, + Passes, Sanitizer, LtoCli, CrossLangLto}; use syntax::feature_gate::UnstableFeatures; use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple}; use syntax::edition::Edition; @@ -2429,7 +2457,7 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(RelroLevel); impl_dep_tracking_hash_via_hash!(Passes); impl_dep_tracking_hash_via_hash!(OptLevel); - impl_dep_tracking_hash_via_hash!(Lto); + impl_dep_tracking_hash_via_hash!(LtoCli); impl_dep_tracking_hash_via_hash!(DebugInfo); impl_dep_tracking_hash_via_hash!(UnstableFeatures); impl_dep_tracking_hash_via_hash!(OutputTypes); @@ -2503,7 +2531,7 @@ mod tests { use lint; use middle::cstore; use session::config::{build_configuration, build_session_options_and_crate_config}; - use session::config::{Lto, CrossLangLto}; + use session::config::{LtoCli, CrossLangLto}; use session::build_session; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; @@ -2937,7 +2965,7 @@ mod tests { // Make sure changing a [TRACKED] option changes the hash opts = reference.clone(); - opts.cg.lto = Lto::Fat; + opts.cg.lto = LtoCli::Fat; assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 778c388c7dec7..9e99d3af6d10b 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -547,9 +547,27 @@ impl Session { // lto` and we've for whatever reason forced off ThinLTO via the CLI, // then ensure we can't use a ThinLTO. match self.opts.cg.lto { - config::Lto::No => {} - config::Lto::Yes if self.opts.cli_forced_thinlto_off => return config::Lto::Fat, - other => return other, + config::LtoCli::Unspecified => { + // The compiler was invoked without the `-Clto` flag. Fall + // through to the default handling + } + config::LtoCli::No => { + // The user explicitly opted out of any kind of LTO + return config::Lto::No; + } + config::LtoCli::Yes | + config::LtoCli::Fat | + config::LtoCli::NoParam => { + // All of these mean fat LTO + return config::Lto::Fat; + } + config::LtoCli::Thin => { + return if self.opts.cli_forced_thinlto_off { + config::Lto::Fat + } else { + config::Lto::Thin + }; + } } // Ok at this point the target doesn't require anything and the user @@ -1174,7 +1192,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) { if sess.opts.incremental.is_some() { match sess.lto() { - Lto::Yes | Lto::Thin | Lto::Fat => { sess.err("can't perform LTO when compiling incrementally"); diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index d50a56ad84ab2..8248385c12764 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -1666,7 +1666,6 @@ fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { fn are_upstream_rust_objects_already_included(sess: &Session) -> bool { match sess.lto() { - Lto::Yes | Lto::Fat => true, Lto::Thin => { // If we defer LTO to the linker, we haven't run LTO ourselves, so diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs index ebb229b7b6bfa..95be2d82123a7 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_llvm/back/linker.rs @@ -205,13 +205,12 @@ impl<'a> GccLinker<'a> { self.linker_arg(&format!("-plugin-opt={}", opt_level)); self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess))); - match self.sess.opts.cg.lto { + match self.sess.lto() { config::Lto::Thin | config::Lto::ThinLocal => { self.linker_arg("-plugin-opt=thin"); } config::Lto::Fat | - config::Lto::Yes | config::Lto::No => { // default to regular LTO } diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index c1dda02264ed1..d852eb0bc6834 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -118,7 +118,7 @@ pub(crate) fn run(cgcx: &CodegenContext, Lto::ThinLocal => SymbolExportLevel::Rust, // We're doing LTO for the entire crate graph - Lto::Yes | Lto::Fat | Lto::Thin => { + Lto::Fat | Lto::Thin => { symbol_export::crates_export_threshold(&cgcx.crate_types) } @@ -201,7 +201,6 @@ pub(crate) fn run(cgcx: &CodegenContext, .map(|c| c.as_ptr()) .collect::>(); match cgcx.lto { - Lto::Yes | // `-C lto` == fat LTO by default Lto::Fat => { assert!(cached_modules.is_empty()); let opt_jobs = fat_lto(cgcx, diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 1c0f89193b209..3940673dc79c2 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -928,7 +928,6 @@ fn need_pre_thin_lto_bitcode_for_incr_comp(sess: &Session) -> bool { } match sess.lto() { - Lto::Yes | Lto::Fat | Lto::No => false, Lto::Thin | @@ -1363,7 +1362,7 @@ fn execute_optimize_work_item(cgcx: &CodegenContext, // require LTO so the request for LTO is always unconditionally // passed down to the backend, but we don't actually want to do // anything about it yet until we've got a final product. - Lto::Yes | Lto::Fat | Lto::Thin => { + Lto::Fat | Lto::Thin => { cgcx.crate_types.len() != 1 || cgcx.crate_types[0] != config::CrateType::Rlib } @@ -1543,7 +1542,7 @@ fn start_executing_work(tcx: TyCtxt, exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); Some(Arc::new(exported_symbols)) } - Lto::Yes | Lto::Fat | Lto::Thin => { + Lto::Fat | Lto::Thin => { exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); for &cnum in tcx.crates().iter() { exported_symbols.insert(cnum, copy_symbols(cnum)); diff --git a/src/test/run-make-fulldeps/codegen-options-parsing/Makefile b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile index fda96a8b1fb5e..39e9a9bdd6b68 100644 --- a/src/test/run-make-fulldeps/codegen-options-parsing/Makefile +++ b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile @@ -16,11 +16,11 @@ all: $(RUSTC) -C extra-filename=foo dummy.rs 2>&1 #Option taking no argument $(RUSTC) -C lto= dummy.rs 2>&1 | \ - $(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or' + $(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted' $(RUSTC) -C lto=1 dummy.rs 2>&1 | \ - $(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or' + $(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted' $(RUSTC) -C lto=foo dummy.rs 2>&1 | \ - $(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or' + $(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted' $(RUSTC) -C lto dummy.rs # Should not link dead code... diff --git a/src/test/run-make-fulldeps/lto-smoke/Makefile b/src/test/run-make-fulldeps/lto-smoke/Makefile index 020252e1f8cd3..9b1dc2550b21b 100644 --- a/src/test/run-make-fulldeps/lto-smoke/Makefile +++ b/src/test/run-make-fulldeps/lto-smoke/Makefile @@ -1,6 +1,30 @@ -include ../tools.mk -all: +all: noparam bool_true bool_false thin fat + +noparam: $(RUSTC) lib.rs $(RUSTC) main.rs -C lto $(call RUN,main) + +bool_true: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=yes + $(call RUN,main) + + +bool_false: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=off + $(call RUN,main) + +thin: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=thin + $(call RUN,main) + +fat: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=fat + $(call RUN,main) +