2014-05-06 23:38:01 +12:00
//! Contains infrastructure for configuring the compiler, including parsing
2019-09-06 03:57:44 +01:00
//! command-line options.
2018-04-19 13:56:26 -07:00
2024-02-20 14:12:50 +11:00
#![ allow(rustc::untranslatable_diagnostic) ] // FIXME: make this translatable
2019-12-17 23:22:55 +11:00
pub use crate ::options ::* ;
2023-07-16 22:13:08 -07:00
use crate ::errors ::FileWriteFail ;
2019-11-29 16:05:28 -05:00
use crate ::search_paths ::SearchPath ;
2021-03-24 21:45:09 -07:00
use crate ::utils ::{ CanonicalizedPath , NativeLib , NativeLibKind } ;
2024-02-15 00:03:34 +00:00
use crate ::{ filesearch , lint , HashStableContext } ;
2023-12-17 22:01:06 +11:00
use crate ::{ EarlyDiagCtxt , Session } ;
2023-11-27 13:47:26 +01:00
use rustc_data_structures ::fx ::{ FxHashMap , FxHashSet , FxIndexMap , FxIndexSet } ;
2022-12-02 15:14:49 +01:00
use rustc_data_structures ::stable_hasher ::{ StableOrd , ToStableHashKey } ;
2023-11-28 15:29:39 +11:00
use rustc_errors ::emitter ::HumanReadableErrorType ;
2024-03-05 16:53:24 +11:00
use rustc_errors ::{ ColorConfig , DiagArgValue , DiagCtxtFlags , IntoDiagArg } ;
2019-11-29 16:05:28 -05:00
use rustc_feature ::UnstableFeatures ;
2021-04-10 11:46:36 +01:00
use rustc_span ::edition ::{ Edition , DEFAULT_EDITION , EDITION_NAME_LIST , LATEST_STABLE_EDITION } ;
2023-11-02 14:10:12 +11:00
use rustc_span ::source_map ::FilePathMapping ;
2019-12-31 20:15:40 +03:00
use rustc_span ::symbol ::{ sym , Symbol } ;
2023-11-02 14:10:12 +11:00
use rustc_span ::{ FileName , FileNameDisplayPreference , RealFileName , SourceFileHashAlgorithm } ;
2023-11-28 15:29:39 +11:00
use rustc_target ::abi ::Align ;
use rustc_target ::spec ::LinkSelfContainedComponents ;
use rustc_target ::spec ::{ PanicStrategy , RelocModel , SanitizerSet , SplitDebuginfo } ;
2024-03-21 10:35:19 +11:00
use rustc_target ::spec ::{ Target , TargetTriple , TARGETS } ;
2019-09-06 03:57:44 +01:00
use std ::collections ::btree_map ::{
Iter as BTreeMapIter , Keys as BTreeMapKeysIter , Values as BTreeMapValuesIter ,
} ;
use std ::collections ::{ BTreeMap , BTreeSet } ;
2023-02-26 15:27:27 -05:00
use std ::ffi ::OsStr ;
2019-09-06 03:57:44 +01:00
use std ::fmt ;
2023-07-16 22:13:08 -07:00
use std ::fs ;
2021-06-19 19:22:14 -05:00
use std ::hash ::Hash ;
2022-08-09 02:14:43 +02:00
use std ::iter ;
2018-03-24 20:14:59 +01:00
use std ::path ::{ Path , PathBuf } ;
2019-09-06 03:57:44 +01:00
use std ::str ::{ self , FromStr } ;
2023-01-06 14:07:12 -05:00
use std ::sync ::LazyLock ;
2014-05-06 23:38:01 +12:00
2022-07-05 19:56:22 +02:00
pub mod sigpipe ;
2021-10-21 13:19:46 +02:00
/// The different settings that the `-C strip` flag can have.
2020-05-03 12:36:12 +08:00
#[ derive(Clone, Copy, PartialEq, Hash, Debug) ]
pub enum Strip {
/// Do not strip at all.
None ,
/// Strip debuginfo.
Debuginfo ,
/// Strip all symbols.
Symbols ,
}
2020-07-14 15:27:42 +01:00
/// The different settings that the `-C control-flow-guard` flag can have.
2020-01-13 13:25:39 +00:00
#[ derive(Clone, Copy, PartialEq, Hash, Debug) ]
pub enum CFGuard {
/// Do not emit Control Flow Guard metadata or checks.
Disabled ,
/// Emit Control Flow Guard metadata but no checks.
NoChecks ,
/// Emit Control Flow Guard metadata and checks.
Checks ,
}
2022-01-28 09:48:59 -08:00
/// The different settings that the `-Z cf-protection` flag can have.
#[ derive(Clone, Copy, PartialEq, Hash, Debug) ]
pub enum CFProtection {
/// Do not enable control-flow protection
None ,
/// Emit control-flow protection for branches (enables indirect branch tracking).
Branch ,
/// Emit control-flow protection for returns.
Return ,
/// Emit control-flow protection for both branches and returns.
Full ,
}
2022-04-19 10:43:09 +02:00
#[ derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic) ]
2014-05-06 23:38:01 +12:00
pub enum OptLevel {
2018-03-06 02:29:03 -03:00
No , // -O0
Less , // -O1
Default , // -O2
2016-03-27 12:42:47 -07:00
Aggressive , // -O3
2018-03-06 02:29:03 -03:00
Size , // -Os
SizeMin , // -Oz
2014-05-06 23:38:01 +12:00
}
2018-09-04 17:57:17 +02:00
/// This is what the `LtoCli` values get mapped to after resolving defaults and
/// and taking other command line options into account.
2021-04-20 10:19:25 +01:00
///
/// Note that linker plugin-based LTO is a different mechanism entirely.
2019-10-20 15:54:53 +11:00
#[ derive(Clone, PartialEq) ]
2018-01-16 15:02:31 -08:00
pub enum Lto {
2021-04-20 10:19:25 +01:00
/// Don't do any LTO whatsoever.
2018-01-16 15:02:31 -08:00
No ,
2021-04-20 10:19:25 +01:00
/// Do a full-crate-graph (inter-crate) LTO with ThinLTO.
2018-01-16 15:02:31 -08:00
Thin ,
2021-04-20 10:19:25 +01:00
/// Do a local ThinLTO (intra-crate, over the CodeGen Units of the local crate only). This is
/// only relevant if multiple CGUs are used.
2018-01-16 15:02:31 -08:00
ThinLocal ,
2021-04-20 10:19:25 +01:00
/// Do a full-crate-graph (inter-crate) LTO with "fat" LTO.
2018-01-16 15:02:31 -08:00
Fat ,
}
2018-09-04 17:57:17 +02:00
/// 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 ,
}
2021-10-21 16:04:22 +02:00
/// The different settings that the `-C instrument-coverage` flag can have.
coverage bug fixes and optimization support
Adjusted LLVM codegen for code compiled with `-Zinstrument-coverage` to
address multiple, somewhat related issues.
Fixed a significant flaw in prior coverage solution: Every counter
generated a new counter variable, but there should have only been one
counter variable per function. This appears to have bloated .profraw
files significantly. (For a small program, it increased the size by
about 40%. I have not tested large programs, but there is anecdotal
evidence that profraw files were way too large. This is a good fix,
regardless, but hopefully it also addresses related issues.
Fixes: #82144
Invalid LLVM coverage data produced when compiled with -C opt-level=1
Existing tests now work up to at least `opt-level=3`. This required a
detailed analysis of the LLVM IR, comparisons with Clang C++ LLVM IR
when compiled with coverage, and a lot of trial and error with codegen
adjustments.
The biggest hurdle was figuring out how to continue to support coverage
results for unused functions and generics. Rust's coverage results have
three advantages over Clang's coverage results:
1. Rust's coverage map does not include any overlapping code regions,
making coverage counting unambiguous.
2. Rust generates coverage results (showing zero counts) for all unused
functions, including generics. (Clang does not generate coverage for
uninstantiated template functions.)
3. Rust's unused functions produce minimal stubbed functions in LLVM IR,
sufficient for including in the coverage results; while Clang must
generate the complete LLVM IR for each unused function, even though
it will never be called.
This PR removes the previous hack of attempting to inject coverage into
some other existing function instance, and generates dedicated instances
for each unused function. This change, and a few other adjustments
(similar to what is required for `-C link-dead-code`, but with lower
impact), makes it possible to support LLVM optimizations.
Fixes: #79651
Coverage report: "Unexecuted instantiation:..." for a generic function
from multiple crates
Fixed by removing the aforementioned hack. Some "Unexecuted
instantiation" notices are unavoidable, as explained in the
`used_crate.rs` test, but `-Zinstrument-coverage` has new options to
back off support for either unused generics, or all unused functions,
which avoids the notice, at the cost of less coverage of unused
functions.
Fixes: #82875
Invalid LLVM coverage data produced with crate brotli_decompressor
Fixed by disabling the LLVM function attribute that forces inlining, if
`-Z instrument-coverage` is enabled. This attribute is applied to
Rust functions with `#[inline(always)], and in some cases, the forced
inlining breaks coverage instrumentation and reports.
2021-03-15 16:32:45 -07:00
///
2021-10-21 16:04:22 +02:00
/// Coverage instrumentation now supports combining `-C instrument-coverage`
coverage bug fixes and optimization support
Adjusted LLVM codegen for code compiled with `-Zinstrument-coverage` to
address multiple, somewhat related issues.
Fixed a significant flaw in prior coverage solution: Every counter
generated a new counter variable, but there should have only been one
counter variable per function. This appears to have bloated .profraw
files significantly. (For a small program, it increased the size by
about 40%. I have not tested large programs, but there is anecdotal
evidence that profraw files were way too large. This is a good fix,
regardless, but hopefully it also addresses related issues.
Fixes: #82144
Invalid LLVM coverage data produced when compiled with -C opt-level=1
Existing tests now work up to at least `opt-level=3`. This required a
detailed analysis of the LLVM IR, comparisons with Clang C++ LLVM IR
when compiled with coverage, and a lot of trial and error with codegen
adjustments.
The biggest hurdle was figuring out how to continue to support coverage
results for unused functions and generics. Rust's coverage results have
three advantages over Clang's coverage results:
1. Rust's coverage map does not include any overlapping code regions,
making coverage counting unambiguous.
2. Rust generates coverage results (showing zero counts) for all unused
functions, including generics. (Clang does not generate coverage for
uninstantiated template functions.)
3. Rust's unused functions produce minimal stubbed functions in LLVM IR,
sufficient for including in the coverage results; while Clang must
generate the complete LLVM IR for each unused function, even though
it will never be called.
This PR removes the previous hack of attempting to inject coverage into
some other existing function instance, and generates dedicated instances
for each unused function. This change, and a few other adjustments
(similar to what is required for `-C link-dead-code`, but with lower
impact), makes it possible to support LLVM optimizations.
Fixes: #79651
Coverage report: "Unexecuted instantiation:..." for a generic function
from multiple crates
Fixed by removing the aforementioned hack. Some "Unexecuted
instantiation" notices are unavoidable, as explained in the
`used_crate.rs` test, but `-Zinstrument-coverage` has new options to
back off support for either unused generics, or all unused functions,
which avoids the notice, at the cost of less coverage of unused
functions.
Fixes: #82875
Invalid LLVM coverage data produced with crate brotli_decompressor
Fixed by disabling the LLVM function attribute that forces inlining, if
`-Z instrument-coverage` is enabled. This attribute is applied to
Rust functions with `#[inline(always)], and in some cases, the forced
inlining breaks coverage instrumentation and reports.
2021-03-15 16:32:45 -07:00
/// with compiler and linker optimization (enabled with `-O` or `-C opt-level=1`
/// and higher). Nevertheless, there are many variables, depending on options
/// selected, code structure, and enabled attributes. If errors are encountered,
/// either while compiling or when generating `llvm-cov show` reports, consider
2024-03-12 12:30:33 +11:00
/// lowering the optimization level, or including/excluding `-C link-dead-code`.
coverage bug fixes and optimization support
Adjusted LLVM codegen for code compiled with `-Zinstrument-coverage` to
address multiple, somewhat related issues.
Fixed a significant flaw in prior coverage solution: Every counter
generated a new counter variable, but there should have only been one
counter variable per function. This appears to have bloated .profraw
files significantly. (For a small program, it increased the size by
about 40%. I have not tested large programs, but there is anecdotal
evidence that profraw files were way too large. This is a good fix,
regardless, but hopefully it also addresses related issues.
Fixes: #82144
Invalid LLVM coverage data produced when compiled with -C opt-level=1
Existing tests now work up to at least `opt-level=3`. This required a
detailed analysis of the LLVM IR, comparisons with Clang C++ LLVM IR
when compiled with coverage, and a lot of trial and error with codegen
adjustments.
The biggest hurdle was figuring out how to continue to support coverage
results for unused functions and generics. Rust's coverage results have
three advantages over Clang's coverage results:
1. Rust's coverage map does not include any overlapping code regions,
making coverage counting unambiguous.
2. Rust generates coverage results (showing zero counts) for all unused
functions, including generics. (Clang does not generate coverage for
uninstantiated template functions.)
3. Rust's unused functions produce minimal stubbed functions in LLVM IR,
sufficient for including in the coverage results; while Clang must
generate the complete LLVM IR for each unused function, even though
it will never be called.
This PR removes the previous hack of attempting to inject coverage into
some other existing function instance, and generates dedicated instances
for each unused function. This change, and a few other adjustments
(similar to what is required for `-C link-dead-code`, but with lower
impact), makes it possible to support LLVM optimizations.
Fixes: #79651
Coverage report: "Unexecuted instantiation:..." for a generic function
from multiple crates
Fixed by removing the aforementioned hack. Some "Unexecuted
instantiation" notices are unavoidable, as explained in the
`used_crate.rs` test, but `-Zinstrument-coverage` has new options to
back off support for either unused generics, or all unused functions,
which avoids the notice, at the cost of less coverage of unused
functions.
Fixes: #82875
Invalid LLVM coverage data produced with crate brotli_decompressor
Fixed by disabling the LLVM function attribute that forces inlining, if
`-Z instrument-coverage` is enabled. This attribute is applied to
Rust functions with `#[inline(always)], and in some cases, the forced
inlining breaks coverage instrumentation and reports.
2021-03-15 16:32:45 -07:00
#[ derive(Clone, Copy, PartialEq, Hash, Debug) ]
pub enum InstrumentCoverage {
2023-10-25 14:57:25 +11:00
/// `-C instrument-coverage=no` (or `off`, `false` etc.)
No ,
/// `-C instrument-coverage` or `-C instrument-coverage=yes`
Yes ,
coverage bug fixes and optimization support
Adjusted LLVM codegen for code compiled with `-Zinstrument-coverage` to
address multiple, somewhat related issues.
Fixed a significant flaw in prior coverage solution: Every counter
generated a new counter variable, but there should have only been one
counter variable per function. This appears to have bloated .profraw
files significantly. (For a small program, it increased the size by
about 40%. I have not tested large programs, but there is anecdotal
evidence that profraw files were way too large. This is a good fix,
regardless, but hopefully it also addresses related issues.
Fixes: #82144
Invalid LLVM coverage data produced when compiled with -C opt-level=1
Existing tests now work up to at least `opt-level=3`. This required a
detailed analysis of the LLVM IR, comparisons with Clang C++ LLVM IR
when compiled with coverage, and a lot of trial and error with codegen
adjustments.
The biggest hurdle was figuring out how to continue to support coverage
results for unused functions and generics. Rust's coverage results have
three advantages over Clang's coverage results:
1. Rust's coverage map does not include any overlapping code regions,
making coverage counting unambiguous.
2. Rust generates coverage results (showing zero counts) for all unused
functions, including generics. (Clang does not generate coverage for
uninstantiated template functions.)
3. Rust's unused functions produce minimal stubbed functions in LLVM IR,
sufficient for including in the coverage results; while Clang must
generate the complete LLVM IR for each unused function, even though
it will never be called.
This PR removes the previous hack of attempting to inject coverage into
some other existing function instance, and generates dedicated instances
for each unused function. This change, and a few other adjustments
(similar to what is required for `-C link-dead-code`, but with lower
impact), makes it possible to support LLVM optimizations.
Fixes: #79651
Coverage report: "Unexecuted instantiation:..." for a generic function
from multiple crates
Fixed by removing the aforementioned hack. Some "Unexecuted
instantiation" notices are unavoidable, as explained in the
`used_crate.rs` test, but `-Zinstrument-coverage` has new options to
back off support for either unused generics, or all unused functions,
which avoids the notice, at the cost of less coverage of unused
functions.
Fixes: #82875
Invalid LLVM coverage data produced with crate brotli_decompressor
Fixed by disabling the LLVM function attribute that forces inlining, if
`-Z instrument-coverage` is enabled. This attribute is applied to
Rust functions with `#[inline(always)], and in some cases, the forced
inlining breaks coverage instrumentation and reports.
2021-03-15 16:32:45 -07:00
}
2024-03-08 18:07:04 +11:00
/// Individual flag values controlled by `-Z coverage-options`.
2024-03-17 13:37:54 +01:00
#[ derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default) ]
2024-03-08 18:07:04 +11:00
pub struct CoverageOptions {
2024-03-13 20:53:10 +11:00
/// Add branch coverage instrumentation.
2024-03-08 18:07:04 +11:00
pub branch : bool ,
}
2022-09-24 20:02:44 +09:00
/// Settings for `-Z instrument-xray` flag.
#[ derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash) ]
pub struct InstrumentXRay {
/// `-Z instrument-xray=always`, force instrumentation
pub always : bool ,
/// `-Z instrument-xray=never`, disable instrumentation
pub never : bool ,
/// `-Z instrument-xray=ignore-loops`, ignore presence of loops,
/// instrument functions based only on instruction count
pub ignore_loops : bool ,
/// `-Z instrument-xray=instruction-threshold=N`, explicitly set instruction threshold
/// for instrumentation, or `None` to use compiler's default
pub instruction_threshold : Option < usize > ,
/// `-Z instrument-xray=skip-entry`, do not instrument function entry
pub skip_entry : bool ,
/// `-Z instrument-xray=skip-exit`, do not instrument function exit
pub skip_exit : bool ,
}
2021-04-15 23:06:32 -04:00
#[ derive(Clone, PartialEq, Hash, Debug) ]
2019-02-01 15:15:43 +01:00
pub enum LinkerPluginLto {
2018-04-25 15:45:04 +02:00
LinkerPlugin ( PathBuf ) ,
2018-07-03 16:33:11 +02:00
LinkerPluginAuto ,
2018-04-25 15:45:04 +02:00
Disabled ,
}
2023-06-21 17:54:27 +00:00
impl LinkerPluginLto {
pub fn enabled ( & self ) -> bool {
match * self {
LinkerPluginLto ::LinkerPlugin ( _ ) | LinkerPluginLto ::LinkerPluginAuto = > true ,
LinkerPluginLto ::Disabled = > false ,
}
}
}
2023-06-21 21:45:13 +00:00
/// The different values `-C link-self-contained` can take: a list of individually enabled or
/// disabled components used during linking, coming from the rustc distribution, instead of being
/// found somewhere on the host system.
///
/// They can be set in bulk via `-C link-self-contained=yes|y|on` or `-C
/// link-self-contained=no|n|off`, and those boolean values are the historical defaults.
///
/// But each component is fine-grained, and can be unstably targeted, to use:
/// - some CRT objects
/// - the libc static library
/// - libgcc/libunwind libraries
/// - a linker we distribute
/// - some sanitizer runtime libraries
/// - all other MinGW libraries and Windows import libs
///
#[ derive(Default, Clone, PartialEq, Debug) ]
pub struct LinkSelfContained {
/// Whether the user explicitly set `-C link-self-contained` on or off, the historical values.
/// Used for compatibility with the existing opt-in and target inference.
pub explicitly_set : Option < bool > ,
2023-09-20 20:25:17 +00:00
/// The components that are enabled on the CLI, using the `+component` syntax or one of the
/// `true` shorcuts.
enabled_components : LinkSelfContainedComponents ,
/// The components that are disabled on the CLI, using the `-component` syntax or one of the
/// `false` shortcuts.
disabled_components : LinkSelfContainedComponents ,
2023-06-21 21:45:13 +00:00
}
2023-06-21 21:46:36 +00:00
impl LinkSelfContained {
/// Incorporates an enabled or disabled component as specified on the CLI, if possible.
/// For example: `+linker`, and `-crto`.
2023-09-20 20:09:06 +00:00
pub ( crate ) fn handle_cli_component ( & mut self , component : & str ) -> Option < ( ) > {
2023-06-21 21:46:36 +00:00
// Note that for example `-Cself-contained=y -Cself-contained=-linker` is not an explicit
// set of all values like `y` or `n` used to be. Therefore, if this flag had previously been
// set in bulk with its historical values, then manually setting a component clears that
// `explicitly_set` state.
2023-07-23 10:12:40 +02:00
if let Some ( component_to_enable ) = component . strip_prefix ( '+' ) {
2023-06-21 21:46:36 +00:00
self . explicitly_set = None ;
2023-09-20 20:25:17 +00:00
self . enabled_components
. insert ( LinkSelfContainedComponents ::from_str ( component_to_enable ) ? ) ;
2023-09-20 20:09:06 +00:00
Some ( ( ) )
2023-07-23 10:12:40 +02:00
} else if let Some ( component_to_disable ) = component . strip_prefix ( '-' ) {
2023-06-21 21:46:36 +00:00
self . explicitly_set = None ;
2023-09-20 20:25:17 +00:00
self . disabled_components
. insert ( LinkSelfContainedComponents ::from_str ( component_to_disable ) ? ) ;
2023-09-20 20:09:06 +00:00
Some ( ( ) )
2023-06-21 21:46:36 +00:00
} else {
2023-09-20 20:09:06 +00:00
None
2023-06-21 21:46:36 +00:00
}
}
/// Turns all components on or off and records that this was done explicitly for compatibility
/// purposes.
pub ( crate ) fn set_all_explicitly ( & mut self , enabled : bool ) {
self . explicitly_set = Some ( enabled ) ;
2023-09-20 20:25:17 +00:00
if enabled {
self . enabled_components = LinkSelfContainedComponents ::all ( ) ;
self . disabled_components = LinkSelfContainedComponents ::empty ( ) ;
2023-06-21 21:46:36 +00:00
} else {
2023-09-20 20:25:17 +00:00
self . enabled_components = LinkSelfContainedComponents ::empty ( ) ;
self . disabled_components = LinkSelfContainedComponents ::all ( ) ;
}
2023-06-21 21:46:36 +00:00
}
/// Helper creating a fully enabled `LinkSelfContained` instance. Used in tests.
pub fn on ( ) -> Self {
let mut on = LinkSelfContained ::default ( ) ;
on . set_all_explicitly ( true ) ;
on
}
2023-06-21 15:49:10 +00:00
2023-06-21 21:49:41 +00:00
/// To help checking CLI usage while some of the values are unstable: returns whether one of the
/// components was set individually. This would also require the `-Zunstable-options` flag, to
/// be allowed.
fn are_unstable_variants_set ( & self ) -> bool {
2023-09-20 20:25:17 +00:00
let any_component_set =
! self . enabled_components . is_empty ( ) | | ! self . disabled_components . is_empty ( ) ;
2023-06-21 21:49:41 +00:00
self . explicitly_set . is_none ( ) & & any_component_set
}
2023-09-20 20:25:17 +00:00
/// Returns whether the self-contained linker component was enabled on the CLI, using the
/// `-C link-self-contained=+linker` syntax, or one of the `true` shorcuts.
pub fn is_linker_enabled ( & self ) -> bool {
self . enabled_components . contains ( LinkSelfContainedComponents ::LINKER )
}
/// Returns whether the self-contained linker component was disabled on the CLI, using the
/// `-C link-self-contained=-linker` syntax, or one of the `false` shorcuts.
pub fn is_linker_disabled ( & self ) -> bool {
self . disabled_components . contains ( LinkSelfContainedComponents ::LINKER )
2023-06-21 15:49:10 +00:00
}
2023-09-21 13:27:45 +00:00
/// Returns CLI inconsistencies to emit errors: individual components were both enabled and
/// disabled.
fn check_consistency ( & self ) -> Option < LinkSelfContainedComponents > {
if self . explicitly_set . is_some ( ) {
None
} else {
let common = self . enabled_components . intersection ( self . disabled_components ) ;
if common . is_empty ( ) { None } else { Some ( common ) }
}
}
2023-06-21 21:46:36 +00:00
}
2021-10-31 17:05:48 -05:00
/// Used with `-Z assert-incr-state`.
#[ derive(Clone, Copy, PartialEq, Hash, Debug) ]
pub enum IncrementalStateAssertion {
/// Found and loaded an existing session directory.
///
/// Note that this says nothing about whether any particular query
/// will be found to be red or green.
Loaded ,
/// Did not load an existing session directory.
NotLoaded ,
}
2021-10-13 17:01:31 -07:00
/// The different settings that can be enabled via the `-Z location-detail` flag.
2023-04-13 18:04:30 +00:00
#[ derive(Copy, Clone, PartialEq, Hash, Debug) ]
2021-10-13 17:01:31 -07:00
pub struct LocationDetail {
pub file : bool ,
pub line : bool ,
pub column : bool ,
}
impl LocationDetail {
2024-03-19 13:31:28 +11:00
pub ( crate ) fn all ( ) -> Self {
2021-10-13 17:01:31 -07:00
Self { file : true , line : true , column : true }
}
}
2021-04-15 23:06:32 -04:00
#[ derive(Clone, PartialEq, Hash, Debug) ]
2019-05-28 16:13:59 +02:00
pub enum SwitchWithOptPath {
2019-04-10 13:46:37 +02:00
Enabled ( Option < PathBuf > ) ,
Disabled ,
}
2019-05-28 16:13:59 +02:00
impl SwitchWithOptPath {
2019-04-10 13:46:37 +02:00
pub fn enabled ( & self ) -> bool {
match * self {
2019-05-28 16:13:59 +02:00
SwitchWithOptPath ::Enabled ( _ ) = > true ,
SwitchWithOptPath ::Disabled = > false ,
2019-04-10 13:46:37 +02:00
}
}
}
2022-04-19 10:43:09 +02:00
#[ derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic) ]
2020-06-11 15:49:57 +01:00
#[ derive(Encodable, Decodable) ]
2019-01-29 07:24:32 +02:00
pub enum SymbolManglingVersion {
Legacy ,
V0 ,
2023-12-05 12:42:57 +08:00
Hashed ,
2019-01-29 07:24:32 +02:00
}
2020-11-28 15:07:51 +00:00
#[ derive(Clone, Copy, Debug, PartialEq, Hash) ]
2018-07-26 11:41:10 -06:00
pub enum DebugInfo {
None ,
2021-04-06 16:00:35 -04:00
LineDirectivesOnly ,
LineTablesOnly ,
2018-07-26 11:41:10 -06:00
Limited ,
Full ,
2014-05-06 23:38:01 +12:00
}
2023-07-12 17:07:34 -04:00
#[ derive(Clone, Copy, Debug, PartialEq, Hash) ]
pub enum DebugInfoCompression {
None ,
Zlib ,
Zstd ,
}
impl ToString for DebugInfoCompression {
fn to_string ( & self ) -> String {
match self {
DebugInfoCompression ::None = > " none " ,
DebugInfoCompression ::Zlib = > " zlib " ,
DebugInfoCompression ::Zstd = > " zstd " ,
}
. to_owned ( )
}
}
sess/cg: re-introduce split dwarf kind
In #79570, `-Z split-dwarf-kind={none,single,split}` was replaced by `-C
split-debuginfo={off,packed,unpacked}`. `-C split-debuginfo`'s packed
and unpacked aren't exact parallels to single and split, respectively.
On Unix, `-C split-debuginfo=packed` will put debuginfo into object
files and package debuginfo into a DWARF package file (`.dwp`) and
`-C split-debuginfo=unpacked` will put debuginfo into dwarf object files
and won't package it.
In the initial implementation of Split DWARF, split mode wrote sections
which did not require relocation into a DWARF object (`.dwo`) file which
was ignored by the linker and then packaged those DWARF objects into
DWARF packages (`.dwp`). In single mode, sections which did not require
relocation were written into object files but ignored by the linker and
were not packaged. However, both split and single modes could be
packaged or not, the primary difference in behaviour was where the
debuginfo sections that did not require link-time relocation were
written (in a DWARF object or the object file).
This commit re-introduces a `-Z split-dwarf-kind` flag, which can be
used to pick between split and single modes when `-C split-debuginfo` is
used to enable Split DWARF (either packed or unpacked).
Signed-off-by: David Wood <david.wood@huawei.com>
2021-10-08 16:10:17 +00:00
/// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split
/// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform
/// uses DWARF for debug-information.
///
/// Some debug-information requires link-time relocation and some does not. LLVM can partition
/// the debuginfo into sections depending on whether or not it requires link-time relocation. Split
/// DWARF provides a mechanism which allows the linker to skip the sections which don't require
/// link-time relocation - either by putting those sections in DWARF object files, or by keeping
/// them in the object file in such a way that the linker will skip them.
#[ derive(Clone, Copy, Debug, PartialEq, Hash) ]
pub enum SplitDwarfKind {
/// Sections which do not require relocation are written into object file but ignored by the
/// linker.
Single ,
/// Sections which do not require relocation are written into a DWARF object (`.dwo`) file
/// which is ignored by the linker.
Split ,
}
impl FromStr for SplitDwarfKind {
type Err = ( ) ;
fn from_str ( s : & str ) -> Result < Self , ( ) > {
Ok ( match s {
" single " = > SplitDwarfKind ::Single ,
" split " = > SplitDwarfKind ::Split ,
_ = > return Err ( ( ) ) ,
} )
}
}
2022-04-19 10:43:09 +02:00
#[ derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, HashStable_Generic) ]
2020-06-11 15:49:57 +01:00
#[ derive(Encodable, Decodable) ]
2014-11-15 20:30:33 -05:00
pub enum OutputType {
2015-09-30 10:08:37 -07:00
Bitcode ,
Assembly ,
LlvmAssembly ,
2017-02-16 16:59:09 -05:00
Mir ,
2016-12-23 19:39:20 +13:00
Metadata ,
2015-09-30 10:08:37 -07:00
Object ,
Exe ,
DepInfo ,
2014-11-15 20:30:33 -05:00
}
2022-12-02 15:14:49 +01:00
// Safety: Trivial C-Style enums have a stable sort order across compilation sessions.
2023-06-08 00:38:50 -04:00
unsafe impl StableOrd for OutputType {
const CAN_USE_UNSTABLE_SORT : bool = true ;
}
2022-12-02 15:14:49 +01:00
2022-04-19 10:43:09 +02:00
impl < HCX : HashStableContext > ToStableHashKey < HCX > for OutputType {
type KeyType = Self ;
fn to_stable_hash_key ( & self , _ : & HCX ) -> Self ::KeyType {
* self
}
}
2017-09-18 12:14:52 +02:00
2015-12-04 19:35:16 +01:00
impl OutputType {
fn is_compatible_with_codegen_units_and_single_output_file ( & self ) -> bool {
match * self {
2019-04-25 09:06:38 -07:00
OutputType ::Exe | OutputType ::DepInfo | OutputType ::Metadata = > true ,
2018-03-06 02:29:03 -03:00
OutputType ::Bitcode
| OutputType ::Assembly
| OutputType ::LlvmAssembly
| OutputType ::Mir
2019-04-25 09:06:38 -07:00
| OutputType ::Object = > false ,
2015-12-04 19:35:16 +01:00
}
}
2023-02-26 15:27:27 -05:00
pub fn shorthand ( & self ) -> & 'static str {
2015-12-04 19:35:16 +01:00
match * self {
OutputType ::Bitcode = > " llvm-bc " ,
OutputType ::Assembly = > " asm " ,
OutputType ::LlvmAssembly = > " llvm-ir " ,
2017-02-16 16:59:09 -05:00
OutputType ::Mir = > " mir " ,
2015-12-04 19:35:16 +01:00
OutputType ::Object = > " obj " ,
2016-12-23 19:39:20 +13:00
OutputType ::Metadata = > " metadata " ,
2015-12-04 19:35:16 +01:00
OutputType ::Exe = > " link " ,
OutputType ::DepInfo = > " dep-info " ,
}
}
2016-07-25 10:51:14 -04:00
2017-11-05 09:20:59 -05:00
fn from_shorthand ( shorthand : & str ) -> Option < Self > {
Some ( match shorthand {
2018-03-06 02:29:03 -03:00
" asm " = > OutputType ::Assembly ,
" llvm-ir " = > OutputType ::LlvmAssembly ,
" mir " = > OutputType ::Mir ,
" llvm-bc " = > OutputType ::Bitcode ,
" obj " = > OutputType ::Object ,
" metadata " = > OutputType ::Metadata ,
" link " = > OutputType ::Exe ,
" dep-info " = > OutputType ::DepInfo ,
2017-11-05 09:20:59 -05:00
_ = > return None ,
} )
}
fn shorthands_display ( ) -> String {
format! (
" `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}` " ,
OutputType ::Bitcode . shorthand ( ) ,
OutputType ::Assembly . shorthand ( ) ,
OutputType ::LlvmAssembly . shorthand ( ) ,
OutputType ::Mir . shorthand ( ) ,
OutputType ::Object . shorthand ( ) ,
OutputType ::Metadata . shorthand ( ) ,
OutputType ::Exe . shorthand ( ) ,
OutputType ::DepInfo . shorthand ( ) ,
)
}
2016-07-25 10:51:14 -04:00
pub fn extension ( & self ) -> & 'static str {
match * self {
OutputType ::Bitcode = > " bc " ,
OutputType ::Assembly = > " s " ,
OutputType ::LlvmAssembly = > " ll " ,
2017-02-16 16:59:09 -05:00
OutputType ::Mir = > " mir " ,
2016-07-25 10:51:14 -04:00
OutputType ::Object = > " o " ,
2016-12-23 19:39:20 +13:00
OutputType ::Metadata = > " rmeta " ,
2016-07-25 10:51:14 -04:00
OutputType ::DepInfo = > " d " ,
OutputType ::Exe = > " " ,
}
}
2023-02-26 15:27:27 -05:00
pub fn is_text_output ( & self ) -> bool {
match * self {
OutputType ::Assembly
| OutputType ::LlvmAssembly
| OutputType ::Mir
| OutputType ::DepInfo = > true ,
OutputType ::Bitcode | OutputType ::Object | OutputType ::Metadata | OutputType ::Exe = > {
false
}
}
}
2015-12-04 19:35:16 +01:00
}
2019-06-10 10:59:03 +02:00
/// The type of diagnostics output to generate.
2016-10-26 11:14:02 +13:00
#[ derive(Clone, Copy, Debug, PartialEq, Eq) ]
pub enum ErrorOutputType {
2019-06-09 12:04:40 +02:00
/// Output meant for the consumption of humans.
2019-03-25 11:16:58 +01:00
HumanReadable ( HumanReadableErrorType ) ,
2019-06-09 12:04:40 +02:00
/// Output that's consumed by other tools such as `rustfix` or the `RLS`.
2019-03-12 13:06:43 +01:00
Json {
2019-06-10 10:59:03 +02:00
/// Render the JSON in a human readable way (with indents and newlines).
2019-03-12 13:06:43 +01:00
pretty : bool ,
2019-06-09 12:04:40 +02:00
/// The JSON output includes a `rendered` field that includes the rendered
/// human output.
2019-03-25 11:16:58 +01:00
json_rendered : HumanReadableErrorType ,
2019-03-12 13:06:43 +01:00
} ,
2016-10-26 11:14:02 +13:00
}
impl Default for ErrorOutputType {
2019-09-06 03:57:44 +01:00
fn default ( ) -> Self {
Self ::HumanReadable ( HumanReadableErrorType ::Default ( ColorConfig ::Auto ) )
2016-10-26 11:14:02 +13:00
}
}
2023-05-12 02:09:46 +08:00
#[ derive(Clone, Hash, Debug) ]
2023-02-06 21:57:45 +04:00
pub enum ResolveDocLinks {
/// Do not resolve doc links.
None ,
/// Resolve doc links on exported items only for crate types that have metadata.
ExportedMetadata ,
/// Resolve doc links on exported items.
Exported ,
/// Resolve doc links on all items.
All ,
}
2019-09-06 03:57:44 +01:00
/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
2021-06-05 15:43:12 -07:00
/// dependency tracking for command-line arguments. Also only hash keys, since tracking
/// should only depend on the output types, not the paths they're written to.
2023-11-04 15:49:57 +00:00
#[ derive(Clone, Debug, Hash, HashStable_Generic, Encodable, Decodable) ]
2023-02-26 15:27:27 -05:00
pub struct OutputTypes ( BTreeMap < OutputType , Option < OutFileName > > ) ;
2016-08-02 16:53:58 -04:00
impl OutputTypes {
2023-02-26 15:27:27 -05:00
pub fn new ( entries : & [ ( OutputType , Option < OutFileName > ) ] ) -> OutputTypes {
2018-03-06 02:29:03 -03:00
OutputTypes ( BTreeMap ::from_iter ( entries . iter ( ) . map ( | & ( k , ref v ) | ( k , v . clone ( ) ) ) ) )
2016-08-02 16:53:58 -04:00
}
2024-03-19 13:31:28 +11:00
pub ( crate ) fn get ( & self , key : & OutputType ) -> Option < & Option < OutFileName > > {
2016-08-02 16:53:58 -04:00
self . 0. get ( key )
}
pub fn contains_key ( & self , key : & OutputType ) -> bool {
self . 0. contains_key ( key )
}
2024-03-21 16:13:46 -04:00
/// Returns `true` if user specified a name and not just produced type
pub fn contains_explicit_name ( & self , key : & OutputType ) -> bool {
self . 0. get ( key ) . map_or ( false , | f | f . is_some ( ) )
}
2023-02-26 15:27:27 -05:00
pub fn iter ( & self ) -> BTreeMapIter < '_ , OutputType , Option < OutFileName > > {
self . 0. iter ( )
}
pub fn keys ( & self ) -> BTreeMapKeysIter < '_ , OutputType , Option < OutFileName > > {
2016-08-02 16:53:58 -04:00
self . 0. keys ( )
}
2023-02-26 15:27:27 -05:00
pub fn values ( & self ) -> BTreeMapValuesIter < '_ , OutputType , Option < OutFileName > > {
2016-08-02 16:53:58 -04:00
self . 0. values ( )
}
2016-12-29 13:23:38 +13:00
2018-03-28 00:13:34 +01:00
pub fn len ( & self ) -> usize {
self . 0. len ( )
}
sess/cg: re-introduce split dwarf kind
In #79570, `-Z split-dwarf-kind={none,single,split}` was replaced by `-C
split-debuginfo={off,packed,unpacked}`. `-C split-debuginfo`'s packed
and unpacked aren't exact parallels to single and split, respectively.
On Unix, `-C split-debuginfo=packed` will put debuginfo into object
files and package debuginfo into a DWARF package file (`.dwp`) and
`-C split-debuginfo=unpacked` will put debuginfo into dwarf object files
and won't package it.
In the initial implementation of Split DWARF, split mode wrote sections
which did not require relocation into a DWARF object (`.dwo`) file which
was ignored by the linker and then packaged those DWARF objects into
DWARF packages (`.dwp`). In single mode, sections which did not require
relocation were written into object files but ignored by the linker and
were not packaged. However, both split and single modes could be
packaged or not, the primary difference in behaviour was where the
debuginfo sections that did not require link-time relocation were
written (in a DWARF object or the object file).
This commit re-introduces a `-Z split-dwarf-kind` flag, which can be
used to pick between split and single modes when `-C split-debuginfo` is
used to enable Split DWARF (either packed or unpacked).
Signed-off-by: David Wood <david.wood@huawei.com>
2021-10-08 16:10:17 +00:00
/// Returns `true` if any of the output types require codegen or linking.
2018-05-08 16:10:16 +03:00
pub fn should_codegen ( & self ) -> bool {
2016-12-29 13:23:38 +13:00
self . 0. keys ( ) . any ( | k | match * k {
2018-03-06 02:29:03 -03:00
OutputType ::Bitcode
| OutputType ::Assembly
| OutputType ::LlvmAssembly
| OutputType ::Mir
| OutputType ::Object
| OutputType ::Exe = > true ,
OutputType ::Metadata | OutputType ::DepInfo = > false ,
2016-12-29 13:23:38 +13:00
} )
}
2021-01-17 15:06:47 +01:00
sess/cg: re-introduce split dwarf kind
In #79570, `-Z split-dwarf-kind={none,single,split}` was replaced by `-C
split-debuginfo={off,packed,unpacked}`. `-C split-debuginfo`'s packed
and unpacked aren't exact parallels to single and split, respectively.
On Unix, `-C split-debuginfo=packed` will put debuginfo into object
files and package debuginfo into a DWARF package file (`.dwp`) and
`-C split-debuginfo=unpacked` will put debuginfo into dwarf object files
and won't package it.
In the initial implementation of Split DWARF, split mode wrote sections
which did not require relocation into a DWARF object (`.dwo`) file which
was ignored by the linker and then packaged those DWARF objects into
DWARF packages (`.dwp`). In single mode, sections which did not require
relocation were written into object files but ignored by the linker and
were not packaged. However, both split and single modes could be
packaged or not, the primary difference in behaviour was where the
debuginfo sections that did not require link-time relocation were
written (in a DWARF object or the object file).
This commit re-introduces a `-Z split-dwarf-kind` flag, which can be
used to pick between split and single modes when `-C split-debuginfo` is
used to enable Split DWARF (either packed or unpacked).
Signed-off-by: David Wood <david.wood@huawei.com>
2021-10-08 16:10:17 +00:00
/// Returns `true` if any of the output types require linking.
2021-01-17 15:06:47 +01:00
pub fn should_link ( & self ) -> bool {
self . 0. keys ( ) . any ( | k | match * k {
OutputType ::Bitcode
| OutputType ::Assembly
| OutputType ::LlvmAssembly
| OutputType ::Mir
| OutputType ::Metadata
| OutputType ::Object
| OutputType ::DepInfo = > false ,
OutputType ::Exe = > true ,
} )
}
2016-08-02 16:53:58 -04:00
}
2019-09-06 03:57:44 +01:00
/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
/// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That
/// would break dependency tracking for command-line arguments.
2019-10-20 15:54:53 +11:00
#[ derive(Clone) ]
2019-04-07 18:48:40 -04:00
pub struct Externs ( BTreeMap < String , ExternEntry > ) ;
2016-08-02 16:53:58 -04:00
2019-12-05 14:43:53 -08:00
#[ derive(Clone, Debug) ]
2019-03-24 23:06:32 -04:00
pub struct ExternEntry {
2019-12-05 14:43:53 -08:00
pub location : ExternLocation ,
/// Indicates this is a "private" dependency for the
/// `exported_private_dependencies` lint.
///
/// This can be set with the `priv` option like
/// `--extern priv:name=foo.rlib`.
pub is_private_dep : bool ,
/// Add the extern entry to the extern prelude.
///
/// This can be disabled with the `noprelude` option like
/// `--extern noprelude:name`.
pub add_prelude : bool ,
2022-04-14 15:09:00 -07:00
/// The extern entry shouldn't be considered for unused dependency warnings.
///
/// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
/// suppress `unused-crate-dependencies` warnings.
pub nounused_dep : bool ,
2023-03-13 20:55:43 -07:00
/// If the extern entry is not referenced in the crate, force it to be resolved anyway.
///
/// Allows a dependency satisfying, for instance, a missing panic handler to be injected
/// without modifying source:
/// `--extern force:extras=/path/to/lib/libstd.rlib`
pub force : bool ,
2019-12-05 14:43:53 -08:00
}
#[ derive(Clone, Debug) ]
pub enum ExternLocation {
/// Indicates to look for the library in the search paths.
///
/// Added via `--extern name`.
FoundInLibrarySearchDirectories ,
/// The locations where this extern entry must be found.
///
/// The `CrateLoader` is responsible for loading these and figuring out
/// which one to use.
///
/// Added via `--extern prelude_name=some_file.rlib`
2021-01-26 22:27:42 +01:00
ExactPaths ( BTreeSet < CanonicalizedPath > ) ,
2019-03-24 23:06:32 -04:00
}
2019-03-20 23:27:08 -04:00
2016-08-02 16:53:58 -04:00
impl Externs {
2021-03-16 01:50:34 -04:00
/// Used for testing.
2019-04-07 18:48:40 -04:00
pub fn new ( data : BTreeMap < String , ExternEntry > ) -> Externs {
2016-08-02 16:53:58 -04:00
Externs ( data )
}
2019-04-07 18:48:40 -04:00
pub fn get ( & self , key : & str ) -> Option < & ExternEntry > {
2019-03-20 23:27:08 -04:00
self . 0. get ( key )
}
2019-06-21 23:49:03 +02:00
pub fn iter ( & self ) -> BTreeMapIter < '_ , String , ExternEntry > {
2019-03-20 23:27:08 -04:00
self . 0. iter ( )
}
}
2019-12-05 14:43:53 -08:00
impl ExternEntry {
fn new ( location : ExternLocation ) -> ExternEntry {
2023-03-13 20:55:43 -07:00
ExternEntry {
location ,
is_private_dep : false ,
add_prelude : false ,
nounused_dep : false ,
force : false ,
}
2019-12-05 14:43:53 -08:00
}
2021-01-26 22:27:42 +01:00
pub fn files ( & self ) -> Option < impl Iterator < Item = & CanonicalizedPath > > {
2019-12-05 14:43:53 -08:00
match & self . location {
ExternLocation ::ExactPaths ( set ) = > Some ( set . iter ( ) ) ,
_ = > None ,
}
}
}
2019-03-20 23:27:08 -04:00
2023-07-16 17:20:28 -07:00
#[ derive(Clone, PartialEq, Debug) ]
pub struct PrintRequest {
pub kind : PrintKind ,
pub out : OutFileName ,
}
2017-04-30 20:33:25 +02:00
#[ derive(Copy, Clone, PartialEq, Eq, Debug) ]
2023-07-16 17:20:28 -07:00
pub enum PrintKind {
2014-12-15 16:03:39 -08:00
FileNames ,
Sysroot ,
2020-03-01 14:33:52 +03:00
TargetLibdir ,
2014-12-15 16:03:39 -08:00
CrateName ,
2016-01-25 11:36:18 -08:00
Cfg ,
2022-09-08 15:37:15 +02:00
CallingConventions ,
2016-02-12 10:11:58 -05:00
TargetList ,
2016-07-11 00:22:13 +10:00
TargetCPUs ,
TargetFeatures ,
RelocationModels ,
CodeModels ,
2017-10-31 18:24:04 +00:00
TlsModels ,
2016-04-07 16:36:35 -05:00
TargetSpec ,
2023-03-09 14:52:45 +01:00
AllTargetSpecs ,
2017-08-22 21:20:42 +01:00
NativeStaticLibs ,
add rustc option for using LLVM stack smash protection
LLVM has built-in heuristics for adding stack canaries to functions. These
heuristics can be selected with LLVM function attributes. This patch adds a
rustc option `-Z stack-protector={none,basic,strong,all}` which controls the use
of these attributes. This gives rustc the same stack smash protection support as
clang offers through options `-fno-stack-protector`, `-fstack-protector`,
`-fstack-protector-strong`, and `-fstack-protector-all`. The protection this can
offer is demonstrated in test/ui/abi/stack-protector.rs. This fills a gap in the
current list of rustc exploit
mitigations (https://doc.rust-lang.org/rustc/exploit-mitigations.html),
originally discussed in #15179.
Stack smash protection adds runtime overhead and is therefore still off by
default, but now users have the option to trade performance for security as they
see fit. An example use case is adding Rust code in an existing C/C++ code base
compiled with stack smash protection. Without the ability to add stack smash
protection to the Rust code, the code base artifacts could be exploitable in
ways not possible if the code base remained pure C/C++.
Stack smash protection support is present in LLVM for almost all the current
tier 1/tier 2 targets: see
test/assembly/stack-protector/stack-protector-target-support.rs. The one
exception is nvptx64-nvidia-cuda. This patch follows clang's example, and adds a
warning message printed if stack smash protection is used with this target (see
test/ui/stack-protector/warn-stack-protector-unsupported.rs). Support for tier 3
targets has not been checked.
Since the heuristics are applied at the LLVM level, the heuristics are expected
to add stack smash protection to a fraction of functions comparable to C/C++.
Some experiments demonstrating how Rust code is affected by the different
heuristics can be found in
test/assembly/stack-protector/stack-protector-heuristics-effect.rs. There is
potential for better heuristics using Rust-specific safety information. For
example it might be reasonable to skip stack smash protection in functions which
transitively only use safe Rust code, or which uses only a subset of functions
the user declares safe (such as anything under `std.*`). Such alternative
heuristics could be added at a later point.
LLVM also offers a "safestack" sanitizer as an alternative way to guard against
stack smashing (see #26612). This could possibly also be included as a
stack-protection heuristic. An alternative is to add it as a sanitizer (#39699).
This is what clang does: safestack is exposed with option
`-fsanitize=safe-stack`.
The options are only supported by the LLVM backend, but as with other codegen
options it is visible in the main codegen option help menu. The heuristic names
"basic", "strong", and "all" are hopefully sufficiently generic to be usable in
other backends as well.
Reviewed-by: Nikita Popov <nikic@php.net>
Extra commits during review:
- [address-review] make the stack-protector option unstable
- [address-review] reduce detail level of stack-protector option help text
- [address-review] correct grammar in comment
- [address-review] use compiler flag to avoid merging functions in test
- [address-review] specify min LLVM version in fortanix stack-protector test
Only for Fortanix test, since this target specifically requests the
`--x86-experimental-lvi-inline-asm-hardening` flag.
- [address-review] specify required LLVM components in stack-protector tests
- move stack protector option enum closer to other similar option enums
- rustc_interface/tests: sort debug option list in tracking hash test
- add an explicit `none` stack-protector option
Revert "set LLVM requirements for all stack protector support test revisions"
This reverts commit a49b74f92a4e7d701d6f6cf63d207a8aff2e0f68.
2021-04-06 21:37:49 +02:00
StackProtectorStrategies ,
2021-12-06 14:09:24 -08:00
LinkArgs ,
2022-11-07 15:21:35 +01:00
SplitDebuginfo ,
2022-12-05 23:15:16 -06:00
DeploymentTarget ,
2014-12-15 16:03:39 -08:00
}
2023-01-02 23:12:47 +00:00
#[ derive(Debug, Copy, Clone, Hash, PartialEq, Eq) ]
2023-12-14 13:00:23 +01:00
pub struct NextSolverConfig {
/// Whether the new trait solver should be enabled in coherence.
pub coherence : bool ,
/// Whether the new trait solver should be enabled everywhere.
/// This is only `true` if `coherence` is also enabled.
pub globally : bool ,
/// Whether to dump proof trees after computing a proof tree.
pub dump_tree : DumpSolverProofTree ,
2023-01-02 23:12:47 +00:00
}
2023-07-03 21:00:10 +01:00
#[ derive(Default, Debug, Copy, Clone, Hash, PartialEq, Eq) ]
2023-07-04 14:56:05 +01:00
pub enum DumpSolverProofTree {
2023-07-03 21:00:10 +01:00
Always ,
OnError ,
2023-07-04 14:56:05 +01:00
#[ default ]
Never ,
2023-07-03 21:00:10 +01:00
}
2014-11-27 07:21:26 -05:00
pub enum Input {
2019-09-06 03:57:44 +01:00
/// Load source code from a file.
2015-02-26 21:00:43 -08:00
File ( PathBuf ) ,
2019-09-06 03:57:44 +01:00
/// Load source code from a string.
2016-03-10 04:49:40 +01:00
Str {
2019-09-06 03:57:44 +01:00
/// A string that is shown in place of a filename.
2017-12-14 08:09:19 +01:00
name : FileName ,
2019-09-06 03:57:44 +01:00
/// An anonymous string containing the source code.
2016-03-10 04:49:40 +01:00
input : String ,
} ,
2014-11-27 07:21:26 -05:00
}
impl Input {
2018-10-10 15:30:53 +02:00
pub fn filestem ( & self ) -> & str {
2014-11-27 07:21:26 -05:00
match * self {
2018-10-10 15:30:53 +02:00
Input ::File ( ref ifile ) = > ifile . file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ,
Input ::Str { .. } = > " rust_out " ,
2014-11-27 07:21:26 -05:00
}
}
2018-05-10 20:13:25 +02:00
2018-12-08 20:30:23 +01:00
pub fn source_name ( & self ) -> FileName {
match * self {
Input ::File ( ref ifile ) = > ifile . clone ( ) . into ( ) ,
Input ::Str { ref name , .. } = > name . clone ( ) ,
}
}
2022-12-06 18:56:28 +00:00
2023-01-16 14:27:33 +00:00
pub fn opt_path ( & self ) -> Option < & Path > {
2022-12-06 18:56:28 +00:00
match self {
2023-01-16 14:27:33 +00:00
Input ::File ( file ) = > Some ( file ) ,
2022-12-06 18:56:28 +00:00
Input ::Str { name , .. } = > match name {
2023-01-16 14:27:33 +00:00
FileName ::Real ( real ) = > real . local_path ( ) ,
2022-12-06 18:56:28 +00:00
FileName ::QuoteExpansion ( _ ) = > None ,
FileName ::Anon ( _ ) = > None ,
FileName ::MacroExpansion ( _ ) = > None ,
FileName ::ProcMacroSourceCode ( _ ) = > None ,
FileName ::CliCrateAttr ( _ ) = > None ,
FileName ::Custom ( _ ) = > None ,
2023-01-16 14:27:33 +00:00
FileName ::DocTest ( path , _ ) = > Some ( path ) ,
2022-12-06 18:56:28 +00:00
FileName ::InlineAsm ( _ ) = > None ,
} ,
}
}
2014-11-27 07:21:26 -05:00
}
2023-11-04 15:49:57 +00:00
#[ derive(Clone, Hash, Debug, HashStable_Generic, PartialEq, Encodable, Decodable) ]
2023-02-26 15:27:27 -05:00
pub enum OutFileName {
Real ( PathBuf ) ,
Stdout ,
}
impl OutFileName {
pub fn parent ( & self ) -> Option < & Path > {
match * self {
OutFileName ::Real ( ref path ) = > path . parent ( ) ,
OutFileName ::Stdout = > None ,
}
}
pub fn filestem ( & self ) -> Option < & OsStr > {
match * self {
OutFileName ::Real ( ref path ) = > path . file_stem ( ) ,
OutFileName ::Stdout = > Some ( OsStr ::new ( " stdout " ) ) ,
}
}
pub fn is_stdout ( & self ) -> bool {
match * self {
OutFileName ::Real ( _ ) = > false ,
OutFileName ::Stdout = > true ,
}
}
pub fn is_tty ( & self ) -> bool {
2023-07-26 18:09:50 +03:00
use std ::io ::IsTerminal ;
2023-02-26 15:27:27 -05:00
match * self {
OutFileName ::Real ( _ ) = > false ,
2023-07-26 18:09:50 +03:00
OutFileName ::Stdout = > std ::io ::stdout ( ) . is_terminal ( ) ,
2023-02-26 15:27:27 -05:00
}
}
pub fn as_path ( & self ) -> & Path {
match * self {
OutFileName ::Real ( ref path ) = > path . as_ref ( ) ,
2023-11-21 20:07:32 +01:00
OutFileName ::Stdout = > Path ::new ( " stdout " ) ,
2023-02-26 15:27:27 -05:00
}
}
/// For a given output filename, return the actual name of the file that
/// can be used to write codegen data of type `flavor`. For real-path
/// output filenames, this would be trivial as we can just use the path.
/// Otherwise for stdout, return a temporary path so that the codegen data
/// may be later copied to stdout.
pub fn file_for_writing (
& self ,
outputs : & OutputFilenames ,
flavor : OutputType ,
codegen_unit_name : Option < & str > ,
) -> PathBuf {
match * self {
OutFileName ::Real ( ref path ) = > path . clone ( ) ,
OutFileName ::Stdout = > outputs . temp_path ( flavor , codegen_unit_name ) ,
}
}
2023-07-16 22:13:08 -07:00
pub fn overwrite ( & self , content : & str , sess : & Session ) {
match self {
OutFileName ::Stdout = > print! ( " {content} " ) ,
OutFileName ::Real ( path ) = > {
if let Err ( e ) = fs ::write ( path , content ) {
2023-12-18 22:21:37 +11:00
sess . dcx ( ) . emit_fatal ( FileWriteFail { path , err : e . to_string ( ) } ) ;
2023-07-16 22:13:08 -07:00
}
}
}
}
2023-02-26 15:27:27 -05:00
}
2023-11-04 15:49:57 +00:00
#[ derive(Clone, Hash, Debug, HashStable_Generic, Encodable, Decodable) ]
2014-11-27 07:21:26 -05:00
pub struct OutputFilenames {
2024-03-19 13:31:28 +11:00
pub ( crate ) out_directory : PathBuf ,
2023-08-11 06:20:35 +02:00
/// Crate name. Never contains '-'.
crate_stem : String ,
/// Typically based on `.rs` input file name. Any '-' is preserved.
2020-01-21 09:54:58 -05:00
filestem : String ,
2023-02-26 15:27:27 -05:00
pub single_output_file : Option < OutFileName > ,
2024-03-19 13:31:28 +11:00
temps_directory : Option < PathBuf > ,
2016-08-02 16:53:58 -04:00
pub outputs : OutputTypes ,
2014-11-27 07:21:26 -05:00
}
2020-01-23 21:48:48 +11:00
pub const RLINK_EXT : & str = " rlink " ;
2017-11-03 22:41:15 +03:00
pub const RUST_CGU_EXT : & str = " rcgu " ;
2020-09-23 17:33:54 +01:00
pub const DWARF_OBJECT_EXT : & str = " dwo " ;
2016-05-13 20:48:32 -04:00
2014-11-27 07:21:26 -05:00
impl OutputFilenames {
2020-01-21 09:50:22 -05:00
pub fn new (
out_directory : PathBuf ,
2023-08-11 06:20:35 +02:00
out_crate_name : String ,
2020-01-21 09:50:22 -05:00
out_filestem : String ,
2023-02-26 15:27:27 -05:00
single_output_file : Option < OutFileName > ,
2021-11-02 22:41:34 +01:00
temps_directory : Option < PathBuf > ,
2020-01-21 09:50:22 -05:00
extra : String ,
outputs : OutputTypes ,
) -> Self {
2020-01-21 09:54:58 -05:00
OutputFilenames {
out_directory ,
single_output_file ,
2021-11-02 22:41:34 +01:00
temps_directory ,
2020-01-21 09:54:58 -05:00
outputs ,
2023-08-11 06:20:35 +02:00
crate_stem : format ! ( " {out_crate_name}{extra} " ) ,
2022-03-24 22:11:05 -07:00
filestem : format ! ( " {out_filestem}{extra} " ) ,
2020-01-21 09:54:58 -05:00
}
2020-01-21 09:50:22 -05:00
}
2023-02-26 15:27:27 -05:00
pub fn path ( & self , flavor : OutputType ) -> OutFileName {
2018-03-06 02:29:03 -03:00
self . outputs
. get ( & flavor )
. and_then ( | p | p . to_owned ( ) )
2015-09-30 10:08:37 -07:00
. or_else ( | | self . single_output_file . clone ( ) )
2023-02-26 15:27:27 -05:00
. unwrap_or_else ( | | OutFileName ::Real ( self . output_path ( flavor ) ) )
2021-04-04 13:35:04 +02:00
}
/// Gets the output path where a compilation artifact of the given type
/// should be placed on disk.
2024-03-19 13:31:28 +11:00
fn output_path ( & self , flavor : OutputType ) -> PathBuf {
2021-04-04 13:35:04 +02:00
let extension = flavor . extension ( ) ;
2023-08-11 06:20:35 +02:00
match flavor {
OutputType ::Metadata = > {
self . out_directory . join ( format! ( " lib {} . {} " , self . crate_stem , extension ) )
}
_ = > self . with_directory_and_extension ( & self . out_directory , extension ) ,
}
2014-11-27 07:21:26 -05:00
}
2019-02-08 14:53:55 +01:00
/// Gets the path where a compilation artifact of the given type for the
2016-05-13 20:48:32 -04:00
/// given codegen unit should be placed on disk. If codegen_unit_name is
/// None, a path distinct from those of any codegen unit will be generated.
2018-03-06 02:29:03 -03:00
pub fn temp_path ( & self , flavor : OutputType , codegen_unit_name : Option < & str > ) -> PathBuf {
2016-07-25 10:51:14 -04:00
let extension = flavor . extension ( ) ;
2016-05-13 20:48:32 -04:00
self . temp_path_ext ( extension , codegen_unit_name )
}
2020-09-23 17:33:54 +01:00
/// Like `temp_path`, but specifically for dwarf objects.
pub fn temp_path_dwo ( & self , codegen_unit_name : Option < & str > ) -> PathBuf {
self . temp_path_ext ( DWARF_OBJECT_EXT , codegen_unit_name )
}
/// Like `temp_path`, but also supports things where there is no corresponding
2019-02-08 14:53:55 +01:00
/// OutputType, like noopt-bitcode or lto-bitcode.
2018-03-06 02:29:03 -03:00
pub fn temp_path_ext ( & self , ext : & str , codegen_unit_name : Option < & str > ) -> PathBuf {
2016-05-13 20:48:32 -04:00
let mut extension = String ::new ( ) ;
if let Some ( codegen_unit_name ) = codegen_unit_name {
rustc: Implement ThinLTO
This commit is an implementation of LLVM's ThinLTO for consumption in rustc
itself. Currently today LTO works by merging all relevant LLVM modules into one
and then running optimization passes. "Thin" LTO operates differently by having
more sharded work and allowing parallelism opportunities between optimizing
codegen units. Further down the road Thin LTO also allows *incremental* LTO
which should enable even faster release builds without compromising on the
performance we have today.
This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then
also implements two forms of ThinLTO:
* In one mode we'll *only* perform ThinLTO over the codegen units produced in a
single compilation. That is, we won't load upstream rlibs, but we'll instead
just perform ThinLTO amongst all codegen units produced by the compiler for
the local crate. This is intended to emulate a desired end point where we have
codegen units turned on by default for all crates and ThinLTO allows us to do
this without performance loss.
* In anther mode, like full LTO today, we'll optimize all upstream dependencies
in "thin" mode. Unlike today, however, this LTO step is fully parallelized so
should finish much more quickly.
There's a good bit of comments about what the implementation is doing and where
it came from, but the tl;dr; is that currently most of the support here is
copied from upstream LLVM. This code duplication is done for a number of
reasons:
* Controlling parallelism means we can use the existing jobserver support to
avoid overloading machines.
* We will likely want a slightly different form of incremental caching which
integrates with our own incremental strategy, but this is yet to be
determined.
* This buys us some flexibility about when/where we run ThinLTO, as well as
having it tailored to fit our needs for the time being.
* Finally this allows us to reuse some artifacts such as our `TargetMachine`
creation, where all our options we used today aren't necessarily supported by
upstream LLVM yet.
My hope is that we can get some experience with this copy/paste in tree and then
eventually upstream some work to LLVM itself to avoid the duplication while
still ensuring our needs are met. Otherwise I fear that maintaining these
bindings may be quite costly over the years with LLVM updates!
2017-07-23 08:14:38 -07:00
extension . push_str ( codegen_unit_name ) ;
2014-11-27 07:21:26 -05:00
}
2016-05-13 20:48:32 -04:00
if ! ext . is_empty ( ) {
if ! extension . is_empty ( ) {
2020-09-10 13:57:40 +02:00
extension . push ( '.' ) ;
rustc: Implement ThinLTO
This commit is an implementation of LLVM's ThinLTO for consumption in rustc
itself. Currently today LTO works by merging all relevant LLVM modules into one
and then running optimization passes. "Thin" LTO operates differently by having
more sharded work and allowing parallelism opportunities between optimizing
codegen units. Further down the road Thin LTO also allows *incremental* LTO
which should enable even faster release builds without compromising on the
performance we have today.
This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then
also implements two forms of ThinLTO:
* In one mode we'll *only* perform ThinLTO over the codegen units produced in a
single compilation. That is, we won't load upstream rlibs, but we'll instead
just perform ThinLTO amongst all codegen units produced by the compiler for
the local crate. This is intended to emulate a desired end point where we have
codegen units turned on by default for all crates and ThinLTO allows us to do
this without performance loss.
* In anther mode, like full LTO today, we'll optimize all upstream dependencies
in "thin" mode. Unlike today, however, this LTO step is fully parallelized so
should finish much more quickly.
There's a good bit of comments about what the implementation is doing and where
it came from, but the tl;dr; is that currently most of the support here is
copied from upstream LLVM. This code duplication is done for a number of
reasons:
* Controlling parallelism means we can use the existing jobserver support to
avoid overloading machines.
* We will likely want a slightly different form of incremental caching which
integrates with our own incremental strategy, but this is yet to be
determined.
* This buys us some flexibility about when/where we run ThinLTO, as well as
having it tailored to fit our needs for the time being.
* Finally this allows us to reuse some artifacts such as our `TargetMachine`
creation, where all our options we used today aren't necessarily supported by
upstream LLVM yet.
My hope is that we can get some experience with this copy/paste in tree and then
eventually upstream some work to LLVM itself to avoid the duplication while
still ensuring our needs are met. Otherwise I fear that maintaining these
bindings may be quite costly over the years with LLVM updates!
2017-07-23 08:14:38 -07:00
extension . push_str ( RUST_CGU_EXT ) ;
2020-09-10 13:57:40 +02:00
extension . push ( '.' ) ;
2016-05-13 20:48:32 -04:00
}
extension . push_str ( ext ) ;
}
2021-11-02 22:41:34 +01:00
let temps_directory = self . temps_directory . as_ref ( ) . unwrap_or ( & self . out_directory ) ;
2022-11-29 11:01:17 +00:00
self . with_directory_and_extension ( temps_directory , & extension )
2014-11-27 07:21:26 -05:00
}
2015-02-26 21:00:43 -08:00
pub fn with_extension ( & self , extension : & str ) -> PathBuf {
2021-11-02 22:41:34 +01:00
self . with_directory_and_extension ( & self . out_directory , extension )
}
fn with_directory_and_extension ( & self , directory : & PathBuf , extension : & str ) -> PathBuf {
let mut path = directory . join ( & self . filestem ) ;
2020-01-21 09:57:50 -05:00
path . set_extension ( extension ) ;
path
2014-11-27 07:21:26 -05:00
}
2020-09-23 17:33:54 +01:00
/// Returns the path for the Split DWARF file - this can differ depending on which Split DWARF
/// mode is being used, which is the logic that this function is intended to encapsulate.
2020-11-08 17:17:37 +00:00
pub fn split_dwarf_path (
2020-09-23 17:33:54 +01:00
& self ,
2020-11-30 08:39:08 -08:00
split_debuginfo_kind : SplitDebuginfo ,
sess/cg: re-introduce split dwarf kind
In #79570, `-Z split-dwarf-kind={none,single,split}` was replaced by `-C
split-debuginfo={off,packed,unpacked}`. `-C split-debuginfo`'s packed
and unpacked aren't exact parallels to single and split, respectively.
On Unix, `-C split-debuginfo=packed` will put debuginfo into object
files and package debuginfo into a DWARF package file (`.dwp`) and
`-C split-debuginfo=unpacked` will put debuginfo into dwarf object files
and won't package it.
In the initial implementation of Split DWARF, split mode wrote sections
which did not require relocation into a DWARF object (`.dwo`) file which
was ignored by the linker and then packaged those DWARF objects into
DWARF packages (`.dwp`). In single mode, sections which did not require
relocation were written into object files but ignored by the linker and
were not packaged. However, both split and single modes could be
packaged or not, the primary difference in behaviour was where the
debuginfo sections that did not require link-time relocation were
written (in a DWARF object or the object file).
This commit re-introduces a `-Z split-dwarf-kind` flag, which can be
used to pick between split and single modes when `-C split-debuginfo` is
used to enable Split DWARF (either packed or unpacked).
Signed-off-by: David Wood <david.wood@huawei.com>
2021-10-08 16:10:17 +00:00
split_dwarf_kind : SplitDwarfKind ,
2020-09-23 17:33:54 +01:00
cgu_name : Option < & str > ,
) -> Option < PathBuf > {
let obj_out = self . temp_path ( OutputType ::Object , cgu_name ) ;
let dwo_out = self . temp_path_dwo ( cgu_name ) ;
sess/cg: re-introduce split dwarf kind
In #79570, `-Z split-dwarf-kind={none,single,split}` was replaced by `-C
split-debuginfo={off,packed,unpacked}`. `-C split-debuginfo`'s packed
and unpacked aren't exact parallels to single and split, respectively.
On Unix, `-C split-debuginfo=packed` will put debuginfo into object
files and package debuginfo into a DWARF package file (`.dwp`) and
`-C split-debuginfo=unpacked` will put debuginfo into dwarf object files
and won't package it.
In the initial implementation of Split DWARF, split mode wrote sections
which did not require relocation into a DWARF object (`.dwo`) file which
was ignored by the linker and then packaged those DWARF objects into
DWARF packages (`.dwp`). In single mode, sections which did not require
relocation were written into object files but ignored by the linker and
were not packaged. However, both split and single modes could be
packaged or not, the primary difference in behaviour was where the
debuginfo sections that did not require link-time relocation were
written (in a DWARF object or the object file).
This commit re-introduces a `-Z split-dwarf-kind` flag, which can be
used to pick between split and single modes when `-C split-debuginfo` is
used to enable Split DWARF (either packed or unpacked).
Signed-off-by: David Wood <david.wood@huawei.com>
2021-10-08 16:10:17 +00:00
match ( split_debuginfo_kind , split_dwarf_kind ) {
( SplitDebuginfo ::Off , SplitDwarfKind ::Single | SplitDwarfKind ::Split ) = > None ,
2020-09-23 17:33:54 +01:00
// Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes
// (pointing at the path which is being determined here). Use the path to the current
// object file.
sess/cg: re-introduce split dwarf kind
In #79570, `-Z split-dwarf-kind={none,single,split}` was replaced by `-C
split-debuginfo={off,packed,unpacked}`. `-C split-debuginfo`'s packed
and unpacked aren't exact parallels to single and split, respectively.
On Unix, `-C split-debuginfo=packed` will put debuginfo into object
files and package debuginfo into a DWARF package file (`.dwp`) and
`-C split-debuginfo=unpacked` will put debuginfo into dwarf object files
and won't package it.
In the initial implementation of Split DWARF, split mode wrote sections
which did not require relocation into a DWARF object (`.dwo`) file which
was ignored by the linker and then packaged those DWARF objects into
DWARF packages (`.dwp`). In single mode, sections which did not require
relocation were written into object files but ignored by the linker and
were not packaged. However, both split and single modes could be
packaged or not, the primary difference in behaviour was where the
debuginfo sections that did not require link-time relocation were
written (in a DWARF object or the object file).
This commit re-introduces a `-Z split-dwarf-kind` flag, which can be
used to pick between split and single modes when `-C split-debuginfo` is
used to enable Split DWARF (either packed or unpacked).
Signed-off-by: David Wood <david.wood@huawei.com>
2021-10-08 16:10:17 +00:00
( SplitDebuginfo ::Packed | SplitDebuginfo ::Unpacked , SplitDwarfKind ::Single ) = > {
Some ( obj_out )
}
2020-09-23 17:33:54 +01:00
// Split mode emits the DWARF into a different file, use that path.
sess/cg: re-introduce split dwarf kind
In #79570, `-Z split-dwarf-kind={none,single,split}` was replaced by `-C
split-debuginfo={off,packed,unpacked}`. `-C split-debuginfo`'s packed
and unpacked aren't exact parallels to single and split, respectively.
On Unix, `-C split-debuginfo=packed` will put debuginfo into object
files and package debuginfo into a DWARF package file (`.dwp`) and
`-C split-debuginfo=unpacked` will put debuginfo into dwarf object files
and won't package it.
In the initial implementation of Split DWARF, split mode wrote sections
which did not require relocation into a DWARF object (`.dwo`) file which
was ignored by the linker and then packaged those DWARF objects into
DWARF packages (`.dwp`). In single mode, sections which did not require
relocation were written into object files but ignored by the linker and
were not packaged. However, both split and single modes could be
packaged or not, the primary difference in behaviour was where the
debuginfo sections that did not require link-time relocation were
written (in a DWARF object or the object file).
This commit re-introduces a `-Z split-dwarf-kind` flag, which can be
used to pick between split and single modes when `-C split-debuginfo` is
used to enable Split DWARF (either packed or unpacked).
Signed-off-by: David Wood <david.wood@huawei.com>
2021-10-08 16:10:17 +00:00
( SplitDebuginfo ::Packed | SplitDebuginfo ::Unpacked , SplitDwarfKind ::Split ) = > {
Some ( dwo_out )
}
2020-09-23 17:33:54 +01:00
}
}
2014-11-27 07:21:26 -05:00
}
2023-08-23 11:18:20 +02:00
bitflags ::bitflags! {
/// Scopes used to determined if it need to apply to --remap-path-prefix
2023-12-30 17:09:02 +01:00
#[ derive(Clone, Copy, PartialEq, Eq, Hash) ]
2023-08-23 11:18:20 +02:00
pub struct RemapPathScopeComponents : u8 {
/// Apply remappings to the expansion of std::file!() macro
const MACRO = 1 < < 0 ;
/// Apply remappings to printed compiler diagnostics
const DIAGNOSTICS = 1 < < 1 ;
2024-03-19 13:51:22 +01:00
/// Apply remappings to debug informations
const DEBUGINFO = 1 < < 3 ;
/// An alias for `macro` and `debuginfo`. This ensures all paths in compiled
/// executables or libraries are remapped but not elsewhere.
const OBJECT = Self ::MACRO . bits ( ) | Self ::DEBUGINFO . bits ( ) ;
2023-08-23 11:18:20 +02:00
}
}
2014-11-15 20:30:33 -05:00
pub fn host_triple ( ) -> & 'static str {
// Get the host triple out of the build environment. This ensures that our
// idea of the host triple is the same as for the set of libraries we've
2022-11-16 20:34:16 +00:00
// actually built. We can't just take LLVM's host triple because they
2014-11-15 20:30:33 -05:00
// normalize all ix86 architectures to i386.
//
// Instead of grabbing the host triple (for the current host), we grab (at
// compile time) the target triple that this rustc is built with and
// calling that (at runtime) the host triple.
2018-03-06 02:29:03 -03:00
( option_env! ( " CFG_COMPILER_HOST_TRIPLE " ) ) . expect ( " CFG_COMPILER_HOST_TRIPLE " )
2014-11-15 20:30:33 -05:00
}
2023-08-23 15:46:58 +02:00
fn file_path_mapping (
remap_path_prefix : Vec < ( PathBuf , PathBuf ) > ,
unstable_opts : & UnstableOptions ,
) -> FilePathMapping {
FilePathMapping ::new (
remap_path_prefix . clone ( ) ,
if unstable_opts . remap_path_scope . contains ( RemapPathScopeComponents ::DIAGNOSTICS )
& & ! remap_path_prefix . is_empty ( )
{
FileNameDisplayPreference ::Remapped
} else {
FileNameDisplayPreference ::Local
} ,
)
}
2018-07-26 12:36:11 -06:00
impl Default for Options {
fn default ( ) -> Options {
Options {
2021-10-31 17:05:48 -05:00
assert_incr_state : None ,
2018-07-26 12:36:11 -06:00
crate_types : Vec ::new ( ) ,
optimize : OptLevel ::No ,
debuginfo : DebugInfo ::None ,
2023-07-12 17:07:34 -04:00
debuginfo_compression : DebugInfoCompression ::None ,
2018-07-26 12:36:11 -06:00
lint_opts : Vec ::new ( ) ,
lint_cap : None ,
describe_lints : false ,
output_types : OutputTypes ( BTreeMap ::new ( ) ) ,
2018-11-22 16:33:07 +11:00
search_paths : vec ! [ ] ,
2018-07-26 12:36:11 -06:00
maybe_sysroot : None ,
target_triple : TargetTriple ::from_triple ( host_triple ( ) ) ,
test : false ,
incremental : None ,
2023-10-13 17:28:34 +00:00
untracked_state_hash : Default ::default ( ) ,
2022-07-06 07:44:47 -05:00
unstable_opts : Default ::default ( ) ,
2018-07-26 12:36:11 -06:00
prints : Vec ::new ( ) ,
2021-05-07 15:18:19 +03:00
cg : Default ::default ( ) ,
2018-07-26 12:36:11 -06:00
error_format : ErrorOutputType ::default ( ) ,
2022-07-06 11:57:41 +01:00
diagnostic_width : None ,
2018-07-26 12:36:11 -06:00
externs : Externs ( BTreeMap ::new ( ) ) ,
crate_name : None ,
libs : Vec ::new ( ) ,
unstable_features : UnstableFeatures ::Disallow ,
debug_assertions : true ,
actually_rustdoc : false ,
2023-02-06 21:57:45 +04:00
resolve_doc_links : ResolveDocLinks ::None ,
2024-01-10 12:47:22 +11:00
trimmed_def_paths : false ,
2018-07-26 12:36:11 -06:00
cli_forced_codegen_units : None ,
2022-10-26 20:28:25 -04:00
cli_forced_local_thinlto_off : false ,
2018-07-26 12:36:11 -06:00
remap_path_prefix : Vec ::new ( ) ,
2021-04-27 16:25:12 +00:00
real_rust_source_base_dir : None ,
2018-07-26 12:36:11 -06:00
edition : DEFAULT_EDITION ,
2019-07-17 12:52:56 -07:00
json_artifact_notifications : false ,
2022-04-16 17:11:33 -07:00
json_unused_externs : JsonUnusedExterns ::No ,
2021-12-04 14:34:20 -05:00
json_future_incompat : false ,
2019-11-03 21:42:03 -05:00
pretty : None ,
2021-08-12 15:30:40 -05:00
working_dir : RealFileName ::LocalPath ( std ::env ::current_dir ( ) . unwrap ( ) ) ,
Add a simple markdown parser for formatting `rustc --explain`
Currently, the output of `rustc --explain foo` displays the raw markdown in a
pager. This is acceptable, but using actual formatting makes it easier to
understand.
This patch consists of three major components:
1. A markdown parser. This is an extremely simple non-backtracking recursive
implementation that requires normalization of the final token stream
2. A utility to write the token stream to an output buffer
3. Configuration within rustc_driver_impl to invoke this combination for
`--explain`. Like the current implementation, it first attempts to print to
a pager with a fallback colorized terminal, and standard print as a last
resort.
If color is disabled, or if the output does not support it, or if printing
with color fails, it will write the raw markdown (which matches current
behavior).
Pagers known to support color are: `less` (with `-r`), `bat` (aka `catbat`),
and `delta`.
The markdown parser does not support the entire markdown specification, but
should support the following with reasonable accuracy:
- Headings, including formatting
- Comments
- Code, inline and fenced block (no indented block)
- Strong, emphasis, and strikethrough formatted text
- Links, anchor, inline, and reference-style
- Horizontal rules
- Unordered and ordered list items, including formatting
This parser and writer should be reusable by other systems if ever needed.
2022-12-19 12:09:40 -06:00
color : ColorConfig ::Auto ,
2023-11-27 13:47:26 +01:00
logical_env : FxIndexMap ::default ( ) ,
2023-12-19 13:24:05 -05:00
verbose : false ,
2018-07-26 12:36:11 -06:00
}
2014-05-06 23:38:01 +12:00
}
}
2016-03-28 17:43:36 -04:00
impl Options {
2019-02-08 14:53:55 +01:00
/// Returns `true` if there is a reason to build the dep graph.
2016-03-28 17:43:36 -04:00
pub fn build_dep_graph ( & self ) -> bool {
2018-03-06 02:29:03 -03:00
self . incremental . is_some ( )
2022-07-06 07:44:47 -05:00
| | self . unstable_opts . dump_dep_graph
| | self . unstable_opts . query_dep_graph
2016-03-28 17:43:36 -04:00
}
2016-07-13 17:03:02 -04:00
2024-03-19 13:31:28 +11:00
pub ( crate ) fn file_path_mapping ( & self ) -> FilePathMapping {
2023-08-23 15:46:58 +02:00
file_path_mapping ( self . remap_path_prefix . clone ( ) , & self . unstable_opts )
2017-04-24 19:01:19 +02:00
}
2017-12-18 15:35:45 +00:00
2019-09-06 03:57:44 +01:00
/// Returns `true` if there will be an output file generated.
2017-12-18 15:35:45 +00:00
pub fn will_create_output_file ( & self ) -> bool {
2022-07-06 07:44:47 -05:00
! self . unstable_opts . parse_only & & // The file is just being parsed
2023-09-10 13:24:20 +00:00
self . unstable_opts . ls . is_empty ( ) // The file is just being queried
2017-12-18 15:35:45 +00:00
}
2018-07-26 13:20:47 -06:00
#[ inline ]
pub fn share_generics ( & self ) -> bool {
2022-07-06 07:44:47 -05:00
match self . unstable_opts . share_generics {
2018-07-26 13:20:47 -06:00
Some ( setting ) = > setting ,
None = > match self . optimize {
OptLevel ::No | OptLevel ::Less | OptLevel ::Size | OptLevel ::SizeMin = > true ,
OptLevel ::Default | OptLevel ::Aggressive = > false ,
} ,
}
}
2021-10-21 14:02:59 +02:00
pub fn get_symbol_mangling_version ( & self ) -> SymbolManglingVersion {
self . cg . symbol_mangling_version . unwrap_or ( SymbolManglingVersion ::Legacy )
}
2016-03-28 17:43:36 -04:00
}
2022-07-06 07:44:47 -05:00
impl UnstableOptions {
2023-12-18 08:59:22 +11:00
pub fn dcx_flags ( & self , can_emit_warnings : bool ) -> DiagCtxtFlags {
2023-12-18 08:47:03 +11:00
DiagCtxtFlags {
2019-12-29 23:07:23 +03:00
can_emit_warnings ,
treat_err_as_bug : self . treat_err_as_bug ,
2024-01-12 00:30:04 +00:00
eagerly_emit_delayed_bugs : self . eagerly_emit_delayed_bugs ,
2019-12-15 17:12:30 +02:00
macro_backtrace : self . macro_backtrace ,
2020-04-02 16:44:47 +11:00
deduplicate_diagnostics : self . deduplicate_diagnostics ,
2022-10-19 00:08:20 +02:00
track_diagnostics : self . track_diagnostics ,
2019-12-29 23:07:23 +03:00
}
}
2019-12-30 00:23:19 +03:00
}
2019-01-13 13:06:26 +01:00
// The type of entry function, so users can have their own entry functions
2022-04-19 10:43:09 +02:00
#[ derive(Copy, Clone, PartialEq, Hash, Debug, HashStable_Generic) ]
2014-05-06 23:38:01 +12:00
pub enum EntryFnType {
2022-07-05 19:56:22 +02:00
Main {
/// Specifies what to do with `SIGPIPE` before calling `fn main()`.
///
/// What values that are valid and what they mean must be in sync
/// across rustc and libstd, but we don't want it public in libstd,
/// so we take a bit of an unusual approach with simple constants
/// and an `include!()`.
sigpipe : u8 ,
} ,
2018-07-26 11:29:45 -06:00
Start ,
2014-05-06 23:38:01 +12:00
}
2020-06-11 15:49:57 +01:00
#[ derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable) ]
2022-04-19 10:43:09 +02:00
#[ derive(HashStable_Generic) ]
2014-05-06 23:38:01 +12:00
pub enum CrateType {
2018-07-26 11:13:11 -06:00
Executable ,
Dylib ,
Rlib ,
Staticlib ,
Cdylib ,
ProcMacro ,
2014-05-06 23:38:01 +12:00
}
2023-02-06 21:57:45 +04:00
impl CrateType {
pub fn has_metadata ( self ) -> bool {
match self {
CrateType ::Rlib | CrateType ::Dylib | CrateType ::ProcMacro = > true ,
CrateType ::Executable | CrateType ::Cdylib | CrateType ::Staticlib = > false ,
}
}
}
2021-04-15 23:06:32 -04:00
#[ derive(Clone, Hash, Debug, PartialEq, Eq) ]
2014-09-12 08:17:58 -07:00
pub enum Passes {
2018-07-26 11:22:14 -06:00
Some ( Vec < String > ) ,
All ,
2014-09-12 08:17:58 -07:00
}
impl Passes {
2024-03-19 13:31:28 +11:00
fn is_empty ( & self ) -> bool {
2014-09-12 08:17:58 -07:00
match * self {
2018-07-26 11:22:14 -06:00
Passes ::Some ( ref v ) = > v . is_empty ( ) ,
Passes ::All = > false ,
2014-09-12 08:17:58 -07:00
}
}
2021-11-13 00:00:00 +00:00
2024-03-19 13:31:28 +11:00
pub ( crate ) fn extend ( & mut self , passes : impl IntoIterator < Item = String > ) {
2021-11-13 00:00:00 +00:00
match * self {
Passes ::Some ( ref mut v ) = > v . extend ( passes ) ,
Passes ::All = > { }
}
}
2014-09-12 08:17:58 -07:00
}
2021-07-13 12:14:26 +01:00
#[ derive(Clone, Copy, Hash, Debug, PartialEq) ]
pub enum PAuthKey {
A ,
B ,
}
#[ derive(Clone, Copy, Hash, Debug, PartialEq) ]
pub struct PacRet {
pub leaf : bool ,
pub key : PAuthKey ,
}
2022-12-15 00:06:34 +01:00
#[ derive(Clone, Copy, Hash, Debug, PartialEq, Default) ]
2021-07-13 12:14:26 +01:00
pub struct BranchProtection {
pub bti : bool ,
pub pac_ret : Option < PacRet > ,
}
2024-03-19 13:31:28 +11:00
pub ( crate ) const fn default_lib_output ( ) -> CrateType {
2018-07-26 11:13:11 -06:00
CrateType ::Rlib
2014-05-06 23:38:01 +12:00
}
2023-10-30 14:05:06 +11:00
fn default_configuration ( sess : & Session ) -> Cfg {
Clean up config mess.
`parse_cfgspecs` and `parse_check_cfg` run very early, before the main
interner is running. They each use a short-lived interner and convert
all interned symbols to strings in their output data structures. Once
the main interner starts up, these data structures get converted into
new data structures that are identical except with the strings converted
to symbols.
All is not obvious from the current code, which is a mess, particularly
with inconsistent naming that obscures the parallel string/symbol data
structures. This commit clean things up a lot.
- The existing `CheckCfg` type is generic, allowing both
`CheckCfg<String>` and `CheckCfg<Symbol>` forms. This is really
useful, but it defaults to `String`. The commit removes the default so
we have to use `CheckCfg<String>` and `CheckCfg<Symbol>` explicitly,
which makes things clearer.
- Introduces `Cfg`, which is generic over `String` and `Symbol`, similar
to `CheckCfg`.
- Renames some things.
- `parse_cfgspecs` -> `parse_cfg`
- `CfgSpecs` -> `Cfg<String>`, plus it's used in more places, rather
than the underlying `FxHashSet` type.
- `CrateConfig` -> `Cfg<Symbol>`.
- `CrateCheckConfig` -> `CheckCfg<Symbol>`
- Adds some comments explaining the string-to-symbol conversions.
- `to_crate_check_config`, which converts `CheckCfg<String>` to
`CheckCfg<Symbol>`, is inlined and removed and combined with the
overly-general `CheckCfg::map_data` to produce
`CheckCfg::<String>::intern`.
- `build_configuration` now does the `Cfg<String>`-to-`Cfg<Symbol>`
conversion, so callers don't need to, which removes the need for
`to_crate_config`.
The diff for two of the fields in `Config` is a good example of the
improved clarity:
```
- pub crate_cfg: FxHashSet<(String, Option<String>)>,
- pub crate_check_cfg: CheckCfg,
+ pub crate_cfg: Cfg<String>,
+ pub crate_check_cfg: CheckCfg<String>,
```
Compare that with the diff for the corresponding fields in `ParseSess`,
and the relationship to `Config` is much clearer than before:
```
- pub config: CrateConfig,
- pub check_config: CrateCheckConfig,
+ pub config: Cfg<Symbol>,
+ pub check_config: CheckCfg<Symbol>,
```
2023-10-27 15:58:02 +11:00
let mut ret = Cfg ::default ( ) ;
2023-11-29 15:08:43 +11:00
macro_rules ! ins_none {
( $key :expr ) = > {
ret . insert ( ( $key , None ) ) ;
} ;
}
macro_rules ! ins_str {
( $key :expr , $val_str :expr ) = > {
ret . insert ( ( $key , Some ( Symbol ::intern ( $val_str ) ) ) ) ;
} ;
}
macro_rules ! ins_sym {
( $key :expr , $val_sym :expr ) = > {
ret . insert ( ( $key , Some ( $val_sym ) ) ) ;
} ;
}
// Symbols are inserted in alphabetical order as much as possible.
// The exceptions are where control flow forces things out of order.
//
// Run `rustc --print cfg` to see the configuration in practice.
//
// NOTE: These insertions should be kept in sync with
// `CheckCfg::fill_well_known` below.
if sess . opts . debug_assertions {
ins_none! ( sym ::debug_assertions ) ;
2016-12-22 22:20:47 -07:00
}
2023-11-29 15:08:43 +11:00
if sess . overflow_checks ( ) {
ins_none! ( sym ::overflow_checks ) ;
}
ins_sym! ( sym ::panic , sess . panic_strategy ( ) . desc_symbol ( ) ) ;
// JUSTIFICATION: before wrapper fn is available
#[ allow(rustc::bad_opt_access) ]
if sess . opts . crate_types . contains ( & CrateType ::ProcMacro ) {
ins_none! ( sym ::proc_macro ) ;
}
2023-07-22 17:16:18 +02:00
if sess . is_nightly_build ( ) {
2023-11-29 15:08:43 +11:00
ins_sym! ( sym ::relocation_model , sess . target . relocation_model . desc_symbol ( ) ) ;
2023-07-22 17:16:18 +02:00
}
2023-11-29 15:08:43 +11:00
for mut s in sess . opts . unstable_opts . sanitizer {
// KASAN is still ASAN under the hood, so it uses the same attribute.
if s = = SanitizerSet ::KERNELADDRESS {
s = SanitizerSet ::ADDRESS ;
}
ins_str! ( sym ::sanitize , & s . to_string ( ) ) ;
2015-12-10 12:21:55 -08:00
}
2023-11-29 15:08:43 +11:00
if sess . is_sanitizer_cfi_generalize_pointers_enabled ( ) {
ins_none! ( sym ::sanitizer_cfi_generalize_pointers ) ;
}
if sess . is_sanitizer_cfi_normalize_integers_enabled ( ) {
ins_none! ( sym ::sanitizer_cfi_normalize_integers ) ;
}
ins_str! ( sym ::target_abi , & sess . target . abi ) ;
ins_str! ( sym ::target_arch , & sess . target . arch ) ;
ins_str! ( sym ::target_endian , sess . target . endian . as_str ( ) ) ;
ins_str! ( sym ::target_env , & sess . target . env ) ;
for family in sess . target . families . as_ref ( ) {
ins_str! ( sym ::target_family , family ) ;
if family = = " windows " {
ins_none! ( sym ::windows ) ;
} else if family = = " unix " {
ins_none! ( sym ::unix ) ;
}
}
// `target_has_atomic*`
let layout = sess . target . parse_data_layout ( ) . unwrap_or_else ( | err | {
2023-12-18 22:21:37 +11:00
sess . dcx ( ) . emit_fatal ( err ) ;
2023-11-29 15:08:43 +11:00
} ) ;
2023-01-16 19:13:52 +08:00
let mut has_atomic = false ;
2021-06-14 23:40:09 +02:00
for ( i , align ) in [
2020-09-20 12:09:22 +02:00
( 8 , layout . i8_align . abi ) ,
( 16 , layout . i16_align . abi ) ,
( 32 , layout . i32_align . abi ) ,
( 64 , layout . i64_align . abi ) ,
( 128 , layout . i128_align . abi ) ,
] {
2023-11-29 15:08:43 +11:00
if i > = sess . target . min_atomic_width ( ) & & i < = sess . target . max_atomic_width ( ) {
if ! has_atomic {
has_atomic = true ;
if sess . is_nightly_build ( ) {
if sess . target . atomic_cas {
ins_none! ( sym ::target_has_atomic ) ;
}
ins_none! ( sym ::target_has_atomic_load_store ) ;
}
}
2023-11-29 13:45:50 +11:00
let mut insert_atomic = | sym , align : Align | {
2023-11-29 15:08:43 +11:00
if sess . target . atomic_cas {
ins_sym! ( sym ::target_has_atomic , sym ) ;
2019-10-08 17:09:23 +01:00
}
2020-09-20 12:09:22 +02:00
if align . bits ( ) = = i {
2023-11-29 15:08:43 +11:00
ins_sym! ( sym ::target_has_atomic_equal_alignment , sym ) ;
2020-09-20 12:09:22 +02:00
}
2023-11-29 15:08:43 +11:00
ins_sym! ( sym ::target_has_atomic_load_store , sym ) ;
2019-10-08 17:09:23 +01:00
} ;
2023-11-29 13:45:50 +11:00
insert_atomic ( sym ::integer ( i ) , align ) ;
2023-11-29 15:08:43 +11:00
if sess . target . pointer_width as u64 = = i {
2023-11-29 13:45:50 +11:00
insert_atomic ( sym ::ptr , layout . pointer_align . abi ) ;
2016-04-15 20:16:19 +01:00
}
}
}
2020-06-14 00:00:00 +00:00
2023-11-29 15:08:43 +11:00
ins_str! ( sym ::target_os , & sess . target . os ) ;
ins_sym! ( sym ::target_pointer_width , sym ::integer ( sess . target . pointer_width ) ) ;
2020-07-25 19:02:49 +01:00
2023-11-29 15:08:43 +11:00
if sess . opts . unstable_opts . has_thread_local . unwrap_or ( sess . target . has_thread_local ) {
ins_none! ( sym ::target_thread_local ) ;
2019-10-22 00:00:00 +00:00
}
2020-06-14 00:00:00 +00:00
2023-11-29 15:08:43 +11:00
ins_str! ( sym ::target_vendor , & sess . target . vendor ) ;
2022-12-12 22:42:44 -08:00
2023-11-29 15:08:43 +11:00
// If the user wants a test runner, then add the test cfg.
if sess . is_test_crate ( ) {
ins_none! ( sym ::test ) ;
2022-12-12 22:42:44 -08:00
}
2018-10-10 15:33:10 +02:00
ret
2014-05-06 23:38:01 +12:00
}
Clean up config mess.
`parse_cfgspecs` and `parse_check_cfg` run very early, before the main
interner is running. They each use a short-lived interner and convert
all interned symbols to strings in their output data structures. Once
the main interner starts up, these data structures get converted into
new data structures that are identical except with the strings converted
to symbols.
All is not obvious from the current code, which is a mess, particularly
with inconsistent naming that obscures the parallel string/symbol data
structures. This commit clean things up a lot.
- The existing `CheckCfg` type is generic, allowing both
`CheckCfg<String>` and `CheckCfg<Symbol>` forms. This is really
useful, but it defaults to `String`. The commit removes the default so
we have to use `CheckCfg<String>` and `CheckCfg<Symbol>` explicitly,
which makes things clearer.
- Introduces `Cfg`, which is generic over `String` and `Symbol`, similar
to `CheckCfg`.
- Renames some things.
- `parse_cfgspecs` -> `parse_cfg`
- `CfgSpecs` -> `Cfg<String>`, plus it's used in more places, rather
than the underlying `FxHashSet` type.
- `CrateConfig` -> `Cfg<Symbol>`.
- `CrateCheckConfig` -> `CheckCfg<Symbol>`
- Adds some comments explaining the string-to-symbol conversions.
- `to_crate_check_config`, which converts `CheckCfg<String>` to
`CheckCfg<Symbol>`, is inlined and removed and combined with the
overly-general `CheckCfg::map_data` to produce
`CheckCfg::<String>::intern`.
- `build_configuration` now does the `Cfg<String>`-to-`Cfg<Symbol>`
conversion, so callers don't need to, which removes the need for
`to_crate_config`.
The diff for two of the fields in `Config` is a good example of the
improved clarity:
```
- pub crate_cfg: FxHashSet<(String, Option<String>)>,
- pub crate_check_cfg: CheckCfg,
+ pub crate_cfg: Cfg<String>,
+ pub crate_check_cfg: CheckCfg<String>,
```
Compare that with the diff for the corresponding fields in `ParseSess`,
and the relationship to `Config` is much clearer than before:
```
- pub config: CrateConfig,
- pub check_config: CrateCheckConfig,
+ pub config: Cfg<Symbol>,
+ pub check_config: CheckCfg<Symbol>,
```
2023-10-27 15:58:02 +11:00
/// The parsed `--cfg` options that define the compilation environment of the
2023-10-30 14:05:06 +11:00
/// crate, used to drive conditional compilation.
2023-10-28 09:22:30 +11:00
///
/// An `FxIndexSet` is used to ensure deterministic ordering of error messages
/// relating to `--cfg`.
2023-10-30 14:05:06 +11:00
pub type Cfg = FxIndexSet < ( Symbol , Option < Symbol > ) > ;
2018-12-08 20:30:23 +01:00
2023-10-30 14:05:06 +11:00
/// The parsed `--check-cfg` options.
#[ derive(Default) ]
pub struct CheckCfg {
2023-04-30 14:43:59 +02:00
/// Is well known names activated
pub exhaustive_names : bool ,
2022-02-25 13:43:57 +01:00
/// Is well known values activated
2023-04-30 14:43:59 +02:00
pub exhaustive_values : bool ,
/// All the expected values for a config name
2023-10-30 14:05:06 +11:00
pub expecteds : FxHashMap < Symbol , ExpectedValues < Symbol > > ,
2023-12-13 17:59:33 +01:00
/// Well known names (only used for diagnostics purposes)
pub well_known_names : FxHashSet < Symbol > ,
2021-09-29 02:39:30 +02:00
}
2023-04-30 14:43:59 +02:00
pub enum ExpectedValues < T > {
Some ( FxHashSet < Option < T > > ) ,
Any ,
}
impl < T : Eq + Hash > ExpectedValues < T > {
fn insert ( & mut self , value : T ) -> bool {
match self {
ExpectedValues ::Some ( expecteds ) = > expecteds . insert ( Some ( value ) ) ,
ExpectedValues ::Any = > false ,
}
}
}
impl < T : Eq + Hash > Extend < T > for ExpectedValues < T > {
fn extend < I : IntoIterator < Item = T > > ( & mut self , iter : I ) {
match self {
ExpectedValues ::Some ( expecteds ) = > expecteds . extend ( iter . into_iter ( ) . map ( Some ) ) ,
ExpectedValues ::Any = > { }
}
}
}
impl < ' a , T : Eq + Hash + Copy + ' a > Extend < & ' a T > for ExpectedValues < T > {
fn extend < I : IntoIterator < Item = & ' a T > > ( & mut self , iter : I ) {
match self {
ExpectedValues ::Some ( expecteds ) = > expecteds . extend ( iter . into_iter ( ) . map ( | a | Some ( * a ) ) ) ,
ExpectedValues ::Any = > { }
2021-09-29 02:39:30 +02:00
}
}
}
2023-10-30 14:05:06 +11:00
impl CheckCfg {
2023-04-30 14:43:59 +02:00
pub fn fill_well_known ( & mut self , current_target : & Target ) {
if ! self . exhaustive_values & & ! self . exhaustive_names {
2022-02-25 16:10:26 +01:00
return ;
}
2023-04-30 14:43:59 +02:00
let no_values = | | {
let mut values = FxHashSet ::default ( ) ;
values . insert ( None ) ;
ExpectedValues ::Some ( values )
} ;
let empty_values = | | {
let values = FxHashSet ::default ( ) ;
ExpectedValues ::Some ( values )
} ;
2023-11-29 15:08:43 +11:00
macro_rules ! ins {
2023-12-13 17:59:33 +01:00
( $name :expr , $values :expr ) = > { {
self . well_known_names . insert ( $name ) ;
2023-11-29 15:08:43 +11:00
self . expecteds . entry ( $name ) . or_insert_with ( $values )
2023-12-13 17:59:33 +01:00
} } ;
2023-11-29 15:08:43 +11:00
}
// Symbols are inserted in alphabetical order as much as possible.
// The exceptions are where control flow forces things out of order.
//
// NOTE: This should be kept in sync with `default_configuration`.
// Note that symbols inserted conditionally in `default_configuration`
// are inserted unconditionally here.
2023-12-07 12:04:00 +01:00
//
// When adding a new config here you should also update
// `tests/ui/check-cfg/well-known-values.rs`.
2024-02-15 15:23:07 +01:00
//
// Don't forget to update `src/doc/unstable-book/src/compiler-flags/check-cfg.md`
// in the unstable book as well!
2022-02-25 16:10:26 +01:00
2023-11-29 15:08:43 +11:00
ins! ( sym ::debug_assertions , no_values ) ;
2022-02-25 16:10:26 +01:00
2024-02-15 11:40:22 +01:00
// These four are never set by rustc, but we set them anyway: they
// should not trigger a lint because `cargo clippy`, `cargo doc`,
// `cargo test` and `cargo miri run` (respectively) can set them.
ins! ( sym ::clippy , no_values ) ;
2023-11-29 15:08:43 +11:00
ins! ( sym ::doc , no_values ) ;
ins! ( sym ::doctest , no_values ) ;
ins! ( sym ::miri , no_values ) ;
ins! ( sym ::overflow_checks , no_values ) ;
ins! ( sym ::panic , empty_values ) . extend ( & PanicStrategy ::all ( ) ) ;
ins! ( sym ::proc_macro , no_values ) ;
ins! ( sym ::relocation_model , empty_values ) . extend ( RelocModel ::all ( ) ) ;
2022-02-25 16:10:26 +01:00
let sanitize_values = SanitizerSet ::all ( )
. into_iter ( )
. map ( | sanitizer | Symbol ::intern ( sanitizer . as_str ( ) . unwrap ( ) ) ) ;
2023-11-29 15:08:43 +11:00
ins! ( sym ::sanitize , empty_values ) . extend ( sanitize_values ) ;
2022-02-25 16:10:26 +01:00
2023-11-29 15:08:43 +11:00
ins! ( sym ::sanitizer_cfi_generalize_pointers , no_values ) ;
ins! ( sym ::sanitizer_cfi_normalize_integers , no_values ) ;
2022-04-27 19:11:56 +02:00
2023-12-12 22:17:41 +01:00
ins! ( sym ::target_feature , empty_values ) . extend (
rustc_target ::target_features ::all_known_features ( )
. map ( | ( f , _sb ) | f )
. chain ( rustc_target ::target_features ::RUSTC_SPECIFIC_FEATURES . iter ( ) . cloned ( ) )
. map ( Symbol ::intern ) ,
) ;
2022-02-25 16:10:26 +01:00
2023-11-29 15:08:43 +11:00
// sym::target_*
2022-06-02 15:39:16 +02:00
{
const VALUES : [ & Symbol ; 8 ] = [
2023-11-29 15:08:43 +11:00
& sym ::target_abi ,
2022-06-02 15:39:16 +02:00
& sym ::target_arch ,
& sym ::target_endian ,
& sym ::target_env ,
2023-11-29 15:08:43 +11:00
& sym ::target_family ,
& sym ::target_os ,
2022-06-02 15:39:16 +02:00
& sym ::target_pointer_width ,
2023-11-29 15:08:43 +11:00
& sym ::target_vendor ,
2022-06-02 15:39:16 +02:00
] ;
// Initialize (if not already initialized)
for & e in VALUES {
2023-04-30 14:43:59 +02:00
if ! self . exhaustive_values {
2023-11-29 15:08:43 +11:00
ins! ( e , | | ExpectedValues ::Any ) ;
2023-04-30 14:43:59 +02:00
} else {
2023-11-29 15:08:43 +11:00
ins! ( e , empty_values ) ;
2023-04-30 14:43:59 +02:00
}
2022-06-02 15:39:16 +02:00
}
2023-04-30 14:43:59 +02:00
if self . exhaustive_values {
// Get all values map at once otherwise it would be costly.
// (8 values * 220 targets ~= 1760 times, at the time of writing this comment).
let [
2023-11-29 15:08:43 +11:00
values_target_abi ,
2023-04-30 14:43:59 +02:00
values_target_arch ,
values_target_endian ,
values_target_env ,
2023-11-29 15:08:43 +11:00
values_target_family ,
values_target_os ,
2023-04-30 14:43:59 +02:00
values_target_pointer_width ,
2023-11-29 15:08:43 +11:00
values_target_vendor ,
2023-04-30 14:43:59 +02:00
] = self
. expecteds
. get_many_mut ( VALUES )
. expect ( " unable to get all the check-cfg values buckets " ) ;
for target in TARGETS
. iter ( )
. map ( | target | Target ::expect_builtin ( & TargetTriple ::from_triple ( target ) ) )
. chain ( iter ::once ( current_target . clone ( ) ) )
{
2023-11-29 15:08:43 +11:00
values_target_abi . insert ( Symbol ::intern ( & target . options . abi ) ) ;
2023-04-30 14:43:59 +02:00
values_target_arch . insert ( Symbol ::intern ( & target . arch ) ) ;
values_target_endian . insert ( Symbol ::intern ( target . options . endian . as_str ( ) ) ) ;
values_target_env . insert ( Symbol ::intern ( & target . options . env ) ) ;
2023-11-29 15:08:43 +11:00
values_target_family . extend (
target . options . families . iter ( ) . map ( | family | Symbol ::intern ( family ) ) ,
) ;
values_target_os . insert ( Symbol ::intern ( & target . options . os ) ) ;
2023-04-30 14:43:59 +02:00
values_target_pointer_width . insert ( sym ::integer ( target . pointer_width ) ) ;
2023-11-29 15:08:43 +11:00
values_target_vendor . insert ( Symbol ::intern ( & target . options . vendor ) ) ;
2023-04-30 14:43:59 +02:00
}
2022-06-02 15:39:16 +02:00
}
2021-09-29 02:39:30 +02:00
}
2023-11-29 15:08:43 +11:00
let atomic_values = & [
sym ::ptr ,
sym ::integer ( 8 usize ) ,
sym ::integer ( 16 usize ) ,
sym ::integer ( 32 usize ) ,
sym ::integer ( 64 usize ) ,
sym ::integer ( 128 usize ) ,
] ;
for sym in [
sym ::target_has_atomic ,
sym ::target_has_atomic_equal_alignment ,
sym ::target_has_atomic_load_store ,
] {
ins! ( sym , no_values ) . extend ( atomic_values ) ;
}
ins! ( sym ::target_thread_local , no_values ) ;
ins! ( sym ::test , no_values ) ;
ins! ( sym ::unix , no_values ) ;
ins! ( sym ::windows , no_values ) ;
2021-09-29 02:39:30 +02:00
}
}
2023-10-30 14:05:06 +11:00
pub fn build_configuration ( sess : & Session , mut user_cfg : Cfg ) -> Cfg {
2014-05-06 23:38:01 +12:00
// Combine the configuration requested by the session (command line) with
2019-09-06 03:57:44 +01:00
// some default and generated configuration items.
2023-12-15 23:56:24 +01:00
user_cfg . extend ( default_configuration ( sess ) ) ;
2016-11-15 08:54:27 +00:00
user_cfg
2014-05-06 23:38:01 +12:00
}
2024-03-21 10:35:19 +11:00
pub fn build_target_config ( early_dcx : & EarlyDiagCtxt , opts : & Options , sysroot : & Path ) -> Target {
match Target ::search ( & opts . target_triple , sysroot ) {
Ok ( ( target , warnings ) ) = > {
for warning in warnings . warning_messages ( ) {
early_dcx . early_warn ( warning )
}
if ! matches! ( target . pointer_width , 16 | 32 | 64 ) {
early_dcx . early_fatal ( format! (
" target specification was invalid: unrecognized target-pointer-width {} " ,
target . pointer_width
) )
}
target
}
Err ( e ) = > early_dcx . early_fatal ( format! (
2023-07-25 22:00:13 +02:00
" Error loading target specification: {e}. \
2024-03-21 10:35:19 +11:00
Run ` rustc - - print target - list ` for a list of built - in targets "
) ) ,
2021-05-27 10:21:53 +02:00
}
2014-05-06 23:38:01 +12:00
}
2015-01-28 08:34:18 -05:00
#[ derive(Copy, Clone, PartialEq, Eq, Debug) ]
2024-03-19 13:31:28 +11:00
enum OptionStability {
2016-02-19 22:03:54 -08:00
Stable ,
Unstable ,
}
2014-12-17 14:42:50 +01:00
pub struct RustcOptGroup {
2018-02-23 09:53:00 -08:00
pub apply : Box < dyn Fn ( & mut getopts ::Options ) -> & mut getopts ::Options > ,
2024-03-19 13:31:28 +11:00
name : & 'static str ,
stability : OptionStability ,
2014-12-17 14:42:50 +01:00
}
impl RustcOptGroup {
pub fn is_stable ( & self ) -> bool {
self . stability = = OptionStability ::Stable
}
2017-06-08 14:20:55 -07:00
pub fn stable < F > ( name : & 'static str , f : F ) -> RustcOptGroup
2018-03-06 02:29:03 -03:00
where
F : Fn ( & mut getopts ::Options ) -> & mut getopts ::Options + 'static ,
2017-06-08 14:20:55 -07:00
{
RustcOptGroup { name , apply : Box ::new ( f ) , stability : OptionStability ::Stable }
2014-12-17 14:42:50 +01:00
}
2017-06-08 14:20:55 -07:00
pub fn unstable < F > ( name : & 'static str , f : F ) -> RustcOptGroup
2018-03-06 02:29:03 -03:00
where
F : Fn ( & mut getopts ::Options ) -> & mut getopts ::Options + 'static ,
2017-06-08 14:20:55 -07:00
{
RustcOptGroup { name , apply : Box ::new ( f ) , stability : OptionStability ::Unstable }
2014-12-17 14:42:50 +01:00
}
}
// The `opt` local module holds wrappers around the `getopts` API that
// adds extra rustc-specific metadata to each option; such metadata
2022-11-16 20:34:16 +00:00
// is exposed by . The public
2014-12-17 14:42:50 +01:00
// functions below ending with `_u` are the functions that return
2018-11-27 02:59:49 +00:00
// *unstable* options, i.e., options that are only enabled when the
2014-12-17 14:42:50 +01:00
// user also passes the `-Z unstable-options` debugging flag.
mod opt {
2019-07-23 20:34:17 +03:00
// The `fn flag*` etc below are written so that we can use them
2014-12-17 14:42:50 +01:00
// in the future; do not warn about them not being used right now.
#![ allow(dead_code) ]
use super ::RustcOptGroup ;
2024-03-19 13:31:28 +11:00
type R = RustcOptGroup ;
type S = & 'static str ;
2017-06-08 14:20:55 -07:00
fn stable < F > ( name : S , f : F ) -> R
2018-03-06 02:29:03 -03:00
where
F : Fn ( & mut getopts ::Options ) -> & mut getopts ::Options + 'static ,
2017-06-08 14:20:55 -07:00
{
RustcOptGroup ::stable ( name , f )
}
2014-12-17 14:42:50 +01:00
2017-06-08 14:20:55 -07:00
fn unstable < F > ( name : S , f : F ) -> R
2018-03-06 02:29:03 -03:00
where
F : Fn ( & mut getopts ::Options ) -> & mut getopts ::Options + 'static ,
2017-06-08 14:20:55 -07:00
{
RustcOptGroup ::unstable ( name , f )
}
fn longer ( a : S , b : S ) -> S {
if a . len ( ) > b . len ( ) { a } else { b }
}
2014-12-17 14:42:50 +01:00
2024-03-19 13:31:28 +11:00
pub ( crate ) fn opt_s ( a : S , b : S , c : S , d : S ) -> R {
2017-06-08 14:20:55 -07:00
stable ( longer ( a , b ) , move | opts | opts . optopt ( a , b , c , d ) )
2016-02-19 22:03:54 -08:00
}
2024-03-19 13:31:28 +11:00
pub ( crate ) fn multi_s ( a : S , b : S , c : S , d : S ) -> R {
2017-06-08 14:20:55 -07:00
stable ( longer ( a , b ) , move | opts | opts . optmulti ( a , b , c , d ) )
2016-02-19 22:03:54 -08:00
}
2024-03-19 13:31:28 +11:00
pub ( crate ) fn flag_s ( a : S , b : S , c : S ) -> R {
2017-06-08 14:20:55 -07:00
stable ( longer ( a , b ) , move | opts | opts . optflag ( a , b , c ) )
2016-02-19 22:03:54 -08:00
}
2024-03-19 13:31:28 +11:00
pub ( crate ) fn flagmulti_s ( a : S , b : S , c : S ) -> R {
2017-06-08 14:20:55 -07:00
stable ( longer ( a , b ) , move | opts | opts . optflagmulti ( a , b , c ) )
2016-02-19 22:03:54 -08:00
}
2015-04-29 17:20:36 +02:00
2024-03-19 13:31:28 +11:00
fn opt ( a : S , b : S , c : S , d : S ) -> R {
2017-06-08 14:20:55 -07:00
unstable ( longer ( a , b ) , move | opts | opts . optopt ( a , b , c , d ) )
2016-02-19 22:03:54 -08:00
}
2024-03-19 13:31:28 +11:00
pub ( crate ) fn multi ( a : S , b : S , c : S , d : S ) -> R {
2017-06-08 14:20:55 -07:00
unstable ( longer ( a , b ) , move | opts | opts . optmulti ( a , b , c , d ) )
2016-02-19 22:03:54 -08:00
}
2014-12-17 14:42:50 +01:00
}
2024-03-19 13:31:28 +11:00
2023-01-06 14:07:12 -05:00
static EDITION_STRING : LazyLock < String > = LazyLock ::new ( | | {
format! (
2023-01-06 14:36:52 -05:00
" Specify which edition of the compiler to use when compiling code. \
2023-01-06 14:07:12 -05:00
The default is { DEFAULT_EDITION } and the latest stable edition is { LATEST_STABLE_EDITION } . "
)
} ) ;
2024-03-19 13:31:28 +11:00
2014-12-17 14:42:50 +01:00
/// Returns the "short" subset of the rustc command line options,
/// including metadata for each option, such as whether the option is
/// part of the stable long-term interface for rustc.
pub fn rustc_short_optgroups ( ) -> Vec < RustcOptGroup > {
2014-12-15 16:03:39 -08:00
vec! [
2016-02-19 22:03:54 -08:00
opt ::flag_s ( " h " , " help " , " Display this message " ) ,
2023-04-20 19:29:19 +08:00
opt ::multi_s ( " " , " cfg " , " Configure the compilation environment.
SPEC supports the syntax ` NAME [ = \ " VALUE \" ]`. " , " SPEC " ) ,
2021-09-29 02:39:30 +02:00
opt ::multi ( " " , " check-cfg " , " Provide list of valid cfg options for checking " , " SPEC " ) ,
2018-03-06 02:29:03 -03:00
opt ::multi_s (
" L " ,
" " ,
" Add a directory to the library search path. The
2016-04-15 23:55:42 +03:00
optional KIND can be one of dependency , crate , native ,
2019-07-06 05:30:15 +02:00
framework , or all ( the default ) . " ,
2018-03-06 02:29:03 -03:00
" [KIND=]PATH " ,
) ,
opt ::multi_s (
" l " ,
" " ,
" Link the generated crate(s) to the specified native
2016-04-10 06:59:19 -07:00
library NAME . The optional KIND can be one of
2021-03-24 21:45:09 -07:00
static , framework , or dylib ( the default ) .
Optional comma separated MODIFIERS ( bundle | verbatim | whole - archive | as - needed )
may be specified each with a prefix of either '+' to
enable or '-' to disable . " ,
" [KIND[:MODIFIERS]=]NAME[:RENAME] " ,
2018-03-06 02:29:03 -03:00
) ,
2019-07-20 16:34:41 -04:00
make_crate_type_option ( ) ,
2018-03-06 02:29:03 -03:00
opt ::opt_s ( " " , " crate-name " , " Specify the name of the crate being built " , " NAME " ) ,
2019-03-22 11:51:37 +00:00
opt ::opt_s (
" " ,
" edition " ,
2023-04-09 23:07:18 +02:00
& EDITION_STRING ,
2019-03-22 11:51:37 +00:00
EDITION_NAME_LIST ,
) ,
2018-03-06 02:29:03 -03:00
opt ::multi_s (
" " ,
" emit " ,
" Comma separated list of types of output for \
the compiler to emit " ,
" [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] " ,
) ,
opt ::multi_s (
" " ,
" print " ,
2019-05-12 14:16:50 -07:00
" Compiler information to print on stdout " ,
2022-09-08 15:37:15 +02:00
" [crate-name|file-names|sysroot|target-libdir|cfg|calling-conventions| \
target - list | target - cpus | target - features | relocation - models | code - models | \
2023-03-09 14:52:45 +01:00
tls - models | target - spec - json | all - target - specs - json | native - static - libs | \
2022-12-05 23:15:16 -06:00
stack - protector - strategies | link - args | deployment - target ] " ,
2018-03-06 02:29:03 -03:00
) ,
opt ::flagmulti_s ( " g " , " " , " Equivalent to -C debuginfo=2 " ) ,
2016-02-19 22:03:54 -08:00
opt ::flagmulti_s ( " O " , " " , " Equivalent to -C opt-level=2 " ) ,
opt ::opt_s ( " o " , " " , " Write output to <filename> " , " FILENAME " ) ,
2018-03-06 02:29:03 -03:00
opt ::opt_s (
" " ,
" out-dir " ,
" Write output to compiler-chosen filename \
in < dir > " ,
" DIR " ,
) ,
opt ::opt_s (
" " ,
" explain " ,
" Provide a detailed explanation of an error \
message " ,
" OPT " ,
) ,
2016-02-19 22:03:54 -08:00
opt ::flag_s ( " " , " test " , " Build a test harness " ) ,
2018-03-06 02:29:03 -03:00
opt ::opt_s ( " " , " target " , " Target triple for which the code is compiled " , " TARGET " ) ,
2021-07-23 23:59:17 -07:00
opt ::multi_s ( " A " , " allow " , " Set lint allowed " , " LINT " ) ,
opt ::multi_s ( " W " , " warn " , " Set lint warnings " , " LINT " ) ,
opt ::multi_s ( " " , " force-warn " , " Set lint force-warn " , " LINT " ) ,
opt ::multi_s ( " D " , " deny " , " Set lint denied " , " LINT " ) ,
opt ::multi_s ( " F " , " forbid " , " Set lint forbidden " , " LINT " ) ,
2018-03-06 02:29:03 -03:00
opt ::multi_s (
" " ,
" cap-lints " ,
" Set the most restrictive lint level. \
More restrictive lints are capped at this \
level " ,
" LEVEL " ,
) ,
2016-02-19 22:03:54 -08:00
opt ::multi_s ( " C " , " codegen " , " Set a codegen option " , " OPT[=VALUE] " ) ,
opt ::flag_s ( " V " , " version " , " Print version info and exit " ) ,
opt ::flag_s ( " v " , " verbose " , " Use verbose output " ) ,
2014-12-15 16:03:39 -08:00
]
}
2014-12-17 14:42:50 +01:00
/// Returns all rustc command line options, including metadata for
/// each option, such as whether the option is part of the stable
/// long-term interface for rustc.
pub fn rustc_optgroups ( ) -> Vec < RustcOptGroup > {
let mut opts = rustc_short_optgroups ( ) ;
2022-07-06 07:44:47 -05:00
// FIXME: none of these descriptions are actually used
2017-06-08 14:20:55 -07:00
opts . extend ( vec! [
2018-03-06 02:29:03 -03:00
opt ::multi_s (
" " ,
" extern " ,
" Specify where an external rust library is located " ,
2019-09-29 18:17:48 -07:00
" NAME[=PATH] " ,
2018-03-06 02:29:03 -03:00
) ,
2016-02-19 22:03:54 -08:00
opt ::opt_s ( " " , " sysroot " , " Override the system root " , " PATH " ) ,
2022-07-06 07:44:47 -05:00
opt ::multi ( " Z " , " " , " Set unstable / perma-unstable options " , " FLAG " ) ,
2018-03-06 02:29:03 -03:00
opt ::opt_s (
" " ,
" error-format " ,
" How errors and other messages are produced " ,
" human|json|short " ,
) ,
2019-07-17 12:52:56 -07:00
opt ::multi_s ( " " , " json " , " Configure the JSON output of the compiler " , " CONFIG " ) ,
2018-03-06 02:29:03 -03:00
opt ::opt_s (
" " ,
" color " ,
" Configure coloring of output:
2016-03-15 09:09:29 +01:00
auto = colorize , if output goes to a tty ( default ) ;
always = always colorize output ;
2018-03-06 02:29:03 -03:00
never = never colorize output " ,
" auto|always|never " ,
) ,
2022-02-14 06:01:38 +00:00
opt ::opt_s (
" " ,
2022-07-06 11:57:41 +01:00
" diagnostic-width " ,
" Inform rustc of the width of the output so that diagnostics can be truncated to fit " ,
2022-02-14 06:01:38 +00:00
" WIDTH " ,
) ,
2018-03-06 02:29:03 -03:00
opt ::multi_s (
" " ,
" remap-path-prefix " ,
2018-03-13 13:26:07 -07:00
" Remap source names in all output (compiler messages and output files) " ,
2018-03-06 02:29:03 -03:00
" FROM=TO " ,
) ,
2024-01-12 11:02:57 +01:00
opt ::multi ( " " , " env-set " , " Inject an environment variable " , " VAR=VALUE " ) ,
2014-12-15 16:03:39 -08:00
] ) ;
opts
2014-05-06 23:38:01 +12:00
}
2018-06-23 15:09:21 +02:00
pub fn get_cmd_lint_options (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2018-06-23 15:09:21 +02:00
matches : & getopts ::Matches ,
2021-07-08 00:05:38 -07:00
) -> ( Vec < ( String , lint ::Level ) > , bool , Option < lint ::Level > ) {
2020-01-04 18:04:30 -08:00
let mut lint_opts_with_position = vec! [ ] ;
2018-06-23 15:09:21 +02:00
let mut describe_lints = false ;
2022-06-05 12:33:45 +02:00
for level in [ lint ::Allow , lint ::Warn , lint ::ForceWarn ( None ) , lint ::Deny , lint ::Forbid ] {
2021-07-08 00:05:38 -07:00
for ( arg_pos , lint_name ) in matches . opt_strs_pos ( level . as_str ( ) ) {
2018-06-23 15:09:21 +02:00
if lint_name = = " help " {
describe_lints = true ;
} else {
2021-12-13 22:58:58 +01:00
lint_opts_with_position . push ( ( arg_pos , lint_name . replace ( '-' , " _ " ) , level ) ) ;
2018-06-23 15:09:21 +02:00
}
}
}
2020-01-04 18:04:30 -08:00
lint_opts_with_position . sort_by_key ( | x | x . 0 ) ;
let lint_opts = lint_opts_with_position
. iter ( )
. cloned ( )
. map ( | ( _ , lint_name , level ) | ( lint_name , level ) )
. collect ( ) ;
2018-06-23 15:09:21 +02:00
let lint_cap = matches . opt_str ( " cap-lints " ) . map ( | cap | {
lint ::Level ::from_str ( & cap )
2023-12-20 14:53:50 +11:00
. unwrap_or_else ( | | early_dcx . early_fatal ( format! ( " unknown lint level: ` {cap} ` " ) ) )
2018-06-23 15:09:21 +02:00
} ) ;
2021-05-27 19:19:39 +02:00
2021-07-08 00:05:38 -07:00
( lint_opts , describe_lints , lint_cap )
2018-06-23 15:09:21 +02:00
}
2019-09-06 03:57:44 +01:00
/// Parses the `--color` flag.
2023-12-18 10:57:26 +11:00
pub fn parse_color ( early_dcx : & EarlyDiagCtxt , matches : & getopts ::Matches ) -> ColorConfig {
2022-11-16 21:58:58 +00:00
match matches . opt_str ( " color " ) . as_deref ( ) {
2018-03-06 02:29:03 -03:00
Some ( " auto " ) = > ColorConfig ::Auto ,
2015-12-14 11:17:55 +13:00
Some ( " always " ) = > ColorConfig ::Always ,
2018-03-06 02:29:03 -03:00
Some ( " never " ) = > ColorConfig ::Never ,
2015-08-22 23:51:53 +09:00
2015-12-14 11:17:55 +13:00
None = > ColorConfig ::Auto ,
2015-08-22 23:51:53 +09:00
2023-12-20 14:53:50 +11:00
Some ( arg ) = > early_dcx . early_fatal ( format! (
2023-06-23 05:56:09 +08:00
" argument for `--color` must be auto, \
2022-03-24 22:11:05 -07:00
always or never ( instead was ` { arg } ` ) "
2023-06-23 05:56:09 +08:00
) ) ,
2019-07-17 12:52:56 -07:00
}
}
2015-08-22 23:51:53 +09:00
2020-07-05 19:35:46 +02:00
/// Possible json config files
pub struct JsonConfig {
pub json_rendered : HumanReadableErrorType ,
2024-03-19 13:31:28 +11:00
json_artifact_notifications : bool ,
2022-04-16 17:11:33 -07:00
pub json_unused_externs : JsonUnusedExterns ,
2024-03-19 13:31:28 +11:00
json_future_incompat : bool ,
2020-07-05 19:35:46 +02:00
}
2022-04-16 17:11:33 -07:00
/// Report unused externs in event stream
#[ derive(Copy, Clone) ]
pub enum JsonUnusedExterns {
/// Do not
No ,
/// Report, but do not exit with failure status for deny/forbid
Silent ,
/// Report, and also exit with failure status for deny/forbid
Loud ,
}
impl JsonUnusedExterns {
pub fn is_enabled ( & self ) -> bool {
match self {
JsonUnusedExterns ::No = > false ,
JsonUnusedExterns ::Loud | JsonUnusedExterns ::Silent = > true ,
}
}
pub fn is_loud ( & self ) -> bool {
match self {
JsonUnusedExterns ::No | JsonUnusedExterns ::Silent = > false ,
JsonUnusedExterns ::Loud = > true ,
}
}
}
2019-07-17 12:52:56 -07:00
/// Parse the `--json` flag.
///
/// The first value returned is how to render JSON diagnostics, and the second
/// is whether or not artifact notifications are enabled.
2023-12-18 10:57:26 +11:00
pub fn parse_json ( early_dcx : & EarlyDiagCtxt , matches : & getopts ::Matches ) -> JsonConfig {
2019-07-17 12:52:56 -07:00
let mut json_rendered : fn ( ColorConfig ) -> HumanReadableErrorType =
HumanReadableErrorType ::Default ;
let mut json_color = ColorConfig ::Never ;
let mut json_artifact_notifications = false ;
2022-04-16 17:11:33 -07:00
let mut json_unused_externs = JsonUnusedExterns ::No ;
2021-12-04 14:34:20 -05:00
let mut json_future_incompat = false ;
2019-07-17 12:52:56 -07:00
for option in matches . opt_strs ( " json " ) {
// For now conservatively forbid `--color` with `--json` since `--json`
// won't actually be emitting any colors and anything colorized is
// embedded in a diagnostic message anyway.
if matches . opt_str ( " color " ) . is_some ( ) {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " cannot specify the `--color` option with `--json` " ) ;
2019-07-17 12:52:56 -07:00
}
2018-04-19 13:56:26 -07:00
2019-07-17 12:52:56 -07:00
for sub_option in option . split ( ',' ) {
match sub_option {
" diagnostic-short " = > json_rendered = HumanReadableErrorType ::Short ,
" diagnostic-rendered-ansi " = > json_color = ColorConfig ::Always ,
" artifacts " = > json_artifact_notifications = true ,
2022-04-16 17:11:33 -07:00
" unused-externs " = > json_unused_externs = JsonUnusedExterns ::Loud ,
" unused-externs-silent " = > json_unused_externs = JsonUnusedExterns ::Silent ,
2021-12-04 14:34:20 -05:00
" future-incompat " = > json_future_incompat = true ,
2023-12-20 14:53:50 +11:00
s = > early_dcx . early_fatal ( format! ( " unknown `--json` option ` {s} ` " ) ) ,
2019-07-17 12:52:56 -07:00
}
}
2018-04-19 21:03:21 -07:00
}
2020-07-05 19:35:46 +02:00
JsonConfig {
json_rendered : json_rendered ( json_color ) ,
json_artifact_notifications ,
json_unused_externs ,
2021-12-04 14:34:20 -05:00
json_future_incompat ,
2020-07-05 19:35:46 +02:00
}
2019-07-17 12:52:56 -07:00
}
2018-04-19 21:03:21 -07:00
2019-09-06 03:57:44 +01:00
/// Parses the `--error-format` flag.
2019-07-17 12:52:56 -07:00
pub fn parse_error_format (
2023-12-18 10:57:26 +11:00
early_dcx : & mut EarlyDiagCtxt ,
2019-07-17 12:52:56 -07:00
matches : & getopts ::Matches ,
color : ColorConfig ,
json_rendered : HumanReadableErrorType ,
) -> ErrorOutputType {
2019-09-06 03:57:44 +01:00
// We need the `opts_present` check because the driver will send us Matches
2016-01-07 09:23:01 +13:00
// with only stable options if no unstable options are used. Since error-format
2019-09-06 03:57:44 +01:00
// is unstable, it will not be present. We have to use `opts_present` not
// `opt_present` because the latter will panic.
2016-01-07 09:23:01 +13:00
let error_format = if matches . opts_present ( & [ " error-format " . to_owned ( ) ] ) {
2022-11-16 21:58:58 +00:00
match matches . opt_str ( " error-format " ) . as_deref ( ) {
2019-03-25 11:16:58 +01:00
None | Some ( " human " ) = > {
ErrorOutputType ::HumanReadable ( HumanReadableErrorType ::Default ( color ) )
2019-12-22 17:42:04 -05:00
}
2019-05-31 21:15:59 +02:00
Some ( " human-annotate-rs " ) = > {
2019-06-05 21:13:56 +02:00
ErrorOutputType ::HumanReadable ( HumanReadableErrorType ::AnnotateSnippet ( color ) )
2019-05-31 21:15:59 +02:00
}
2019-03-25 11:16:58 +01:00
Some ( " json " ) = > ErrorOutputType ::Json { pretty : false , json_rendered } ,
Some ( " pretty-json " ) = > ErrorOutputType ::Json { pretty : true , json_rendered } ,
Some ( " short " ) = > ErrorOutputType ::HumanReadable ( HumanReadableErrorType ::Short ( color ) ) ,
2015-12-31 16:50:06 +13:00
2023-06-23 05:56:09 +08:00
Some ( arg ) = > {
2023-12-18 10:57:26 +11:00
early_dcx . abort_if_error_and_set_error_format ( ErrorOutputType ::HumanReadable (
2023-06-23 05:56:09 +08:00
HumanReadableErrorType ::Default ( color ) ,
) ) ;
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! (
2019-09-01 18:09:59 +01:00
" argument for `--error-format` must be `human`, `json` or \
2022-03-24 22:11:05 -07:00
` short ` ( instead was ` { arg } ` ) "
2023-06-23 05:56:09 +08:00
) )
}
2015-12-31 16:50:06 +13:00
}
} else {
2019-03-25 11:16:58 +01:00
ErrorOutputType ::HumanReadable ( HumanReadableErrorType ::Default ( color ) )
2015-12-31 16:50:06 +13:00
} ;
2019-07-17 12:52:56 -07:00
match error_format {
ErrorOutputType ::Json { .. } = > { }
// Conservatively require that the `--json` argument is coupled with
// `--error-format=json`. This means that `--json` is specified we
// should actually be emitting JSON blobs.
2020-02-28 14:20:33 +01:00
_ if ! matches . opt_strs ( " json " ) . is_empty ( ) = > {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " using `--json` requires also using `--error-format=json` " ) ;
2019-07-17 12:52:56 -07:00
}
_ = > { }
}
2020-03-20 15:03:11 +01:00
error_format
2019-07-17 12:52:56 -07:00
}
2023-12-18 10:57:26 +11:00
pub fn parse_crate_edition ( early_dcx : & EarlyDiagCtxt , matches : & getopts ::Matches ) -> Edition {
2019-07-17 12:52:56 -07:00
let edition = match matches . opt_str ( " edition " ) {
Some ( arg ) = > Edition ::from_str ( & arg ) . unwrap_or_else ( | _ | {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! (
2023-06-23 05:56:09 +08:00
" argument for `--edition` must be one of: \
2022-03-24 22:11:05 -07:00
{ EDITION_NAME_LIST } . ( instead was ` { arg } ` ) "
2023-06-23 05:56:09 +08:00
) )
2019-07-17 12:52:56 -07:00
} ) ,
None = > DEFAULT_EDITION ,
} ;
2020-12-24 16:48:41 +01:00
if ! edition . is_stable ( ) & & ! nightly_options ::is_unstable_enabled ( matches ) {
2021-04-10 11:46:36 +01:00
let is_nightly = nightly_options ::match_is_nightly_build ( matches ) ;
let msg = if ! is_nightly {
format! (
2023-07-25 22:00:13 +02:00
" the crate requires edition {edition}, but the latest edition supported by this Rust version is {LATEST_STABLE_EDITION} "
2021-04-10 11:46:36 +01:00
)
} else {
2022-03-24 22:11:05 -07:00
format! ( " edition {edition} is unstable and only available with -Z unstable-options " )
2021-04-10 11:46:36 +01:00
} ;
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( msg )
2019-07-17 12:52:56 -07:00
}
2019-10-11 23:30:58 +02:00
edition
}
2014-05-06 23:38:01 +12:00
2022-07-06 07:44:47 -05:00
fn check_error_format_stability (
2023-12-18 10:57:26 +11:00
early_dcx : & mut EarlyDiagCtxt ,
2022-07-06 07:44:47 -05:00
unstable_opts : & UnstableOptions ,
2019-10-11 23:30:58 +02:00
error_format : ErrorOutputType ,
) {
2022-07-06 07:44:47 -05:00
if ! unstable_opts . unstable_options {
Change printing of "`--error-format` is unstable" errors.
Currently for these two errors we go to the effort of switching to a
standard JSON emitter, for no obvious reason, and unlike any other
errors. This behaviour was added for `pretty-json` in #45737, and then
`human-annotate-rs` copied it some time later when it was added.
This commit changes things to just using the requested emitter, which is
simpler and consistent with other errors.
Old output:
```
$ rustc --error-format pretty-json
{"$message_type":"diagnostic","message":"`--error-format=pretty-json` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"error: `--error-format=pretty-json` is unstable\n\n"}
$ rustc --error-format human-annotate-rs
{"$message_type":"diagnostic","message":"`--error-format=human-annotate-rs` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"error: `--error-format=human-annotate-rs` is unstable\n\n"}
```
New output:
```
$ rustc --error-format pretty-json
{
"$message_type": "diagnostic",
"message": "`--error-format=pretty-json` is unstable",
"code": null,
"level": "error",
"spans": [],
"children": [],
"rendered": "error: `--error-format=pretty-json` is unstable\n\n"
}
$ rustc --error-format human-annotate-rs
error: `--error-format=human-annotate-rs` is unstable
```
2024-01-05 14:11:12 +11:00
if let ErrorOutputType ::Json { pretty : true , .. } = error_format {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " `--error-format=pretty-json` is unstable " ) ;
2019-03-12 13:06:43 +01:00
}
2019-06-05 21:13:56 +02:00
if let ErrorOutputType ::HumanReadable ( HumanReadableErrorType ::AnnotateSnippet ( _ ) ) =
2019-05-31 21:15:59 +02:00
error_format
{
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " `--error-format=human-annotate-rs` is unstable " ) ;
2019-05-31 21:15:59 +02:00
}
2017-11-03 13:38:26 +01:00
}
2019-10-11 23:30:58 +02:00
}
2017-11-03 13:38:26 +01:00
2019-10-11 23:30:58 +02:00
fn parse_output_types (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2022-07-06 07:44:47 -05:00
unstable_opts : & UnstableOptions ,
2019-10-11 23:30:58 +02:00
matches : & getopts ::Matches ,
) -> OutputTypes {
2016-08-02 16:53:58 -04:00
let mut output_types = BTreeMap ::new ( ) ;
2022-07-06 07:44:47 -05:00
if ! unstable_opts . parse_only {
2015-09-30 10:08:37 -07:00
for list in matches . opt_strs ( " emit " ) {
for output_type in list . split ( ',' ) {
2023-07-16 17:58:46 -07:00
let ( shorthand , path ) = split_out_file_name ( output_type ) ;
2018-10-10 15:33:10 +02:00
let output_type = OutputType ::from_shorthand ( shorthand ) . unwrap_or_else ( | | {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! (
2023-06-23 05:56:09 +08:00
" unknown emission type: `{shorthand}` - expected one of: {display} " ,
display = OutputType ::shorthands_display ( ) ,
) )
2018-10-10 15:33:10 +02:00
} ) ;
2015-09-30 10:08:37 -07:00
output_types . insert ( output_type , path ) ;
2014-05-06 23:38:01 +12:00
}
}
} ;
2017-05-28 13:49:14 +07:00
if output_types . is_empty ( ) {
2015-09-30 10:08:37 -07:00
output_types . insert ( OutputType ::Exe , None ) ;
2014-05-06 23:38:01 +12:00
}
2019-10-11 23:30:58 +02:00
OutputTypes ( output_types )
}
2014-05-06 23:38:01 +12:00
2023-07-16 17:58:46 -07:00
fn split_out_file_name ( arg : & str ) -> ( & str , Option < OutFileName > ) {
match arg . split_once ( '=' ) {
None = > ( arg , None ) ,
Some ( ( kind , " - " ) ) = > ( kind , Some ( OutFileName ::Stdout ) ) ,
Some ( ( kind , path ) ) = > ( kind , Some ( OutFileName ::Real ( PathBuf ::from ( path ) ) ) ) ,
}
}
2019-10-11 23:30:58 +02:00
fn should_override_cgus_and_disable_thinlto (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2019-10-11 23:30:58 +02:00
output_types : & OutputTypes ,
matches : & getopts ::Matches ,
mut codegen_units : Option < usize > ,
) -> ( bool , Option < usize > ) {
2022-10-26 20:28:25 -04:00
let mut disable_local_thinlto = false ;
2019-09-06 03:57:44 +01:00
// Issue #30063: if user requests LLVM-related output to one
2015-12-04 19:35:16 +01:00
// particular path, disable codegen-units.
2019-10-11 23:30:58 +02:00
let incompatible : Vec < _ > = output_types
. 0
2018-03-06 02:29:03 -03:00
. iter ( )
2017-09-25 12:26:25 -07:00
. map ( | ot_path | ot_path . 0 )
2018-03-06 02:29:03 -03:00
. filter ( | ot | ! ot . is_compatible_with_codegen_units_and_single_output_file ( ) )
2017-09-25 12:26:25 -07:00
. map ( | ot | ot . shorthand ( ) )
. collect ( ) ;
if ! incompatible . is_empty ( ) {
match codegen_units {
Some ( n ) if n > 1 = > {
if matches . opt_present ( " o " ) {
for ot in & incompatible {
2023-12-18 10:57:26 +11:00
early_dcx . early_warn ( format! (
2023-06-23 05:56:09 +08:00
" `--emit={ot}` with `-o` incompatible with \
2019-09-01 18:09:59 +01:00
` - C codegen - units = N ` for N > 1 " ,
2023-06-23 05:56:09 +08:00
) ) ;
2017-09-25 12:26:25 -07:00
}
2023-12-18 10:57:26 +11:00
early_dcx . early_warn ( " resetting to default -C codegen-units=1 " ) ;
2017-09-25 12:26:25 -07:00
codegen_units = Some ( 1 ) ;
2022-10-26 20:28:25 -04:00
disable_local_thinlto = true ;
2017-09-25 12:26:25 -07:00
}
2015-12-04 19:35:16 +01:00
}
2017-11-25 11:13:58 -08:00
_ = > {
codegen_units = Some ( 1 ) ;
2022-10-26 20:28:25 -04:00
disable_local_thinlto = true ;
2017-11-25 11:13:58 -08:00
}
2015-12-04 19:35:16 +01:00
}
}
2019-10-11 23:30:58 +02:00
if codegen_units = = Some ( 0 ) {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " value for codegen units must be a positive non-zero integer " ) ;
2017-12-03 14:16:19 +01:00
}
2022-10-26 20:28:25 -04:00
( disable_local_thinlto , codegen_units )
2019-10-11 23:30:58 +02:00
}
fn collect_print_requests (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2019-10-11 23:30:58 +02:00
cg : & mut CodegenOptions ,
2022-07-06 07:44:47 -05:00
unstable_opts : & mut UnstableOptions ,
2019-10-11 23:30:58 +02:00
matches : & getopts ::Matches ,
) -> Vec < PrintRequest > {
2016-07-11 00:22:13 +10:00
let mut prints = Vec ::< PrintRequest > ::new ( ) ;
2023-05-24 14:19:22 +00:00
if cg . target_cpu . as_ref ( ) . is_some_and ( | s | s = = " help " ) {
2023-07-16 17:20:28 -07:00
prints . push ( PrintRequest { kind : PrintKind ::TargetCPUs , out : OutFileName ::Stdout } ) ;
2016-07-11 00:22:13 +10:00
cg . target_cpu = None ;
} ;
if cg . target_feature = = " help " {
2023-07-16 17:20:28 -07:00
prints . push ( PrintRequest { kind : PrintKind ::TargetFeatures , out : OutFileName ::Stdout } ) ;
2018-08-23 10:14:52 +02:00
cg . target_feature = String ::new ( ) ;
2016-07-11 00:22:13 +10:00
}
2023-07-16 17:20:28 -07:00
const PRINT_KINDS : & [ ( & str , PrintKind ) ] = & [
2023-11-29 16:33:08 +11:00
// tidy-alphabetical-start
( " all-target-specs-json " , PrintKind ::AllTargetSpecs ) ,
( " calling-conventions " , PrintKind ::CallingConventions ) ,
( " cfg " , PrintKind ::Cfg ) ,
( " code-models " , PrintKind ::CodeModels ) ,
2023-07-16 17:20:28 -07:00
( " crate-name " , PrintKind ::CrateName ) ,
2023-11-29 16:33:08 +11:00
( " deployment-target " , PrintKind ::DeploymentTarget ) ,
2023-07-16 17:20:28 -07:00
( " file-names " , PrintKind ::FileNames ) ,
2023-11-29 16:33:08 +11:00
( " link-args " , PrintKind ::LinkArgs ) ,
( " native-static-libs " , PrintKind ::NativeStaticLibs ) ,
( " relocation-models " , PrintKind ::RelocationModels ) ,
( " split-debuginfo " , PrintKind ::SplitDebuginfo ) ,
( " stack-protector-strategies " , PrintKind ::StackProtectorStrategies ) ,
2023-07-16 17:20:28 -07:00
( " sysroot " , PrintKind ::Sysroot ) ,
( " target-cpus " , PrintKind ::TargetCPUs ) ,
( " target-features " , PrintKind ::TargetFeatures ) ,
2023-11-29 16:33:08 +11:00
( " target-libdir " , PrintKind ::TargetLibdir ) ,
( " target-list " , PrintKind ::TargetList ) ,
2023-07-16 17:20:28 -07:00
( " target-spec-json " , PrintKind ::TargetSpec ) ,
2023-11-29 16:33:08 +11:00
( " tls-models " , PrintKind ::TlsModels ) ,
// tidy-alphabetical-end
2022-11-01 16:24:01 +01:00
] ;
2023-07-16 19:06:04 -07:00
// We disallow reusing the same path in multiple prints, such as `--print
// cfg=output.txt --print link-args=output.txt`, because outputs are printed
// by disparate pieces of the compiler, and keeping track of which files
// need to be overwritten vs appended to is annoying.
let mut printed_paths = FxHashSet ::default ( ) ;
2022-11-01 16:24:01 +01:00
prints . extend ( matches . opt_strs ( " print " ) . into_iter ( ) . map ( | req | {
2023-07-16 17:58:46 -07:00
let ( req , out ) = split_out_file_name ( & req ) ;
2023-07-16 17:20:28 -07:00
let kind = match PRINT_KINDS . iter ( ) . find ( | & & ( name , _ ) | name = = req ) {
Some ( ( _ , PrintKind ::TargetSpec ) ) = > {
2022-11-01 16:24:01 +01:00
if unstable_opts . unstable_options {
2023-07-16 17:20:28 -07:00
PrintKind ::TargetSpec
2022-11-01 16:24:01 +01:00
} else {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal (
2022-11-01 16:24:01 +01:00
" the `-Z unstable-options` flag must also be passed to \
2023-03-09 14:52:45 +01:00
enable the target - spec - json print option " ,
) ;
}
}
2023-07-16 17:20:28 -07:00
Some ( ( _ , PrintKind ::AllTargetSpecs ) ) = > {
2023-03-09 14:52:45 +01:00
if unstable_opts . unstable_options {
2023-07-16 17:20:28 -07:00
PrintKind ::AllTargetSpecs
2023-03-09 14:52:45 +01:00
} else {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal (
2023-03-09 14:52:45 +01:00
" the `-Z unstable-options` flag must also be passed to \
enable the all - target - specs - json print option " ,
2022-11-01 16:24:01 +01:00
) ;
}
}
2023-07-16 17:20:28 -07:00
Some ( & ( _ , print_kind ) ) = > print_kind ,
2022-11-01 16:24:01 +01:00
None = > {
let prints =
2023-07-16 17:20:28 -07:00
PRINT_KINDS . iter ( ) . map ( | ( name , _ ) | format! ( " ` {name} ` " ) ) . collect ::< Vec < _ > > ( ) ;
2022-11-01 16:24:01 +01:00
let prints = prints . join ( " , " ) ;
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! (
2023-06-23 05:56:09 +08:00
" unknown print request `{req}`. Valid print requests are: {prints} "
) ) ;
2019-10-11 23:30:58 +02:00
}
2023-07-16 17:20:28 -07:00
} ;
2023-07-16 17:58:46 -07:00
let out = out . unwrap_or ( OutFileName ::Stdout ) ;
2023-07-16 19:06:04 -07:00
if let OutFileName ::Real ( path ) = & out {
if ! printed_paths . insert ( path . clone ( ) ) {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! (
2023-07-16 19:06:04 -07:00
" cannot print multiple outputs to the same path: {} " ,
path . display ( ) ,
) ) ;
}
}
2023-07-16 17:58:46 -07:00
PrintRequest { kind , out }
2019-10-11 23:30:58 +02:00
} ) ) ;
2014-12-15 16:03:39 -08:00
2019-10-11 23:30:58 +02:00
prints
}
2023-12-18 10:57:26 +11:00
pub fn parse_target_triple ( early_dcx : & EarlyDiagCtxt , matches : & getopts ::Matches ) -> TargetTriple {
2019-10-11 23:30:58 +02:00
match matches . opt_str ( " target " ) {
Some ( target ) if target . ends_with ( " .json " ) = > {
2018-03-24 20:14:59 +01:00
let path = Path ::new ( & target ) ;
2022-11-29 11:01:17 +00:00
TargetTriple ::from_path ( path ) . unwrap_or_else ( | _ | {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! ( " target file {path:?} does not exist " ) )
2019-12-22 17:42:04 -05:00
} )
2019-10-11 23:30:58 +02:00
}
2021-02-16 15:02:04 +01:00
Some ( target ) = > TargetTriple ::TargetTriple ( target ) ,
2019-10-11 23:30:58 +02:00
_ = > TargetTriple ::from_triple ( host_triple ( ) ) ,
}
}
fn parse_opt_level (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2019-10-11 23:30:58 +02:00
matches : & getopts ::Matches ,
cg : & CodegenOptions ,
) -> OptLevel {
// The `-O` and `-C opt-level` flags specify the same setting, so we want to be able
// to use them interchangeably. However, because they're technically different flags,
// we need to work out manually which should take precedence if both are supplied (i.e.
// the rightmost flag). We do this by finding the (rightmost) position of both flags and
// comparing them. Note that if a flag is not found, its position will be `None`, which
// always compared less than `Some(_)`.
let max_o = matches . opt_positions ( " O " ) . into_iter ( ) . max ( ) ;
let max_c = matches
. opt_strs_pos ( " C " )
. into_iter ( )
2020-12-07 11:59:24 -07:00
. flat_map ( | ( i , s ) | {
// NB: This can match a string without `=`.
2022-12-15 00:06:34 +01:00
if let Some ( " opt-level " ) = s . split ( '=' ) . next ( ) { Some ( i ) } else { None }
2020-12-07 11:59:24 -07:00
} )
2019-10-11 23:30:58 +02:00
. max ( ) ;
if max_o > max_c {
OptLevel ::Default
2018-03-14 15:27:06 +01:00
} else {
2020-04-02 16:44:47 +11:00
match cg . opt_level . as_ref ( ) {
" 0 " = > OptLevel ::No ,
" 1 " = > OptLevel ::Less ,
" 2 " = > OptLevel ::Default ,
" 3 " = > OptLevel ::Aggressive ,
" s " = > OptLevel ::Size ,
" z " = > OptLevel ::SizeMin ,
arg = > {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! (
2023-06-23 05:56:09 +08:00
" optimization level needs to be \
2022-03-24 22:11:05 -07:00
between 0 - 3 , s or z ( instead was ` { arg } ` ) "
2023-06-23 05:56:09 +08:00
) ) ;
2014-12-15 16:03:39 -08:00
}
2014-05-06 23:38:01 +12:00
}
2019-10-11 23:30:58 +02:00
}
}
2021-04-06 16:00:35 -04:00
fn select_debuginfo ( matches : & getopts ::Matches , cg : & CodegenOptions ) -> DebugInfo {
2019-04-30 21:52:05 +01:00
let max_g = matches . opt_positions ( " g " ) . into_iter ( ) . max ( ) ;
let max_c = matches
. opt_strs_pos ( " C " )
. into_iter ( )
2020-12-07 11:59:24 -07:00
. flat_map ( | ( i , s ) | {
// NB: This can match a string without `=`.
2022-12-15 00:06:34 +01:00
if let Some ( " debuginfo " ) = s . split ( '=' ) . next ( ) { Some ( i ) } else { None }
2020-12-07 11:59:24 -07:00
} )
2019-04-30 21:52:05 +01:00
. max ( ) ;
2021-04-06 16:00:35 -04:00
if max_g > max_c { DebugInfo ::Full } else { cg . debuginfo }
2019-10-11 23:30:58 +02:00
}
2014-05-06 23:38:01 +12:00
2023-11-28 16:30:57 +11:00
fn parse_assert_incr_state (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2021-10-31 17:05:48 -05:00
opt_assertion : & Option < String > ,
) -> Option < IncrementalStateAssertion > {
match opt_assertion {
Some ( s ) if s . as_str ( ) = = " loaded " = > Some ( IncrementalStateAssertion ::Loaded ) ,
Some ( s ) if s . as_str ( ) = = " not-loaded " = > Some ( IncrementalStateAssertion ::NotLoaded ) ,
2022-03-24 22:11:05 -07:00
Some ( s ) = > {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! ( " unexpected incremental state assertion value: {s} " ) )
2022-03-24 22:11:05 -07:00
}
2021-10-31 17:05:48 -05:00
None = > None ,
}
}
2021-08-06 21:51:59 +08:00
fn parse_native_lib_kind (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2021-08-06 21:51:59 +08:00
matches : & getopts ::Matches ,
kind : & str ,
) -> ( NativeLibKind , Option < bool > ) {
let ( kind , modifiers ) = match kind . split_once ( ':' ) {
None = > ( kind , None ) ,
Some ( ( kind , modifiers ) ) = > ( kind , Some ( modifiers ) ) ,
} ;
let kind = match kind {
2021-03-24 21:45:09 -07:00
" static " = > NativeLibKind ::Static { bundle : None , whole_archive : None } ,
2022-03-14 13:28:34 +03:00
" dylib " = > NativeLibKind ::Dylib { as_needed : None } ,
" framework " = > NativeLibKind ::Framework { as_needed : None } ,
2022-07-19 12:00:28 +03:00
" link-arg " = > {
if ! nightly_options ::is_unstable_enabled ( matches ) {
let why = if nightly_options ::match_is_nightly_build ( matches ) {
" and only accepted on the nightly compiler "
} else {
" , the `-Z unstable-options` flag must also be passed to use it "
} ;
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! ( " library kind `link-arg` is unstable {why} " ) )
2022-07-19 12:00:28 +03:00
}
NativeLibKind ::LinkArg
}
2023-12-20 14:53:50 +11:00
_ = > early_dcx . early_fatal ( format! (
2023-06-23 05:56:09 +08:00
" unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg "
) ) ,
2021-08-06 21:51:59 +08:00
} ;
match modifiers {
None = > ( kind , None ) ,
2023-12-18 10:57:26 +11:00
Some ( modifiers ) = > parse_native_lib_modifiers ( early_dcx , kind , modifiers , matches ) ,
2021-03-24 21:45:09 -07:00
}
}
fn parse_native_lib_modifiers (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2021-03-24 21:45:09 -07:00
mut kind : NativeLibKind ,
modifiers : & str ,
2022-02-11 15:08:35 +08:00
matches : & getopts ::Matches ,
2021-03-24 21:45:09 -07:00
) -> ( NativeLibKind , Option < bool > ) {
let mut verbatim = None ;
for modifier in modifiers . split ( ',' ) {
2022-11-29 11:01:17 +00:00
let ( modifier , value ) = match modifier . strip_prefix ( [ '+' , '-' ] ) {
2021-03-24 21:45:09 -07:00
Some ( m ) = > ( m , modifier . starts_with ( '+' ) ) ,
2023-12-20 14:53:50 +11:00
None = > early_dcx . early_fatal (
2021-03-24 21:45:09 -07:00
" invalid linking modifier syntax, expected '+' or '-' prefix \
2022-03-14 13:28:34 +03:00
before one of : bundle , verbatim , whole - archive , as - needed " ,
2021-03-24 21:45:09 -07:00
) ,
} ;
2022-03-14 13:28:34 +03:00
let report_unstable_modifier = | | {
if ! nightly_options ::is_unstable_enabled ( matches ) {
let why = if nightly_options ::match_is_nightly_build ( matches ) {
" and only accepted on the nightly compiler "
} else {
" , the `-Z unstable-options` flag must also be passed to use it "
} ;
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! ( " linking modifier ` {modifier} ` is unstable {why} " ) )
2022-03-14 13:28:34 +03:00
}
} ;
let assign_modifier = | dst : & mut Option < bool > | {
if dst . is_some ( ) {
let msg = format! ( " multiple ` {modifier} ` modifiers in a single `-l` option " ) ;
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( msg )
2022-03-14 13:28:34 +03:00
} else {
* dst = Some ( value ) ;
}
} ;
2021-03-24 21:45:09 -07:00
match ( modifier , & mut kind ) {
2022-04-08 18:20:57 +03:00
( " bundle " , NativeLibKind ::Static { bundle , .. } ) = > assign_modifier ( bundle ) ,
2023-12-20 14:53:50 +11:00
( " bundle " , _ ) = > early_dcx . early_fatal (
2022-03-14 13:28:34 +03:00
" linking modifier `bundle` is only compatible with `static` linking kind " ,
2021-03-24 21:45:09 -07:00
) ,
2022-11-13 13:03:01 +03:00
( " verbatim " , _ ) = > assign_modifier ( & mut verbatim ) ,
2021-03-24 21:45:09 -07:00
( " whole-archive " , NativeLibKind ::Static { whole_archive , .. } ) = > {
2022-03-14 13:28:34 +03:00
assign_modifier ( whole_archive )
2021-03-24 21:45:09 -07:00
}
2023-12-20 14:53:50 +11:00
( " whole-archive " , _ ) = > early_dcx . early_fatal (
2022-03-14 13:28:34 +03:00
" linking modifier `whole-archive` is only compatible with `static` linking kind " ,
2021-03-24 21:45:09 -07:00
) ,
( " as-needed " , NativeLibKind ::Dylib { as_needed } )
| ( " as-needed " , NativeLibKind ::Framework { as_needed } ) = > {
2022-03-14 13:28:34 +03:00
report_unstable_modifier ( ) ;
assign_modifier ( as_needed )
2021-03-24 21:45:09 -07:00
}
2023-12-20 14:53:50 +11:00
( " as-needed " , _ ) = > early_dcx . early_fatal (
2022-03-14 13:28:34 +03:00
" linking modifier `as-needed` is only compatible with \
` dylib ` and ` framework ` linking kinds " ,
2021-03-24 21:45:09 -07:00
) ,
2022-02-11 15:08:35 +08:00
// Note: this error also excludes the case with empty modifier
// string, like `modifiers = ""`.
2023-12-20 14:53:50 +11:00
_ = > early_dcx . early_fatal ( format! (
2023-06-23 05:56:09 +08:00
" unknown linking modifier `{modifier}`, expected one \
2022-03-14 13:28:34 +03:00
of : bundle , verbatim , whole - archive , as - needed "
2023-06-23 05:56:09 +08:00
) ) ,
2021-03-24 21:45:09 -07:00
}
}
( kind , verbatim )
}
2023-12-18 10:57:26 +11:00
fn parse_libs ( early_dcx : & EarlyDiagCtxt , matches : & getopts ::Matches ) -> Vec < NativeLib > {
2019-10-11 23:30:58 +02:00
matches
2018-03-06 02:29:03 -03:00
. opt_strs ( " l " )
. into_iter ( )
. map ( | s | {
2021-03-24 21:45:09 -07:00
// Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]",
2022-07-19 12:00:28 +03:00
// where KIND is one of "dylib", "framework", "static", "link-arg" and
2023-01-14 17:34:59 +01:00
// where MODIFIERS are a comma separated list of supported modifiers
2021-03-24 21:45:09 -07:00
// (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed
// with either + or - to indicate whether it is enabled or disabled.
// The last value specified for a given modifier wins.
let ( name , kind , verbatim ) = match s . split_once ( '=' ) {
None = > ( s , NativeLibKind ::Unspecified , None ) ,
2020-12-07 11:59:24 -07:00
Some ( ( kind , name ) ) = > {
2023-12-18 10:57:26 +11:00
let ( kind , verbatim ) = parse_native_lib_kind ( early_dcx , matches , kind ) ;
2021-03-24 21:45:09 -07:00
( name . to_string ( ) , kind , verbatim )
2018-03-06 02:29:03 -03:00
}
} ;
2021-03-24 21:45:09 -07:00
2020-12-07 11:59:24 -07:00
let ( name , new_name ) = match name . split_once ( ':' ) {
None = > ( name , None ) ,
Some ( ( name , new_name ) ) = > ( name . to_string ( ) , Some ( new_name . to_owned ( ) ) ) ,
} ;
2022-03-14 13:28:34 +03:00
if name . is_empty ( ) {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " library name must not be empty " ) ;
2022-03-14 13:28:34 +03:00
}
2021-03-24 21:45:09 -07:00
NativeLib { name , new_name , kind , verbatim }
2018-03-06 02:29:03 -03:00
} )
2019-10-11 23:30:58 +02:00
. collect ( )
}
2014-05-06 23:38:01 +12:00
2019-12-05 14:43:53 -08:00
pub fn parse_externs (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2019-10-11 23:30:58 +02:00
matches : & getopts ::Matches ,
2022-07-06 07:44:47 -05:00
unstable_opts : & UnstableOptions ,
2019-10-11 23:30:58 +02:00
) -> Externs {
2023-11-29 01:16:25 +11:00
fn is_ascii_ident ( string : & str ) -> bool {
let mut chars = string . chars ( ) ;
if let Some ( start ) = chars . next ( )
& & ( start . is_ascii_alphabetic ( ) | | start = = '_' )
{
chars . all ( | char | char . is_ascii_alphanumeric ( ) | | char = = '_' )
} else {
false
}
}
2022-07-06 07:44:47 -05:00
let is_unstable_enabled = unstable_opts . unstable_options ;
2019-04-07 18:48:40 -04:00
let mut externs : BTreeMap < String , ExternEntry > = BTreeMap ::new ( ) ;
2019-12-05 14:43:53 -08:00
for arg in matches . opt_strs ( " extern " ) {
2020-12-07 11:59:24 -07:00
let ( name , path ) = match arg . split_once ( '=' ) {
None = > ( arg , None ) ,
2021-01-26 22:27:42 +01:00
Some ( ( name , path ) ) = > ( name . to_string ( ) , Some ( Path ::new ( path ) ) ) ,
2020-12-07 11:59:24 -07:00
} ;
let ( options , name ) = match name . split_once ( ':' ) {
None = > ( None , name ) ,
Some ( ( opts , name ) ) = > ( Some ( opts ) , name . to_string ( ) ) ,
2019-12-05 14:43:53 -08:00
} ;
2023-11-29 01:16:25 +11:00
if ! is_ascii_ident ( & name ) {
2023-12-20 14:53:50 +11:00
let mut error = early_dcx . early_struct_fatal ( format! (
2023-08-18 13:23:53 +02:00
" crate name `{name}` passed to `--extern` is not a valid ASCII identifier "
) ) ;
2023-11-06 13:06:40 +11:00
let adjusted_name = name . replace ( '-' , " _ " ) ;
2023-11-29 01:16:25 +11:00
if is_ascii_ident ( & adjusted_name ) {
2024-02-20 14:12:50 +11:00
#[ allow(rustc::diagnostic_outside_of_impl) ] // FIXME
2023-08-18 13:23:53 +02:00
error . help ( format! (
" consider replacing the dashes with underscores: `{adjusted_name}` "
) ) ;
}
error . emit ( ) ;
}
2021-01-26 22:27:42 +01:00
let path = path . map ( | p | CanonicalizedPath ::new ( p ) ) ;
2019-12-05 14:43:53 -08:00
let entry = externs . entry ( name . to_owned ( ) ) ;
use std ::collections ::btree_map ::Entry ;
let entry = if let Some ( path ) = path {
// --extern prelude_name=some_file.rlib
match entry {
Entry ::Vacant ( vacant ) = > {
let files = BTreeSet ::from_iter ( iter ::once ( path ) ) ;
vacant . insert ( ExternEntry ::new ( ExternLocation ::ExactPaths ( files ) ) )
}
Entry ::Occupied ( occupied ) = > {
let ext_ent = occupied . into_mut ( ) ;
match ext_ent {
ExternEntry { location : ExternLocation ::ExactPaths ( files ) , .. } = > {
files . insert ( path ) ;
}
ExternEntry {
location : location @ ExternLocation ::FoundInLibrarySearchDirectories ,
..
} = > {
// Exact paths take precedence over search directories.
let files = BTreeSet ::from_iter ( iter ::once ( path ) ) ;
* location = ExternLocation ::ExactPaths ( files ) ;
}
}
ext_ent
}
}
} else {
// --extern prelude_name
match entry {
Entry ::Vacant ( vacant ) = > {
vacant . insert ( ExternEntry ::new ( ExternLocation ::FoundInLibrarySearchDirectories ) )
}
Entry ::Occupied ( occupied ) = > {
// Ignore if already specified.
occupied . into_mut ( )
}
}
} ;
2019-04-09 17:24:24 -04:00
2019-12-05 14:43:53 -08:00
let mut is_private_dep = false ;
let mut add_prelude = true ;
2022-04-14 15:09:00 -07:00
let mut nounused_dep = false ;
2023-03-13 20:55:43 -07:00
let mut force = false ;
2019-12-05 14:43:53 -08:00
if let Some ( opts ) = options {
if ! is_unstable_enabled {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal (
2019-12-05 14:43:53 -08:00
" the `-Z unstable-options` flag must also be passed to \
2023-03-03 08:38:07 +01:00
enable ` - - extern ` options " ,
2019-12-05 14:43:53 -08:00
) ;
}
for opt in opts . split ( ',' ) {
match opt {
" priv " = > is_private_dep = true ,
" noprelude " = > {
if let ExternLocation ::ExactPaths ( _ ) = & entry . location {
add_prelude = false ;
} else {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal (
2019-12-05 14:43:53 -08:00
" the `noprelude` --extern option requires a file path " ,
) ;
}
}
2022-04-14 15:09:00 -07:00
" nounused " = > nounused_dep = true ,
2023-03-13 20:55:43 -07:00
" force " = > force = true ,
2023-12-20 14:53:50 +11:00
_ = > early_dcx . early_fatal ( format! ( " unknown --extern option ` {opt} ` " ) ) ,
2019-12-05 14:43:53 -08:00
}
}
}
2019-04-09 17:24:24 -04:00
2019-12-05 14:43:53 -08:00
// Crates start out being not private, and go to being private `priv`
// is specified.
entry . is_private_dep | = is_private_dep ;
2022-04-14 15:09:00 -07:00
// likewise `nounused`
entry . nounused_dep | = nounused_dep ;
2023-03-13 20:55:43 -07:00
// and `force`
entry . force | = force ;
2019-12-05 14:43:53 -08:00
// If any flag is missing `noprelude`, then add to the prelude.
entry . add_prelude | = add_prelude ;
2019-04-07 18:48:40 -04:00
}
2019-10-11 23:30:58 +02:00
Externs ( externs )
}
2014-07-01 08:37:54 -07:00
2019-10-11 23:30:58 +02:00
fn parse_remap_path_prefix (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2019-10-11 23:30:58 +02:00
matches : & getopts ::Matches ,
2022-07-06 07:44:47 -05:00
unstable_opts : & UnstableOptions ,
2019-10-11 23:30:58 +02:00
) -> Vec < ( PathBuf , PathBuf ) > {
2021-07-22 14:52:45 -04:00
let mut mapping : Vec < ( PathBuf , PathBuf ) > = matches
2018-03-06 02:29:03 -03:00
. opt_strs ( " remap-path-prefix " )
2018-02-18 15:05:24 -08:00
. into_iter ( )
2020-12-07 11:59:24 -07:00
. map ( | remap | match remap . rsplit_once ( '=' ) {
2023-12-18 11:15:13 +11:00
None = > {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " --remap-path-prefix must contain '=' between FROM and TO " )
2023-12-18 11:15:13 +11:00
}
2020-12-07 11:59:24 -07:00
Some ( ( from , to ) ) = > ( PathBuf ::from ( from ) , PathBuf ::from ( to ) ) ,
2018-02-18 15:05:24 -08:00
} )
2021-07-22 14:52:45 -04:00
. collect ( ) ;
2022-07-06 07:44:47 -05:00
match & unstable_opts . remap_cwd_prefix {
2021-07-22 14:52:45 -04:00
Some ( to ) = > match std ::env ::current_dir ( ) {
Ok ( cwd ) = > mapping . push ( ( cwd , to . clone ( ) ) ) ,
Err ( _ ) = > ( ) ,
} ,
None = > ( ) ,
} ;
mapping
2019-10-11 23:30:58 +02:00
}
2018-02-18 15:05:24 -08:00
2023-11-27 13:47:26 +01:00
fn parse_logical_env (
2023-12-18 10:57:26 +11:00
early_dcx : & mut EarlyDiagCtxt ,
2023-11-27 13:47:26 +01:00
matches : & getopts ::Matches ,
) -> FxIndexMap < String , String > {
let mut vars = FxIndexMap ::default ( ) ;
2024-01-12 11:02:57 +01:00
for arg in matches . opt_strs ( " env-set " ) {
2023-11-27 13:47:26 +01:00
if let Some ( ( name , val ) ) = arg . split_once ( '=' ) {
vars . insert ( name . to_string ( ) , val . to_string ( ) ) ;
} else {
2024-01-12 11:02:57 +01:00
early_dcx . early_fatal ( format! ( " `--env-set`: specify value for variable ` {arg} ` " ) ) ;
2023-11-27 13:47:26 +01:00
}
}
vars
}
2022-07-25 13:02:39 +01:00
// JUSTIFICATION: before wrapper fn is available
2022-08-09 09:56:13 -04:00
#[ allow(rustc::bad_opt_access) ]
2023-12-18 10:57:26 +11:00
pub fn build_session_options ( early_dcx : & mut EarlyDiagCtxt , matches : & getopts ::Matches ) -> Options {
let color = parse_color ( early_dcx , matches ) ;
2019-10-11 23:30:58 +02:00
2023-12-18 10:57:26 +11:00
let edition = parse_crate_edition ( early_dcx , matches ) ;
2019-10-11 23:30:58 +02:00
2021-12-04 14:34:20 -05:00
let JsonConfig {
json_rendered ,
json_artifact_notifications ,
json_unused_externs ,
json_future_incompat ,
2023-12-18 10:57:26 +11:00
} = parse_json ( early_dcx , matches ) ;
2019-10-11 23:30:58 +02:00
2023-12-18 10:57:26 +11:00
let error_format = parse_error_format ( early_dcx , matches , color , json_rendered ) ;
2019-10-11 23:30:58 +02:00
2023-12-18 10:57:26 +11:00
early_dcx . abort_if_error_and_set_error_format ( error_format ) ;
2023-06-28 23:51:12 +08:00
2022-07-06 11:57:41 +01:00
let diagnostic_width = matches . opt_get ( " diagnostic-width " ) . unwrap_or_else ( | _ | {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " `--diagnostic-width` must be an positive integer " ) ;
2022-02-14 06:01:38 +00:00
} ) ;
2019-10-11 23:30:58 +02:00
let unparsed_crate_types = matches . opt_strs ( " crate-type " ) ;
let crate_types = parse_crate_types_from_list ( unparsed_crate_types )
2023-12-20 14:53:50 +11:00
. unwrap_or_else ( | e | early_dcx . early_fatal ( e ) ) ;
2019-10-11 23:30:58 +02:00
2023-12-18 10:57:26 +11:00
let mut unstable_opts = UnstableOptions ::build ( early_dcx , matches ) ;
let ( lint_opts , describe_lints , lint_cap ) = get_cmd_lint_options ( early_dcx , matches ) ;
2019-10-11 23:30:58 +02:00
Change printing of "`--error-format` is unstable" errors.
Currently for these two errors we go to the effort of switching to a
standard JSON emitter, for no obvious reason, and unlike any other
errors. This behaviour was added for `pretty-json` in #45737, and then
`human-annotate-rs` copied it some time later when it was added.
This commit changes things to just using the requested emitter, which is
simpler and consistent with other errors.
Old output:
```
$ rustc --error-format pretty-json
{"$message_type":"diagnostic","message":"`--error-format=pretty-json` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"error: `--error-format=pretty-json` is unstable\n\n"}
$ rustc --error-format human-annotate-rs
{"$message_type":"diagnostic","message":"`--error-format=human-annotate-rs` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"error: `--error-format=human-annotate-rs` is unstable\n\n"}
```
New output:
```
$ rustc --error-format pretty-json
{
"$message_type": "diagnostic",
"message": "`--error-format=pretty-json` is unstable",
"code": null,
"level": "error",
"spans": [],
"children": [],
"rendered": "error: `--error-format=pretty-json` is unstable\n\n"
}
$ rustc --error-format human-annotate-rs
error: `--error-format=human-annotate-rs` is unstable
```
2024-01-05 14:11:12 +11:00
check_error_format_stability ( early_dcx , & unstable_opts , error_format ) ;
2019-10-11 23:30:58 +02:00
2022-07-06 07:44:47 -05:00
if ! unstable_opts . unstable_options & & json_unused_externs . is_enabled ( ) {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal (
2020-06-30 20:17:07 +02:00
" the `-Z unstable-options` flag must also be passed to enable \
the flag ` - - json = unused - externs ` " ,
) ;
}
2023-12-18 10:57:26 +11:00
let output_types = parse_output_types ( early_dcx , & unstable_opts , matches ) ;
2019-10-11 23:30:58 +02:00
2023-12-18 10:57:26 +11:00
let mut cg = CodegenOptions ::build ( early_dcx , matches ) ;
2023-12-18 11:15:13 +11:00
let ( disable_local_thinlto , mut codegen_units ) = should_override_cgus_and_disable_thinlto (
early_dcx ,
& output_types ,
matches ,
cg . codegen_units ,
) ;
2019-10-11 23:30:58 +02:00
2023-11-29 00:00:00 +00:00
if unstable_opts . threads = = 0 {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " value for threads must be a positive non-zero integer " ) ;
2023-11-29 00:00:00 +00:00
}
2023-12-08 00:00:00 +00:00
let fuel = unstable_opts . fuel . is_some ( ) | | unstable_opts . print_fuel . is_some ( ) ;
if fuel & & unstable_opts . threads > 1 {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " optimization fuel is incompatible with multiple threads " ) ;
2023-11-29 00:00:00 +00:00
}
2023-12-08 00:00:00 +00:00
if fuel & & cg . incremental . is_some ( ) {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " optimization fuel is incompatible with incremental compilation " ) ;
2023-12-08 00:00:00 +00:00
}
2019-10-11 23:30:58 +02:00
2020-03-29 20:19:14 +02:00
let incremental = cg . incremental . as_ref ( ) . map ( PathBuf ::from ) ;
2019-10-11 23:30:58 +02:00
2023-12-18 10:57:26 +11:00
let assert_incr_state = parse_assert_incr_state ( early_dcx , & unstable_opts . assert_incr_state ) ;
2021-10-31 17:05:48 -05:00
2022-07-06 07:44:47 -05:00
if unstable_opts . profile & & incremental . is_some ( ) {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " can't instrument with gcov profiling when compiling incrementally " ) ;
2019-10-11 23:30:58 +02:00
}
2022-07-06 07:44:47 -05:00
if unstable_opts . profile {
2020-04-17 19:53:31 +01:00
match codegen_units {
Some ( 1 ) = > { }
None = > codegen_units = Some ( 1 ) ,
2023-12-18 10:57:26 +11:00
Some ( _ ) = > early_dcx
2023-12-20 14:53:50 +11:00
. early_fatal ( " can't instrument with gcov profiling with multiple codegen units " ) ,
2020-04-17 19:53:31 +01:00
}
}
2019-10-11 23:30:58 +02:00
if cg . profile_generate . enabled ( ) & & cg . profile_use . is_some ( ) {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " options `-C profile-generate` and `-C profile-use` are exclusive " ) ;
2019-10-11 23:30:58 +02:00
}
2022-07-06 07:44:47 -05:00
if unstable_opts . profile_sample_use . is_some ( )
2021-05-07 07:41:37 +00:00
& & ( cg . profile_generate . enabled ( ) | | cg . profile_use . is_some ( ) )
{
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal (
2021-05-07 07:41:37 +00:00
" option `-Z profile-sample-use` cannot be used with `-C profile-generate` or `-C profile-use` " ,
) ;
}
2023-11-02 17:34:05 +11:00
// Check for unstable values of `-C symbol-mangling-version`.
// This is what prevents them from being used on stable compilers.
match cg . symbol_mangling_version {
// Stable values:
None | Some ( SymbolManglingVersion ::V0 ) = > { }
2023-12-05 12:42:57 +08:00
2023-11-02 17:34:05 +11:00
// Unstable values:
Some ( SymbolManglingVersion ::Legacy ) = > {
if ! unstable_opts . unstable_options {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal (
2023-11-02 17:34:05 +11:00
" `-C symbol-mangling-version=legacy` requires `-Z unstable-options` " ,
) ;
}
2021-10-21 14:02:59 +02:00
}
2023-12-05 12:42:57 +08:00
Some ( SymbolManglingVersion ::Hashed ) = > {
if ! unstable_opts . unstable_options {
early_dcx . early_fatal (
" `-C symbol-mangling-version=hashed` requires `-Z unstable-options` " ,
) ;
}
}
2021-10-21 14:02:59 +02:00
}
2023-10-25 14:57:25 +11:00
if cg . instrument_coverage ! = InstrumentCoverage ::No {
2020-07-02 11:27:15 -07:00
if cg . profile_generate . enabled ( ) | | cg . profile_use . is_some ( ) {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal (
2021-10-21 16:04:22 +02:00
" option `-C instrument-coverage` is not compatible with either `-C profile-use` \
2020-07-02 11:27:15 -07:00
or ` - C profile - generate ` " ,
) ;
}
2021-10-21 16:04:22 +02:00
// `-C instrument-coverage` implies `-C symbol-mangling-version=v0` - to ensure consistent
2020-08-27 12:53:43 -07:00
// and reversible name mangling. Note, LLVM coverage tools can analyze coverage over
// multiple runs, including some changes to source code; so mangled names must be consistent
// across compilations.
2021-10-21 14:02:59 +02:00
match cg . symbol_mangling_version {
None = > cg . symbol_mangling_version = Some ( SymbolManglingVersion ::V0 ) ,
2020-12-14 00:25:29 -08:00
Some ( SymbolManglingVersion ::Legacy ) = > {
2023-12-18 10:57:26 +11:00
early_dcx . early_warn (
2021-10-21 16:04:22 +02:00
" -C instrument-coverage requires symbol mangling version `v0`, \
2021-10-21 14:02:59 +02:00
but ` - C symbol - mangling - version = legacy ` was specified " ,
2020-12-14 00:25:29 -08:00
) ;
}
Some ( SymbolManglingVersion ::V0 ) = > { }
2023-12-05 12:42:57 +08:00
Some ( SymbolManglingVersion ::Hashed ) = > {
early_dcx . early_warn (
" -C instrument-coverage requires symbol mangling version `v0`, \
but ` - C symbol - mangling - version = hashed ` was specified " ,
) ;
}
2020-12-14 00:25:29 -08:00
}
2020-07-02 11:27:15 -07:00
}
2020-09-16 10:47:56 -07:00
if let Ok ( graphviz_font ) = std ::env ::var ( " RUSTC_GRAPHVIZ_FONT " ) {
2022-07-06 07:44:47 -05:00
unstable_opts . graphviz_font = graphviz_font ;
2020-09-16 10:47:56 -07:00
}
2020-04-30 10:53:16 -07:00
if ! cg . embed_bitcode {
2020-04-19 20:48:43 +10:00
match cg . lto {
LtoCli ::No | LtoCli ::Unspecified = > { }
2023-06-23 05:56:09 +08:00
LtoCli ::Yes | LtoCli ::NoParam | LtoCli ::Thin | LtoCli ::Fat = > {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " options `-C embed-bitcode=no` and `-C lto` are incompatible " )
2023-06-23 05:56:09 +08:00
}
2020-04-19 20:48:43 +10:00
}
}
2023-06-21 21:49:41 +00:00
// For testing purposes, until we have more feedback about these options: ensure `-Z
2023-09-20 17:00:57 +00:00
// unstable-options` is required when using the unstable `-C link-self-contained` and `-C
// linker-flavor` options.
2023-06-21 21:49:41 +00:00
if ! nightly_options ::is_unstable_enabled ( matches ) {
let uses_unstable_self_contained_option =
cg . link_self_contained . are_unstable_variants_set ( ) ;
if uses_unstable_self_contained_option {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal (
2023-06-21 21:49:41 +00:00
" only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off` are stable, \
the ` - Z unstable - options ` flag must also be passed to use the unstable values " ,
2023-05-23 00:00:35 +03:00
) ;
2023-06-21 21:49:41 +00:00
}
if let Some ( flavor ) = cg . linker_flavor {
if flavor . is_unstable ( ) {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! (
2023-06-21 21:49:41 +00:00
" the linker flavor `{}` is unstable, the `-Z unstable-options` \
flag must also be passed to use the unstable values " ,
flavor . desc ( )
) ) ;
}
2023-05-23 00:00:35 +03:00
}
}
2023-09-21 13:27:45 +00:00
// Check `-C link-self-contained` for consistency: individual components cannot be both enabled
// and disabled at the same time.
if let Some ( erroneous_components ) = cg . link_self_contained . check_consistency ( ) {
let names : String = erroneous_components
. into_iter ( )
. map ( | c | c . as_str ( ) . unwrap ( ) )
. intersperse ( " , " )
. collect ( ) ;
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! (
2023-09-21 13:27:45 +00:00
" some `-C link-self-contained` components were both enabled and disabled: {names} "
) ) ;
}
2023-12-18 10:57:26 +11:00
let prints = collect_print_requests ( early_dcx , & mut cg , & mut unstable_opts , matches ) ;
2019-10-11 23:30:58 +02:00
let cg = cg ;
let sysroot_opt = matches . opt_str ( " sysroot " ) . map ( | m | PathBuf ::from ( & m ) ) ;
2023-12-18 10:57:26 +11:00
let target_triple = parse_target_triple ( early_dcx , matches ) ;
let opt_level = parse_opt_level ( early_dcx , matches , & cg ) ;
2019-10-11 23:30:58 +02:00
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
// to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
// for more details.
let debug_assertions = cg . debug_assertions . unwrap_or ( opt_level = = OptLevel ::No ) ;
2021-04-06 16:00:35 -04:00
let debuginfo = select_debuginfo ( matches , & cg ) ;
2023-11-29 16:56:15 +11:00
let debuginfo_compression = unstable_opts . debuginfo_compression ;
2019-10-11 23:30:58 +02:00
2023-12-18 10:57:26 +11:00
let libs = parse_libs ( early_dcx , matches ) ;
2019-10-11 23:30:58 +02:00
let test = matches . opt_present ( " test " ) ;
if ! cg . remark . is_empty ( ) & & debuginfo = = DebugInfo ::None {
2023-12-18 10:57:26 +11:00
early_dcx . early_warn ( " -C remark requires \" -C debuginfo=n \" to show source locations " ) ;
2019-10-11 23:30:58 +02:00
}
2023-06-25 23:39:02 +02:00
if cg . remark . is_empty ( ) & & unstable_opts . remark_dir . is_some ( ) {
2023-12-18 11:15:13 +11:00
early_dcx
. early_warn ( " using -Z remark-dir without enabling remarks using e.g. -C remark=all " ) ;
2023-06-25 23:39:02 +02:00
}
2023-12-18 10:57:26 +11:00
let externs = parse_externs ( early_dcx , matches , & unstable_opts ) ;
2019-10-11 23:30:58 +02:00
let crate_name = matches . opt_str ( " crate-name " ) ;
2023-12-18 10:57:26 +11:00
let remap_path_prefix = parse_remap_path_prefix ( early_dcx , matches , & unstable_opts ) ;
2019-10-11 23:30:58 +02:00
2023-12-18 10:57:26 +11:00
let pretty = parse_pretty ( early_dcx , & unstable_opts ) ;
2019-11-03 21:42:03 -05:00
2023-01-15 18:42:04 +01:00
// query-dep-graph is required if dump-dep-graph is given #106736
if unstable_opts . dump_dep_graph & & ! unstable_opts . query_dep_graph {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( " can't dump dependency graph without `-Z query-dep-graph` " ) ;
2023-01-15 18:42:04 +01:00
}
2023-12-18 10:57:26 +11:00
let logical_env = parse_logical_env ( early_dcx , matches ) ;
2023-11-27 13:47:26 +01:00
2024-02-15 00:03:34 +00:00
let sysroot = filesearch ::materialize_sysroot ( sysroot_opt ) ;
2024-03-06 13:28:12 +01:00
2021-04-27 16:25:12 +00:00
let real_rust_source_base_dir = {
// This is the location used by the `rust-src` `rustup` component.
let mut candidate = sysroot . join ( " lib/rustlib/src/rust " ) ;
if let Ok ( metadata ) = candidate . symlink_metadata ( ) {
// Replace the symlink rustbuild creates, with its destination.
// We could try to use `fs::canonicalize` instead, but that might
// produce unnecessarily verbose path.
if metadata . file_type ( ) . is_symlink ( ) {
if let Ok ( symlink_dest ) = std ::fs ::read_link ( & candidate ) {
candidate = symlink_dest ;
}
}
}
// Only use this directory if it has a file we can expect to always find.
2023-02-15 17:39:43 +00:00
candidate . join ( " library/std/src/lib.rs " ) . is_file ( ) . then_some ( candidate )
2021-04-27 16:25:12 +00:00
} ;
2024-02-29 14:16:32 +01:00
let mut search_paths = vec! [ ] ;
for s in & matches . opt_strs ( " L " ) {
2024-03-06 10:19:34 +01:00
search_paths . push ( SearchPath ::from_cli_opt ( & sysroot , & target_triple , early_dcx , s ) ) ;
2024-02-29 14:16:32 +01:00
}
2021-08-12 15:30:40 -05:00
let working_dir = std ::env ::current_dir ( ) . unwrap_or_else ( | e | {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! ( " Current directory is invalid: {e} " ) ) ;
2021-08-12 15:30:40 -05:00
} ) ;
2023-08-23 15:46:58 +02:00
let remap = file_path_mapping ( remap_path_prefix . clone ( ) , & unstable_opts ) ;
2023-01-16 14:27:33 +00:00
let ( path , remapped ) = remap . map_prefix ( & working_dir ) ;
2021-08-12 15:30:40 -05:00
let working_dir = if remapped {
2023-01-16 14:27:33 +00:00
RealFileName ::Remapped { virtual_name : path . into_owned ( ) , local_path : Some ( working_dir ) }
2021-08-12 15:30:40 -05:00
} else {
2023-01-16 14:27:33 +00:00
RealFileName ::LocalPath ( path . into_owned ( ) )
2021-08-12 15:30:40 -05:00
} ;
2023-12-19 13:24:05 -05:00
let verbose = matches . opt_present ( " verbose " ) | | unstable_opts . verbose_internals ;
2019-10-11 23:30:58 +02:00
Options {
2021-10-31 17:05:48 -05:00
assert_incr_state ,
2019-10-11 23:30:58 +02:00
crate_types ,
optimize : opt_level ,
debuginfo ,
2023-07-12 17:07:34 -04:00
debuginfo_compression ,
2019-10-11 23:30:58 +02:00
lint_opts ,
lint_cap ,
describe_lints ,
output_types ,
search_paths ,
2024-02-15 00:03:34 +00:00
maybe_sysroot : Some ( sysroot ) ,
2019-10-11 23:30:58 +02:00
target_triple ,
test ,
incremental ,
2023-10-13 17:28:34 +00:00
untracked_state_hash : Default ::default ( ) ,
2022-07-06 07:44:47 -05:00
unstable_opts ,
2019-10-11 23:30:58 +02:00
prints ,
cg ,
error_format ,
2022-07-06 11:57:41 +01:00
diagnostic_width ,
2019-10-11 23:30:58 +02:00
externs ,
2020-10-10 14:27:52 -04:00
unstable_features : UnstableFeatures ::from_environment ( crate_name . as_deref ( ) ) ,
2019-10-11 23:30:58 +02:00
crate_name ,
libs ,
debug_assertions ,
actually_rustdoc : false ,
2023-02-06 21:57:45 +04:00
resolve_doc_links : ResolveDocLinks ::ExportedMetadata ,
2024-01-10 12:47:22 +11:00
trimmed_def_paths : false ,
2019-10-11 23:30:58 +02:00
cli_forced_codegen_units : codegen_units ,
2022-10-26 20:28:25 -04:00
cli_forced_local_thinlto_off : disable_local_thinlto ,
2019-10-11 23:30:58 +02:00
remap_path_prefix ,
2021-04-27 16:25:12 +00:00
real_rust_source_base_dir ,
2019-10-11 23:30:58 +02:00
edition ,
json_artifact_notifications ,
2020-06-30 20:17:07 +02:00
json_unused_externs ,
2021-12-04 14:34:20 -05:00
json_future_incompat ,
2019-11-03 21:42:03 -05:00
pretty ,
2021-08-12 15:30:40 -05:00
working_dir ,
Add a simple markdown parser for formatting `rustc --explain`
Currently, the output of `rustc --explain foo` displays the raw markdown in a
pager. This is acceptable, but using actual formatting makes it easier to
understand.
This patch consists of three major components:
1. A markdown parser. This is an extremely simple non-backtracking recursive
implementation that requires normalization of the final token stream
2. A utility to write the token stream to an output buffer
3. Configuration within rustc_driver_impl to invoke this combination for
`--explain`. Like the current implementation, it first attempts to print to
a pager with a fallback colorized terminal, and standard print as a last
resort.
If color is disabled, or if the output does not support it, or if printing
with color fails, it will write the raw markdown (which matches current
behavior).
Pagers known to support color are: `less` (with `-r`), `bat` (aka `catbat`),
and `delta`.
The markdown parser does not support the entire markdown specification, but
should support the following with reasonable accuracy:
- Headings, including formatting
- Comments
- Code, inline and fenced block (no indented block)
- Strong, emphasis, and strikethrough formatted text
- Links, anchor, inline, and reference-style
- Horizontal rules
- Unordered and ordered list items, including formatting
This parser and writer should be reusable by other systems if ever needed.
2022-12-19 12:09:40 -06:00
color ,
2023-11-27 13:47:26 +01:00
logical_env ,
2023-12-19 13:24:05 -05:00
verbose ,
2019-11-03 21:42:03 -05:00
}
}
2023-12-18 10:57:26 +11:00
fn parse_pretty ( early_dcx : & EarlyDiagCtxt , unstable_opts : & UnstableOptions ) -> Option < PpMode > {
2021-03-25 15:48:21 -04:00
use PpMode ::* ;
2022-07-06 07:44:47 -05:00
let first = match unstable_opts . unpretty . as_deref ( ) ? {
2021-03-25 15:48:21 -04:00
" normal " = > Source ( PpSourceMode ::Normal ) ,
" identified " = > Source ( PpSourceMode ::Identified ) ,
" expanded " = > Source ( PpSourceMode ::Expanded ) ,
" expanded,identified " = > Source ( PpSourceMode ::ExpandedIdentified ) ,
" expanded,hygiene " = > Source ( PpSourceMode ::ExpandedHygiene ) ,
2023-10-10 12:17:06 +11:00
" ast-tree " = > AstTree ,
" ast-tree,expanded " = > AstTreeExpanded ,
2021-03-25 15:48:21 -04:00
" hir " = > Hir ( PpHirMode ::Normal ) ,
" hir,identified " = > Hir ( PpHirMode ::Identified ) ,
" hir,typed " = > Hir ( PpHirMode ::Typed ) ,
" hir-tree " = > HirTree ,
" thir-tree " = > ThirTree ,
2023-01-26 23:35:24 +01:00
" thir-flat " = > ThirFlat ,
2021-03-25 15:48:21 -04:00
" mir " = > Mir ,
2023-11-14 16:21:55 +03:00
" stable-mir " = > StableMir ,
2021-03-25 15:48:21 -04:00
" mir-cfg " = > MirCFG ,
2023-12-20 14:53:50 +11:00
name = > early_dcx . early_fatal ( format! (
2023-06-23 05:56:09 +08:00
" argument to `unpretty` must be one of `normal`, `identified`, \
2022-03-06 12:43:30 +00:00
` expanded ` , ` expanded , identified ` , ` expanded , hygiene ` , \
2021-03-25 15:48:21 -04:00
` ast - tree ` , ` ast - tree , expanded ` , ` hir ` , ` hir , identified ` , \
2023-11-14 16:21:55 +03:00
` hir , typed ` , ` hir - tree ` , ` thir - tree ` , ` thir - flat ` , ` mir ` , ` stable - mir ` , or \
2023-01-26 23:35:24 +01:00
` mir - cfg ` ; got { name } "
2023-06-23 05:56:09 +08:00
) ) ,
2021-03-25 15:48:21 -04:00
} ;
2022-08-31 13:09:26 +00:00
debug! ( " got unpretty option: {first:?} " ) ;
2021-03-25 15:48:21 -04:00
Some ( first )
2015-01-30 21:44:27 +13:00
}
2019-07-20 16:34:41 -04:00
pub fn make_crate_type_option ( ) -> RustcOptGroup {
opt ::multi_s (
" " ,
" crate-type " ,
" Comma separated list of types of crates
for the compiler to emit " ,
" [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro] " ,
)
}
2018-03-06 02:29:03 -03:00
pub fn parse_crate_types_from_list ( list_list : Vec < String > ) -> Result < Vec < CrateType > , String > {
2014-07-19 21:11:26 -07:00
let mut crate_types : Vec < CrateType > = Vec ::new ( ) ;
2015-01-31 12:20:46 -05:00
for unparsed_crate_type in & list_list {
2014-11-27 13:53:34 -05:00
for part in unparsed_crate_type . split ( ',' ) {
2014-07-19 21:11:26 -07:00
let new_part = match part {
2018-03-06 02:29:03 -03:00
" lib " = > default_lib_output ( ) ,
2018-07-26 11:13:11 -06:00
" rlib " = > CrateType ::Rlib ,
" staticlib " = > CrateType ::Staticlib ,
" dylib " = > CrateType ::Dylib ,
" cdylib " = > CrateType ::Cdylib ,
" bin " = > CrateType ::Executable ,
" proc-macro " = > CrateType ::ProcMacro ,
2022-03-24 22:11:05 -07:00
_ = > return Err ( format! ( " unknown crate type: ` {part} ` " ) ) ,
2014-07-19 21:11:26 -07:00
} ;
2015-02-09 19:30:22 +02:00
if ! crate_types . contains ( & new_part ) {
crate_types . push ( new_part )
}
2014-07-19 21:11:26 -07:00
}
}
2017-05-28 13:49:14 +07:00
Ok ( crate_types )
2014-07-19 21:11:26 -07:00
}
2016-03-15 09:09:29 +01:00
pub mod nightly_options {
2023-06-23 05:56:09 +08:00
use super ::{ OptionStability , RustcOptGroup } ;
2023-12-17 22:01:06 +11:00
use crate ::EarlyDiagCtxt ;
2019-11-30 02:50:47 +01:00
use rustc_feature ::UnstableFeatures ;
2016-03-15 09:09:29 +01:00
pub fn is_unstable_enabled ( matches : & getopts ::Matches ) -> bool {
2020-10-10 14:27:52 -04:00
match_is_nightly_build ( matches )
& & matches . opt_strs ( " Z " ) . iter ( ) . any ( | x | * x = = " unstable-options " )
2016-03-15 09:09:29 +01:00
}
2020-10-10 14:27:52 -04:00
pub fn match_is_nightly_build ( matches : & getopts ::Matches ) -> bool {
is_nightly_build ( matches . opt_str ( " crate-name " ) . as_deref ( ) )
}
2024-03-19 13:31:28 +11:00
fn is_nightly_build ( krate : Option < & str > ) -> bool {
2020-10-10 14:27:52 -04:00
UnstableFeatures ::from_environment ( krate ) . is_nightly_build ( )
2016-03-15 09:09:29 +01:00
}
2023-06-23 05:56:09 +08:00
pub fn check_nightly_options (
2023-12-18 10:57:26 +11:00
early_dcx : & EarlyDiagCtxt ,
2023-06-23 05:56:09 +08:00
matches : & getopts ::Matches ,
flags : & [ RustcOptGroup ] ,
) {
2018-03-06 02:29:03 -03:00
let has_z_unstable_option = matches . opt_strs ( " Z " ) . iter ( ) . any ( | x | * x = = " unstable-options " ) ;
2020-10-10 14:27:52 -04:00
let really_allows_unstable_options = match_is_nightly_build ( matches ) ;
2023-09-10 00:01:32 +08:00
let mut nightly_options_on_stable = 0 ;
2016-03-15 09:09:29 +01:00
for opt in flags . iter ( ) {
if opt . stability = = OptionStability ::Stable {
2018-03-06 02:29:03 -03:00
continue ;
2016-03-15 09:09:29 +01:00
}
2017-06-08 14:20:55 -07:00
if ! matches . opt_present ( opt . name ) {
2018-03-06 02:29:03 -03:00
continue ;
2016-03-15 09:09:29 +01:00
}
2017-06-08 14:20:55 -07:00
if opt . name ! = " Z " & & ! has_z_unstable_option {
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! (
2023-06-23 05:56:09 +08:00
" the `-Z unstable-options` flag must also be passed to enable \
2018-03-06 02:29:03 -03:00
the flag ` { } ` " ,
2023-06-23 05:56:09 +08:00
opt . name
) ) ;
2016-03-15 09:09:29 +01:00
}
if really_allows_unstable_options {
2018-03-06 02:29:03 -03:00
continue ;
2016-03-15 09:09:29 +01:00
}
match opt . stability {
OptionStability ::Unstable = > {
2023-09-10 00:01:32 +08:00
nightly_options_on_stable + = 1 ;
2018-03-06 02:29:03 -03:00
let msg = format! (
2023-05-16 16:04:03 +10:00
" the option `{}` is only accepted on the nightly compiler " ,
2018-03-06 02:29:03 -03:00
opt . name
) ;
2023-12-20 14:53:50 +11:00
let _ = early_dcx . early_err ( msg ) ;
2016-03-15 09:09:29 +01:00
}
OptionStability ::Stable = > { }
}
}
2023-09-10 00:01:32 +08:00
if nightly_options_on_stable > 0 {
2023-12-18 10:57:26 +11:00
early_dcx
2023-09-10 00:01:32 +08:00
. early_help ( " consider switching to a nightly toolchain: `rustup default nightly` " ) ;
2023-12-18 10:57:26 +11:00
early_dcx . early_note ( " selecting a toolchain with `+toolchain` arguments require a rustup proxy; see <https://rust-lang.github.io/rustup/concepts/index.html> " ) ;
early_dcx . early_note ( " for more information about Rust's stability policy, see <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html#unstable-features> " ) ;
2023-12-20 14:53:50 +11:00
early_dcx . early_fatal ( format! (
2023-09-10 00:01:32 +08:00
" {} nightly option{} were parsed " ,
nightly_options_on_stable ,
if nightly_options_on_stable > 1 { " s " } else { " " }
) ) ;
}
2016-03-15 09:09:29 +01:00
}
}
2015-01-20 15:45:07 -08:00
impl fmt ::Display for CrateType {
2018-08-29 22:02:42 -07:00
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
2014-06-11 10:48:17 +03:00
match * self {
2018-07-26 11:13:11 -06:00
CrateType ::Executable = > " bin " . fmt ( f ) ,
CrateType ::Dylib = > " dylib " . fmt ( f ) ,
CrateType ::Rlib = > " rlib " . fmt ( f ) ,
CrateType ::Staticlib = > " staticlib " . fmt ( f ) ,
CrateType ::Cdylib = > " cdylib " . fmt ( f ) ,
CrateType ::ProcMacro = > " proc-macro " . fmt ( f ) ,
2014-06-11 10:48:17 +03:00
}
}
}
2014-05-06 23:38:01 +12:00
2024-03-05 16:53:24 +11:00
impl IntoDiagArg for CrateType {
fn into_diag_arg ( self ) -> DiagArgValue {
self . to_string ( ) . into_diag_arg ( )
2022-08-30 17:01:54 +01:00
}
}
2019-11-03 21:42:03 -05:00
#[ derive(Copy, Clone, PartialEq, Debug) ]
pub enum PpSourceMode {
2021-03-25 15:48:21 -04:00
/// `-Zunpretty=normal`
2021-02-18 20:21:18 +01:00
Normal ,
2021-03-25 15:48:21 -04:00
/// `-Zunpretty=expanded`
2021-02-18 20:21:18 +01:00
Expanded ,
2021-03-25 15:48:21 -04:00
/// `-Zunpretty=identified`
2021-02-18 20:21:18 +01:00
Identified ,
2021-03-25 15:48:21 -04:00
/// `-Zunpretty=expanded,identified`
2021-02-18 20:21:18 +01:00
ExpandedIdentified ,
2021-03-25 15:48:21 -04:00
/// `-Zunpretty=expanded,hygiene`
2021-02-18 20:21:18 +01:00
ExpandedHygiene ,
}
#[ derive(Copy, Clone, PartialEq, Debug) ]
pub enum PpHirMode {
/// `-Zunpretty=hir`
Normal ,
/// `-Zunpretty=hir,identified`
Identified ,
/// `-Zunpretty=hir,typed`
Typed ,
2019-11-03 21:42:03 -05:00
}
#[ derive(Copy, Clone, PartialEq, Debug) ]
pub enum PpMode {
2021-02-18 20:21:18 +01:00
/// Options that print the source code, i.e.
2021-06-25 11:56:14 +02:00
/// `-Zunpretty=normal` and `-Zunpretty=expanded`
2021-02-18 20:21:18 +01:00
Source ( PpSourceMode ) ,
2023-10-10 12:17:06 +11:00
/// `-Zunpretty=ast-tree`
AstTree ,
/// `-Zunpretty=ast-tree,expanded`
AstTreeExpanded ,
2021-02-18 20:21:18 +01:00
/// Options that print the HIR, i.e. `-Zunpretty=hir`
Hir ( PpHirMode ) ,
/// `-Zunpretty=hir-tree`
HirTree ,
2021-03-07 15:09:39 +01:00
/// `-Zunpretty=thir-tree`
ThirTree ,
2023-03-03 04:10:46 +01:00
/// `-Zunpretty=thir-flat`
2023-01-26 23:35:24 +01:00
ThirFlat ,
2021-02-18 20:21:18 +01:00
/// `-Zunpretty=mir`
Mir ,
/// `-Zunpretty=mir-cfg`
MirCFG ,
2023-11-14 16:21:55 +03:00
/// `-Zunpretty=stable-mir`
StableMir ,
2019-11-03 21:42:03 -05:00
}
impl PpMode {
2019-11-20 08:27:42 -05:00
pub fn needs_ast_map ( & self ) -> bool {
2019-11-03 21:42:03 -05:00
use PpMode ::* ;
use PpSourceMode ::* ;
match * self {
2023-10-10 12:17:06 +11:00
Source ( Normal | Identified ) | AstTree = > false ,
2019-12-22 17:42:04 -05:00
2021-06-25 11:56:14 +02:00
Source ( Expanded | ExpandedIdentified | ExpandedHygiene )
2023-10-10 12:17:06 +11:00
| AstTreeExpanded
2021-02-18 20:21:18 +01:00
| Hir ( _ )
| HirTree
2021-03-07 15:09:39 +01:00
| ThirTree
2023-01-26 23:35:24 +01:00
| ThirFlat
2021-02-18 20:21:18 +01:00
| Mir
2023-11-08 12:37:26 +03:00
| MirCFG
2023-11-14 16:21:55 +03:00
| StableMir = > true ,
2019-11-03 21:42:03 -05:00
}
}
2022-07-16 20:35:54 -07:00
pub fn needs_hir ( & self ) -> bool {
use PpMode ::* ;
match * self {
2023-10-10 12:17:06 +11:00
Source ( _ ) | AstTree | AstTreeExpanded = > false ,
2022-07-16 20:35:54 -07:00
2023-11-14 16:21:55 +03:00
Hir ( _ ) | HirTree | ThirTree | ThirFlat | Mir | MirCFG | StableMir = > true ,
2022-07-16 20:35:54 -07:00
}
}
2019-11-03 21:42:03 -05:00
pub fn needs_analysis ( & self ) -> bool {
use PpMode ::* ;
2023-11-14 16:21:55 +03:00
matches! ( * self , Hir ( PpHirMode ::Typed ) | Mir | StableMir | MirCFG | ThirTree | ThirFlat )
2019-11-03 21:42:03 -05:00
}
}
2023-11-30 09:45:03 +11:00
#[ derive(Clone, Hash, PartialEq, Eq, Debug) ]
pub enum WasiExecModel {
Command ,
Reactor ,
}
2018-11-12 13:05:20 -05:00
/// Command-line arguments passed to the compiler have to be incorporated with
2016-08-02 16:53:58 -04:00
/// the dependency tracking system for incremental compilation. This module
/// provides some utilities to make this more convenient.
///
2018-11-12 13:05:20 -05:00
/// The values of all command-line arguments that are relevant for dependency
2016-08-02 16:53:58 -04:00
/// tracking are hashed into a single value that determines whether the
/// incremental compilation cache can be re-used or not. This hashing is done
2019-09-06 03:57:44 +01:00
/// via the `DepTrackingHash` trait defined below, since the standard `Hash`
/// implementation might not be suitable (e.g., arguments are stored in a `Vec`,
2016-08-02 16:53:58 -04:00
/// the hash of which is order dependent, but we might not want the order of
/// arguments to make a difference for the hash).
///
2019-09-06 03:57:44 +01:00
/// However, since the value provided by `Hash::hash` often *is* suitable,
2016-08-02 16:53:58 -04:00
/// especially for primitive types, there is the
2019-09-06 03:57:44 +01:00
/// `impl_dep_tracking_hash_via_hash!()` macro that allows to simply reuse the
/// `Hash` implementation for `DepTrackingHash`. It's important though that
2016-08-02 16:53:58 -04:00
/// we have an opt-in scheme here, so one is hopefully forced to think about
2018-11-12 13:05:20 -05:00
/// how the hash should be calculated when adding a new command-line argument.
2022-05-20 19:51:09 -04:00
pub ( crate ) mod dep_tracking {
2016-09-24 19:20:57 +02:00
use super ::{
2024-03-08 18:07:04 +11:00
BranchProtection , CFGuard , CFProtection , CollapseMacroDebuginfo , CoverageOptions ,
CrateType , DebugInfo , DebugInfoCompression , ErrorOutputType , FunctionReturn ,
InliningThreshold , InstrumentCoverage , InstrumentXRay , LinkerPluginLto , LocationDetail ,
LtoCli , NextSolverConfig , OomStrategy , OptLevel , OutFileName , OutputType , OutputTypes ,
Polonius , RemapPathScopeComponents , ResolveDocLinks , SourceFileHashAlgorithm ,
SplitDwarfKind , SwitchWithOptPath , SymbolManglingVersion , WasiExecModel ,
2019-12-22 17:42:04 -05:00
} ;
2019-11-29 16:05:28 -05:00
use crate ::lint ;
2023-10-13 17:28:34 +00:00
use crate ::utils ::NativeLib ;
2023-11-27 13:47:26 +01:00
use rustc_data_structures ::fx ::FxIndexMap ;
2023-10-13 17:28:34 +00:00
use rustc_data_structures ::stable_hasher ::Hash64 ;
2022-03-28 09:36:20 +01:00
use rustc_errors ::LanguageIdentifier ;
2019-11-29 16:05:28 -05:00
use rustc_feature ::UnstableFeatures ;
2019-12-31 20:15:40 +03:00
use rustc_span ::edition ::Edition ;
2021-08-12 15:30:40 -05:00
use rustc_span ::RealFileName ;
2020-05-07 03:34:27 +03:00
use rustc_target ::spec ::{ CodeModel , MergeFunctions , PanicStrategy , RelocModel } ;
add rustc option for using LLVM stack smash protection
LLVM has built-in heuristics for adding stack canaries to functions. These
heuristics can be selected with LLVM function attributes. This patch adds a
rustc option `-Z stack-protector={none,basic,strong,all}` which controls the use
of these attributes. This gives rustc the same stack smash protection support as
clang offers through options `-fno-stack-protector`, `-fstack-protector`,
`-fstack-protector-strong`, and `-fstack-protector-all`. The protection this can
offer is demonstrated in test/ui/abi/stack-protector.rs. This fills a gap in the
current list of rustc exploit
mitigations (https://doc.rust-lang.org/rustc/exploit-mitigations.html),
originally discussed in #15179.
Stack smash protection adds runtime overhead and is therefore still off by
default, but now users have the option to trade performance for security as they
see fit. An example use case is adding Rust code in an existing C/C++ code base
compiled with stack smash protection. Without the ability to add stack smash
protection to the Rust code, the code base artifacts could be exploitable in
ways not possible if the code base remained pure C/C++.
Stack smash protection support is present in LLVM for almost all the current
tier 1/tier 2 targets: see
test/assembly/stack-protector/stack-protector-target-support.rs. The one
exception is nvptx64-nvidia-cuda. This patch follows clang's example, and adds a
warning message printed if stack smash protection is used with this target (see
test/ui/stack-protector/warn-stack-protector-unsupported.rs). Support for tier 3
targets has not been checked.
Since the heuristics are applied at the LLVM level, the heuristics are expected
to add stack smash protection to a fraction of functions comparable to C/C++.
Some experiments demonstrating how Rust code is affected by the different
heuristics can be found in
test/assembly/stack-protector/stack-protector-heuristics-effect.rs. There is
potential for better heuristics using Rust-specific safety information. For
example it might be reasonable to skip stack smash protection in functions which
transitively only use safe Rust code, or which uses only a subset of functions
the user declares safe (such as anything under `std.*`). Such alternative
heuristics could be added at a later point.
LLVM also offers a "safestack" sanitizer as an alternative way to guard against
stack smashing (see #26612). This could possibly also be included as a
stack-protection heuristic. An alternative is to add it as a sanitizer (#39699).
This is what clang does: safestack is exposed with option
`-fsanitize=safe-stack`.
The options are only supported by the LLVM backend, but as with other codegen
options it is visible in the main codegen option help menu. The heuristic names
"basic", "strong", and "all" are hopefully sufficiently generic to be usable in
other backends as well.
Reviewed-by: Nikita Popov <nikic@php.net>
Extra commits during review:
- [address-review] make the stack-protector option unstable
- [address-review] reduce detail level of stack-protector option help text
- [address-review] correct grammar in comment
- [address-review] use compiler flag to avoid merging functions in test
- [address-review] specify min LLVM version in fortanix stack-protector test
Only for Fortanix test, since this target specifically requests the
`--x86-experimental-lvi-inline-asm-hardening` flag.
- [address-review] specify required LLVM components in stack-protector tests
- move stack protector option enum closer to other similar option enums
- rustc_interface/tests: sort debug option list in tracking hash test
- add an explicit `none` stack-protector option
Revert "set LLVM requirements for all stack protector support test revisions"
This reverts commit a49b74f92a4e7d701d6f6cf63d207a8aff2e0f68.
2021-04-06 21:37:49 +02:00
use rustc_target ::spec ::{
RelroLevel , SanitizerSet , SplitDebuginfo , StackProtector , TargetTriple , TlsModel ,
} ;
2016-08-02 16:53:58 -04:00
use std ::collections ::BTreeMap ;
2023-10-13 02:44:19 -04:00
use std ::hash ::{ DefaultHasher , Hash } ;
2024-01-29 23:59:09 +01:00
use std ::num ::NonZero ;
2016-08-02 16:53:58 -04:00
use std ::path ::PathBuf ;
2024-03-19 13:31:28 +11:00
pub ( crate ) trait DepTrackingHash {
2021-06-19 19:22:14 -05:00
fn hash (
& self ,
hasher : & mut DefaultHasher ,
error_format : ErrorOutputType ,
for_crate_hash : bool ,
) ;
2016-08-02 16:53:58 -04:00
}
macro_rules ! impl_dep_tracking_hash_via_hash {
2021-04-22 11:45:08 -04:00
( $( $t :ty ) , + $(, ) ? ) = > { $(
2016-08-02 16:53:58 -04:00
impl DepTrackingHash for $t {
2021-06-19 19:22:14 -05:00
fn hash ( & self , hasher : & mut DefaultHasher , _ : ErrorOutputType , _for_crate_hash : bool ) {
2016-08-02 16:53:58 -04:00
Hash ::hash ( self , hasher ) ;
}
}
2021-04-22 11:45:08 -04:00
) + } ;
2016-08-02 16:53:58 -04:00
}
2021-04-15 19:36:25 -04:00
impl < T : DepTrackingHash > DepTrackingHash for Option < T > {
2021-06-19 19:22:14 -05:00
fn hash (
& self ,
hasher : & mut DefaultHasher ,
error_format : ErrorOutputType ,
for_crate_hash : bool ,
) {
2021-04-15 19:36:25 -04:00
match self {
Some ( x ) = > {
Hash ::hash ( & 1 , hasher ) ;
2021-06-19 19:22:14 -05:00
DepTrackingHash ::hash ( x , hasher , error_format , for_crate_hash ) ;
2021-04-15 19:36:25 -04:00
}
None = > Hash ::hash ( & 0 , hasher ) ,
}
}
}
2021-04-22 11:45:08 -04:00
impl_dep_tracking_hash_via_hash! (
bool ,
usize ,
2024-01-29 23:59:09 +01:00
NonZero < usize > ,
2021-04-22 11:45:08 -04:00
u64 ,
2023-10-13 17:28:34 +00:00
Hash64 ,
2021-04-22 11:45:08 -04:00
String ,
PathBuf ,
lint ::Level ,
2021-04-15 19:36:25 -04:00
WasiExecModel ,
u32 ,
RelocModel ,
CodeModel ,
TlsModel ,
InstrumentCoverage ,
2024-03-08 18:07:04 +11:00
CoverageOptions ,
2022-09-24 20:02:44 +09:00
InstrumentXRay ,
2021-04-22 11:45:08 -04:00
CrateType ,
MergeFunctions ,
PanicStrategy ,
RelroLevel ,
OptLevel ,
LtoCli ,
DebugInfo ,
2023-07-12 17:07:34 -04:00
DebugInfoCompression ,
2024-01-11 01:36:05 +07:00
CollapseMacroDebuginfo ,
2021-04-22 11:45:08 -04:00
UnstableFeatures ,
2021-03-24 21:45:09 -07:00
NativeLib ,
2021-04-22 11:45:08 -04:00
SanitizerSet ,
CFGuard ,
2022-01-28 09:48:59 -08:00
CFProtection ,
2021-04-22 11:45:08 -04:00
TargetTriple ,
Edition ,
LinkerPluginLto ,
2023-02-06 21:57:45 +04:00
ResolveDocLinks ,
2021-04-15 19:36:25 -04:00
SplitDebuginfo ,
2022-07-04 14:04:35 +02:00
SplitDwarfKind ,
add rustc option for using LLVM stack smash protection
LLVM has built-in heuristics for adding stack canaries to functions. These
heuristics can be selected with LLVM function attributes. This patch adds a
rustc option `-Z stack-protector={none,basic,strong,all}` which controls the use
of these attributes. This gives rustc the same stack smash protection support as
clang offers through options `-fno-stack-protector`, `-fstack-protector`,
`-fstack-protector-strong`, and `-fstack-protector-all`. The protection this can
offer is demonstrated in test/ui/abi/stack-protector.rs. This fills a gap in the
current list of rustc exploit
mitigations (https://doc.rust-lang.org/rustc/exploit-mitigations.html),
originally discussed in #15179.
Stack smash protection adds runtime overhead and is therefore still off by
default, but now users have the option to trade performance for security as they
see fit. An example use case is adding Rust code in an existing C/C++ code base
compiled with stack smash protection. Without the ability to add stack smash
protection to the Rust code, the code base artifacts could be exploitable in
ways not possible if the code base remained pure C/C++.
Stack smash protection support is present in LLVM for almost all the current
tier 1/tier 2 targets: see
test/assembly/stack-protector/stack-protector-target-support.rs. The one
exception is nvptx64-nvidia-cuda. This patch follows clang's example, and adds a
warning message printed if stack smash protection is used with this target (see
test/ui/stack-protector/warn-stack-protector-unsupported.rs). Support for tier 3
targets has not been checked.
Since the heuristics are applied at the LLVM level, the heuristics are expected
to add stack smash protection to a fraction of functions comparable to C/C++.
Some experiments demonstrating how Rust code is affected by the different
heuristics can be found in
test/assembly/stack-protector/stack-protector-heuristics-effect.rs. There is
potential for better heuristics using Rust-specific safety information. For
example it might be reasonable to skip stack smash protection in functions which
transitively only use safe Rust code, or which uses only a subset of functions
the user declares safe (such as anything under `std.*`). Such alternative
heuristics could be added at a later point.
LLVM also offers a "safestack" sanitizer as an alternative way to guard against
stack smashing (see #26612). This could possibly also be included as a
stack-protection heuristic. An alternative is to add it as a sanitizer (#39699).
This is what clang does: safestack is exposed with option
`-fsanitize=safe-stack`.
The options are only supported by the LLVM backend, but as with other codegen
options it is visible in the main codegen option help menu. The heuristic names
"basic", "strong", and "all" are hopefully sufficiently generic to be usable in
other backends as well.
Reviewed-by: Nikita Popov <nikic@php.net>
Extra commits during review:
- [address-review] make the stack-protector option unstable
- [address-review] reduce detail level of stack-protector option help text
- [address-review] correct grammar in comment
- [address-review] use compiler flag to avoid merging functions in test
- [address-review] specify min LLVM version in fortanix stack-protector test
Only for Fortanix test, since this target specifically requests the
`--x86-experimental-lvi-inline-asm-hardening` flag.
- [address-review] specify required LLVM components in stack-protector tests
- move stack protector option enum closer to other similar option enums
- rustc_interface/tests: sort debug option list in tracking hash test
- add an explicit `none` stack-protector option
Revert "set LLVM requirements for all stack protector support test revisions"
This reverts commit a49b74f92a4e7d701d6f6cf63d207a8aff2e0f68.
2021-04-06 21:37:49 +02:00
StackProtector ,
2021-04-22 11:45:08 -04:00
SwitchWithOptPath ,
2021-04-15 19:36:25 -04:00
SymbolManglingVersion ,
2023-08-23 11:18:20 +02:00
RemapPathScopeComponents ,
2021-04-15 19:36:25 -04:00
SourceFileHashAlgorithm ,
2023-02-26 15:27:27 -05:00
OutFileName ,
2021-06-19 19:22:14 -05:00
OutputType ,
2021-08-12 15:30:40 -05:00
RealFileName ,
2021-10-13 17:01:31 -07:00
LocationDetail ,
2021-07-13 12:14:26 +01:00
BranchProtection ,
2021-10-06 15:52:54 +01:00
OomStrategy ,
2022-03-28 09:36:20 +01:00
LanguageIdentifier ,
2023-12-14 13:00:23 +01:00
NextSolverConfig ,
2023-06-30 11:55:38 +00:00
Polonius ,
2023-11-06 19:55:05 -05:00
InliningThreshold ,
2023-10-18 16:58:17 +02:00
FunctionReturn ,
2021-04-22 11:45:08 -04:00
) ;
2016-08-02 16:53:58 -04:00
impl < T1 , T2 > DepTrackingHash for ( T1 , T2 )
2018-03-06 02:29:03 -03:00
where
T1 : DepTrackingHash ,
T2 : DepTrackingHash ,
2016-08-02 16:53:58 -04:00
{
2021-06-19 19:22:14 -05:00
fn hash (
& self ,
hasher : & mut DefaultHasher ,
error_format : ErrorOutputType ,
for_crate_hash : bool ,
) {
2016-08-02 16:53:58 -04:00
Hash ::hash ( & 0 , hasher ) ;
2021-06-19 19:22:14 -05:00
DepTrackingHash ::hash ( & self . 0 , hasher , error_format , for_crate_hash ) ;
2016-08-02 16:53:58 -04:00
Hash ::hash ( & 1 , hasher ) ;
2021-06-19 19:22:14 -05:00
DepTrackingHash ::hash ( & self . 1 , hasher , error_format , for_crate_hash ) ;
2016-08-02 16:53:58 -04:00
}
}
2016-11-23 16:09:51 -08:00
impl < T1 , T2 , T3 > DepTrackingHash for ( T1 , T2 , T3 )
2018-03-06 02:29:03 -03:00
where
T1 : DepTrackingHash ,
T2 : DepTrackingHash ,
T3 : DepTrackingHash ,
2016-11-23 16:09:51 -08:00
{
2021-06-19 19:22:14 -05:00
fn hash (
& self ,
hasher : & mut DefaultHasher ,
error_format : ErrorOutputType ,
for_crate_hash : bool ,
) {
2016-11-23 16:09:51 -08:00
Hash ::hash ( & 0 , hasher ) ;
2021-06-19 19:22:14 -05:00
DepTrackingHash ::hash ( & self . 0 , hasher , error_format , for_crate_hash ) ;
2016-11-23 16:09:51 -08:00
Hash ::hash ( & 1 , hasher ) ;
2021-06-19 19:22:14 -05:00
DepTrackingHash ::hash ( & self . 1 , hasher , error_format , for_crate_hash ) ;
2016-11-23 16:09:51 -08:00
Hash ::hash ( & 2 , hasher ) ;
2021-06-19 19:22:14 -05:00
DepTrackingHash ::hash ( & self . 2 , hasher , error_format , for_crate_hash ) ;
2016-11-23 16:09:51 -08:00
}
}
2021-05-25 19:43:02 -05:00
impl < T : DepTrackingHash > DepTrackingHash for Vec < T > {
2021-06-19 19:22:14 -05:00
fn hash (
& self ,
hasher : & mut DefaultHasher ,
error_format : ErrorOutputType ,
for_crate_hash : bool ,
) {
2021-05-25 19:43:02 -05:00
Hash ::hash ( & self . len ( ) , hasher ) ;
for ( index , elem ) in self . iter ( ) . enumerate ( ) {
Hash ::hash ( & index , hasher ) ;
2021-06-19 19:22:14 -05:00
DepTrackingHash ::hash ( elem , hasher , error_format , for_crate_hash ) ;
}
}
}
2023-11-27 13:47:26 +01:00
impl < T : DepTrackingHash , V : DepTrackingHash > DepTrackingHash for FxIndexMap < T , V > {
fn hash (
& self ,
hasher : & mut DefaultHasher ,
error_format : ErrorOutputType ,
for_crate_hash : bool ,
) {
Hash ::hash ( & self . len ( ) , hasher ) ;
for ( key , value ) in self . iter ( ) {
DepTrackingHash ::hash ( key , hasher , error_format , for_crate_hash ) ;
DepTrackingHash ::hash ( value , hasher , error_format , for_crate_hash ) ;
}
}
}
2021-06-19 19:22:14 -05:00
impl DepTrackingHash for OutputTypes {
fn hash (
& self ,
hasher : & mut DefaultHasher ,
error_format : ErrorOutputType ,
for_crate_hash : bool ,
) {
Hash ::hash ( & self . 0. len ( ) , hasher ) ;
for ( key , val ) in & self . 0 {
DepTrackingHash ::hash ( key , hasher , error_format , for_crate_hash ) ;
if ! for_crate_hash {
DepTrackingHash ::hash ( val , hasher , error_format , for_crate_hash ) ;
}
2021-05-25 19:43:02 -05:00
}
}
}
2016-08-02 16:53:58 -04:00
// This is a stable hash because BTreeMap is a sorted container
2022-05-20 19:51:09 -04:00
pub ( crate ) fn stable_hash (
2018-03-06 02:29:03 -03:00
sub_hashes : BTreeMap < & 'static str , & dyn DepTrackingHash > ,
hasher : & mut DefaultHasher ,
error_format : ErrorOutputType ,
2021-06-19 19:22:14 -05:00
for_crate_hash : bool ,
2018-03-06 02:29:03 -03:00
) {
2016-08-02 16:53:58 -04:00
for ( key , sub_hash ) in sub_hashes {
// Using Hash::hash() instead of DepTrackingHash::hash() is fine for
// the keys, as they are just plain strings
Hash ::hash ( & key . len ( ) , hasher ) ;
Hash ::hash ( key , hasher ) ;
2021-06-19 19:22:14 -05:00
sub_hash . hash ( hasher , error_format , for_crate_hash ) ;
2016-08-02 16:53:58 -04:00
}
}
}
2021-10-06 15:52:54 +01:00
/// Default behavior to use in out-of-memory situations.
#[ derive(Clone, Copy, PartialEq, Hash, Debug, Encodable, Decodable, HashStable_Generic) ]
pub enum OomStrategy {
/// Generate a panic that can be caught by `catch_unwind`.
Panic ,
/// Abort the process immediately.
Abort ,
}
impl OomStrategy {
pub const SYMBOL : & 'static str = " __rust_alloc_error_handler_should_panic " ;
pub fn should_panic ( self ) -> u8 {
match self {
OomStrategy ::Panic = > 1 ,
OomStrategy ::Abort = > 0 ,
}
}
}
2022-06-18 14:15:03 -04:00
/// How to run proc-macro code when building this crate
#[ derive(Clone, Copy, PartialEq, Hash, Debug) ]
pub enum ProcMacroExecutionStrategy {
/// Run the proc-macro code on the same thread as the server.
SameThread ,
/// Run the proc-macro code on a different thread.
CrossThread ,
}
2022-12-29 21:08:09 +00:00
2024-01-11 01:36:05 +07:00
/// How to perform collapse macros debug info
/// if-ext - if macro from different crate (related to callsite code)
/// | cmd \ attr | no | (unspecified) | external | yes |
/// | no | no | no | no | no |
/// | (unspecified) | no | no | if-ext | yes |
/// | external | no | if-ext | if-ext | yes |
/// | yes | yes | yes | yes | yes |
#[ derive(Clone, Copy, PartialEq, Hash, Debug) ]
pub enum CollapseMacroDebuginfo {
/// Don't collapse debuginfo for the macro
No = 0 ,
/// Unspecified value
Unspecified = 1 ,
/// Collapse debuginfo if the macro comes from a different crate
External = 2 ,
/// Collapse debuginfo for the macro
Yes = 3 ,
}
2022-12-29 21:08:09 +00:00
/// Which format to use for `-Z dump-mono-stats`
#[ derive(Clone, Copy, PartialEq, Hash, Debug) ]
pub enum DumpMonoStatsFormat {
/// Pretty-print a markdown table
Markdown ,
/// Emit structured JSON
Json ,
}
impl DumpMonoStatsFormat {
pub fn extension ( self ) -> & 'static str {
match self {
Self ::Markdown = > " md " ,
Self ::Json = > " json " ,
}
}
}
2023-06-30 11:55:38 +00:00
/// `-Zpolonius` values, enabling the borrow checker polonius analysis, and which version: legacy,
/// or future prototype.
2023-10-20 15:32:22 +00:00
#[ derive(Clone, Copy, PartialEq, Hash, Debug, Default) ]
2023-06-30 11:55:38 +00:00
pub enum Polonius {
/// The default value: disabled.
2023-10-20 15:32:22 +00:00
#[ default ]
2023-06-30 11:55:38 +00:00
Off ,
/// Legacy version, using datalog and the `polonius-engine` crate. Historical value for `-Zpolonius`.
Legacy ,
2023-06-30 13:18:11 +00:00
/// In-tree prototype, extending the NLL infrastructure.
2023-06-30 11:55:38 +00:00
Next ,
}
impl Polonius {
/// Returns whether the legacy version of polonius is enabled
pub fn is_legacy_enabled ( & self ) -> bool {
matches! ( self , Polonius ::Legacy )
}
2023-06-30 13:18:11 +00:00
/// Returns whether the "next" version of polonius is enabled
pub fn is_next_enabled ( & self ) -> bool {
matches! ( self , Polonius ::Next )
}
2023-06-30 11:55:38 +00:00
}
2023-11-06 19:55:05 -05:00
#[ derive(Clone, Copy, PartialEq, Hash, Debug) ]
pub enum InliningThreshold {
Always ,
Sometimes ( usize ) ,
Never ,
}
impl Default for InliningThreshold {
fn default ( ) -> Self {
Self ::Sometimes ( 100 )
}
}
2023-10-18 16:58:17 +02:00
/// The different settings that the `-Zfunction-return` flag can have.
#[ derive(Clone, Copy, PartialEq, Hash, Debug, Default) ]
pub enum FunctionReturn {
/// Keep the function return unmodified.
#[ default ]
Keep ,
/// Replace returns with jumps to thunk, without emitting the thunk.
ThunkExtern ,
}