diff options
Diffstat (limited to 'compiler/rustc_session/src')
| -rw-r--r-- | compiler/rustc_session/src/code_stats.rs | 60 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config/cfg.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config/native_libs/tests.rs | 40 | ||||
| -rw-r--r-- | compiler/rustc_session/src/errors.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_session/src/lib.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_session/src/options.rs | 393 | ||||
| -rw-r--r-- | compiler/rustc_session/src/parse.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_session/src/search_paths.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_session/src/session.rs | 85 | 
10 files changed, 507 insertions, 175 deletions
| diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index f3c21992784..b4597ae2515 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -1,10 +1,9 @@ use std::cmp; use rustc_abi::{Align, Size}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lock; use rustc_span::Symbol; -use rustc_span::def_id::DefId; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct VariantInfo { @@ -71,29 +70,9 @@ pub struct TypeSizeInfo { pub variants: Vec<VariantInfo>, } -pub struct VTableSizeInfo { - pub trait_name: String, - - /// Number of entries in a vtable with the current algorithm - /// (i.e. with upcasting). - pub entries: usize, - - /// Number of entries in a vtable, as-if we did not have trait upcasting. - pub entries_ignoring_upcasting: usize, - - /// Number of entries in a vtable needed solely for upcasting - /// (i.e. `entries - entries_ignoring_upcasting`). - pub entries_for_upcasting: usize, - - /// Cost of having upcasting in % relative to the number of entries without - /// upcasting (i.e. `entries_for_upcasting / entries_ignoring_upcasting * 100%`). - pub upcasting_cost_percent: f64, -} - #[derive(Default)] pub struct CodeStats { type_sizes: Lock<FxHashSet<TypeSizeInfo>>, - vtable_sizes: Lock<FxHashMap<DefId, VTableSizeInfo>>, } impl CodeStats { @@ -127,14 +106,6 @@ impl CodeStats { self.type_sizes.borrow_mut().insert(info); } - pub fn record_vtable_size(&self, trait_did: DefId, trait_name: &str, info: VTableSizeInfo) { - let prev = self.vtable_sizes.lock().insert(trait_did, info); - assert!( - prev.is_none(), - "size of vtable for `{trait_name}` ({trait_did:?}) is already recorded" - ); - } - pub fn print_type_sizes(&self) { let type_sizes = self.type_sizes.borrow(); // We will soon sort, so the initial order does not matter. @@ -238,33 +209,4 @@ impl CodeStats { } } } - - pub fn print_vtable_sizes(&self, crate_name: Symbol) { - // We will soon sort, so the initial order does not matter. - #[allow(rustc::potential_query_instability)] - let mut infos = - std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::<Vec<_>>(); - - // Primary sort: cost % in reverse order (from largest to smallest) - // Secondary sort: trait_name - infos.sort_by(|a, b| { - a.upcasting_cost_percent - .total_cmp(&b.upcasting_cost_percent) - .reverse() - .then_with(|| a.trait_name.cmp(&b.trait_name)) - }); - - for VTableSizeInfo { - trait_name, - entries, - entries_ignoring_upcasting, - entries_for_upcasting, - upcasting_cost_percent, - } in infos - { - println!( - r#"print-vtable-sizes {{ "crate_name": "{crate_name}", "trait_name": "{trait_name}", "entries": "{entries}", "entries_ignoring_upcasting": "{entries_ignoring_upcasting}", "entries_for_upcasting": "{entries_for_upcasting}", "upcasting_cost_percent": "{upcasting_cost_percent}" }}"# - ); - } - } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 97bd2670aa6..2fb4b27b889 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -189,6 +189,39 @@ pub enum CoverageLevel { Mcdc, } +/// The different settings that the `-Z autodiff` flag can have. +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum AutoDiff { + /// Print TypeAnalysis information + PrintTA, + /// Print ActivityAnalysis Information + PrintAA, + /// Print Performance Warnings from Enzyme + PrintPerf, + /// Combines the three print flags above. + Print, + /// Print the whole module, before running opts. + PrintModBefore, + /// Print the whole module just before we pass it to Enzyme. + /// For Debug purpose, prefer the OPT flag below + PrintModAfterOpts, + /// Print the module after Enzyme differentiated everything. + PrintModAfterEnzyme, + + /// Enzyme's loose type debug helper (can cause incorrect gradients) + LooseTypes, + + /// More flags + NoModOptAfter, + /// Tell Enzyme to run LLVM Opts on each function it generated. By default off, + /// since we already optimize the whole module after Enzyme is done. + EnableFncOpt, + NoVecUnroll, + RuntimeActivity, + /// Runs Enzyme specific Inlining + Inline, +} + /// Settings for `-Z instrument-xray` flag. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] pub struct InstrumentXRay { @@ -1191,6 +1224,7 @@ impl Default for Options { color: ColorConfig::Auto, logical_env: FxIndexMap::default(), verbose: false, + target_modifiers: BTreeMap::default(), } } } @@ -1786,7 +1820,7 @@ pub fn parse_error_format( ErrorOutputType::HumanReadable(HumanReadableErrorType::Unicode, color) } Some(arg) => { - early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable( + early_dcx.set_error_format(ErrorOutputType::HumanReadable( HumanReadableErrorType::Default, color, )); @@ -2327,7 +2361,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let error_format = parse_error_format(early_dcx, matches, color, json_color, json_rendered); - early_dcx.abort_if_error_and_set_error_format(error_format); + early_dcx.set_error_format(error_format); let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| { early_dcx.early_fatal("`--diagnostic-width` must be an positive integer"); @@ -2337,14 +2371,16 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let crate_types = parse_crate_types_from_list(unparsed_crate_types) .unwrap_or_else(|e| early_dcx.early_fatal(e)); - let mut unstable_opts = UnstableOptions::build(early_dcx, matches); + let mut target_modifiers = BTreeMap::<OptionsTargetModifiers, String>::new(); + + let mut unstable_opts = UnstableOptions::build(early_dcx, matches, &mut target_modifiers); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); check_error_format_stability(early_dcx, &unstable_opts, error_format); let output_types = parse_output_types(early_dcx, &unstable_opts, matches); - let mut cg = CodegenOptions::build(early_dcx, matches); + let mut cg = CodegenOptions::build(early_dcx, matches, &mut target_modifiers); let (disable_local_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto( early_dcx, &output_types, @@ -2615,6 +2651,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M color, logical_env, verbose, + target_modifiers, } } @@ -2737,6 +2774,7 @@ pub mod nightly_options { "the option `{}` is only accepted on the nightly compiler", opt.name ); + // The non-zero nightly_options_on_stable will force an early_fatal eventually. let _ = early_dcx.early_err(msg); } OptionStability::Stable => {} @@ -2902,7 +2940,7 @@ pub(crate) mod dep_tracking { }; use super::{ - BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions, + AutoDiff, BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, OomStrategy, OptLevel, OutFileName, @@ -2950,6 +2988,7 @@ pub(crate) mod dep_tracking { } impl_dep_tracking_hash_via_hash!( + AutoDiff, bool, usize, NonZero<usize>, diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index d586f913335..aa9ebdd9cea 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -9,7 +9,7 @@ //! //! ## Adding a new cfg //! -//! Adding a new feature requires two new symbols one for the cfg it-self +//! Adding a new feature requires two new symbols one for the cfg itself //! and the second one for the unstable feature gate, those are defined in //! `rustc_span::symbol`. //! @@ -119,6 +119,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) { (sym::overflow_checks, None) => disallow(cfg, "-C overflow-checks"), (sym::debug_assertions, None) => disallow(cfg, "-C debug-assertions"), (sym::ub_checks, None) => disallow(cfg, "-Z ub-checks"), + (sym::contract_checks, None) => disallow(cfg, "-Z contract-checks"), (sym::sanitize, None | Some(_)) => disallow(cfg, "-Z sanitizer"), ( sym::sanitizer_cfi_generalize_pointers | sym::sanitizer_cfi_normalize_integers, @@ -300,6 +301,11 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { if sess.is_nightly_build() && sess.opts.unstable_opts.emscripten_wasm_eh { ins_none!(sym::emscripten_wasm_eh); } + + if sess.contract_checks() { + ins_none!(sym::contract_checks); + } + ret } @@ -421,7 +427,7 @@ impl CheckCfg { Some(values_target_os), Some(values_target_pointer_width), Some(values_target_vendor), - ] = self.expecteds.get_many_mut(VALUES) + ] = self.expecteds.get_disjoint_mut(VALUES) else { panic!("unable to get all the check-cfg values buckets"); }; @@ -464,6 +470,7 @@ impl CheckCfg { ins!(sym::target_thread_local, no_values); ins!(sym::ub_checks, no_values); + ins!(sym::contract_checks, no_values); ins!(sym::unix, no_values); ins!(sym::windows, no_values); diff --git a/compiler/rustc_session/src/config/native_libs/tests.rs b/compiler/rustc_session/src/config/native_libs/tests.rs index 3bcab93ef4b..287c98fe7eb 100644 --- a/compiler/rustc_session/src/config/native_libs/tests.rs +++ b/compiler/rustc_session/src/config/native_libs/tests.rs @@ -14,30 +14,22 @@ fn split() { (":bar", P { kind: None, modifiers: None, name: "", new_name: Some("bar") }), ("kind=foo", P { kind: Some("kind"), modifiers: None, name: "foo", new_name: None }), (":mods=foo", P { kind: Some(""), modifiers: Some("mods"), name: "foo", new_name: None }), - (":mods=:bar", P { - kind: Some(""), - modifiers: Some("mods"), - name: "", - new_name: Some("bar"), - }), - ("kind=foo:bar", P { - kind: Some("kind"), - modifiers: None, - name: "foo", - new_name: Some("bar"), - }), - ("kind:mods=foo", P { - kind: Some("kind"), - modifiers: Some("mods"), - name: "foo", - new_name: None, - }), - ("kind:mods=foo:bar", P { - kind: Some("kind"), - modifiers: Some("mods"), - name: "foo", - new_name: Some("bar"), - }), + ( + ":mods=:bar", + P { kind: Some(""), modifiers: Some("mods"), name: "", new_name: Some("bar") }, + ), + ( + "kind=foo:bar", + P { kind: Some("kind"), modifiers: None, name: "foo", new_name: Some("bar") }, + ), + ( + "kind:mods=foo", + P { kind: Some("kind"), modifiers: Some("mods"), name: "foo", new_name: None }, + ), + ( + "kind:mods=foo:bar", + P { kind: Some("kind"), modifiers: Some("mods"), name: "foo", new_name: Some("bar") }, + ), ("::==::", P { kind: Some(""), modifiers: Some(":"), name: "=", new_name: Some(":") }), ("==::==", P { kind: Some(""), modifiers: None, name: "=", new_name: Some(":==") }), ]; diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 6c26a781487..75c3b2c7a85 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -161,6 +161,7 @@ pub(crate) struct UnstableVirtualFunctionElimination; #[derive(Diagnostic)] #[diag(session_unsupported_dwarf_version)] +#[help(session_unsupported_dwarf_version_help)] pub(crate) struct UnsupportedDwarfVersion { pub(crate) dwarf_version: u32, } diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index dcf86d1a408..112adde3740 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -2,8 +2,10 @@ #![allow(internal_features)] #![feature(iter_intersperse)] #![feature(let_chains)] -#![feature(map_many_mut)] #![feature(rustc_attrs)] +// To generate CodegenOptionsTargetModifiers and UnstableOptionsTargetModifiers enums +// with macro_rules, it is necessary to use recursive mechanic ("Incremental TT Munchers"). +#![recursion_limit = "256"] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 63aaa3abc8e..35819f896c5 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -10,6 +10,7 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_data_structures::stable_hasher::Hash64; use rustc_errors::{ColorConfig, LanguageIdentifier, TerminalUrl}; use rustc_feature::UnstableFeatures; +use rustc_macros::{Decodable, Encodable}; use rustc_span::edition::Edition; use rustc_span::{RealFileName, SourceFileHashAlgorithm}; use rustc_target::spec::{ @@ -59,18 +60,194 @@ macro_rules! hash_substruct { }; } +/// Extended target modifier info. +/// For example, when external target modifier is '-Zregparm=2': +/// Target modifier enum value + user value ('2') from external crate +/// is converted into description: prefix ('Z'), name ('regparm'), tech value ('Some(2)'). +pub struct ExtendedTargetModifierInfo { + /// Flag prefix (usually, 'C' for codegen flags or 'Z' for unstable flags) + pub prefix: String, + /// Flag name + pub name: String, + /// Flag parsed technical value + pub tech_value: String, +} + +/// A recorded -Zopt_name=opt_value (or -Copt_name=opt_value) +/// which alter the ABI or effectiveness of exploit mitigations. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)] +pub struct TargetModifier { + /// Option enum value + pub opt: OptionsTargetModifiers, + /// User-provided option value (before parsing) + pub value_name: String, +} + +impl TargetModifier { + pub fn extend(&self) -> ExtendedTargetModifierInfo { + self.opt.reparse(&self.value_name) + } +} + +fn tmod_push_impl( + opt: OptionsTargetModifiers, + tmod_vals: &BTreeMap<OptionsTargetModifiers, String>, + tmods: &mut Vec<TargetModifier>, +) { + tmods.push(TargetModifier { opt, value_name: tmod_vals.get(&opt).cloned().unwrap_or_default() }) +} + +macro_rules! tmod_push { + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $mods:expr, $tmod_vals:expr) => { + tmod_push_impl( + OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt_name), + $tmod_vals, + $mods, + ); + }; +} + +macro_rules! gather_tmods { + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + [SUBSTRUCT], [TARGET_MODIFIER]) => { + compile_error!("SUBSTRUCT can't be target modifier"); + }; + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + [UNTRACKED], [TARGET_MODIFIER]) => { + tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals) + }; + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + [TRACKED], [TARGET_MODIFIER]) => { + tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals) + }; + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + [TRACKED_NO_CRATE_HASH], [TARGET_MODIFIER]) => { + tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals) + }; + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + [SUBSTRUCT], []) => { + $opt_expr.gather_target_modifiers($mods, $tmod_vals); + }; + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + [UNTRACKED], []) => {{}}; + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + [TRACKED], []) => {{}}; + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + [TRACKED_NO_CRATE_HASH], []) => {{}}; +} + +macro_rules! gather_tmods_top_level { + ($_opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, [SUBSTRUCT $substruct_enum:ident]) => { + $opt_expr.gather_target_modifiers($mods, $tmod_vals); + }; + ($opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, [$non_substruct:ident TARGET_MODIFIER]) => { + compile_error!("Top level option can't be target modifier"); + }; + ($opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, [$non_substruct:ident]) => {}; +} + +/// Macro for generating OptionsTargetsModifiers top-level enum with impl. +/// Will generate something like: +/// ```rust,ignore (illustrative) +/// pub enum OptionsTargetModifiers { +/// CodegenOptions(CodegenOptionsTargetModifiers), +/// UnstableOptions(UnstableOptionsTargetModifiers), +/// } +/// impl OptionsTargetModifiers { +/// pub fn reparse(&self, user_value: &str) -> ExtendedTargetModifierInfo { +/// match self { +/// Self::CodegenOptions(v) => v.reparse(user_value), +/// Self::UnstableOptions(v) => v.reparse(user_value), +/// } +/// } +/// pub fn is_target_modifier(flag_name: &str) -> bool { +/// CodegenOptionsTargetModifiers::is_target_modifier(flag_name) || +/// UnstableOptionsTargetModifiers::is_target_modifier(flag_name) +/// } +/// } +/// ``` +macro_rules! top_level_tmod_enum { + ($( {$($optinfo:tt)*} ),* $(,)*) => { + top_level_tmod_enum! { @parse {}, (user_value){}; $($($optinfo)*|)* } + }; + // Termination + ( + @parse + {$($variant:tt($substruct_enum:tt))*}, + ($user_value:ident){$($pout:tt)*}; + ) => { + #[allow(non_camel_case_types)] + #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone, Encodable, Decodable)] + pub enum OptionsTargetModifiers { + $($variant($substruct_enum)),* + } + impl OptionsTargetModifiers { + #[allow(unused_variables)] + pub fn reparse(&self, $user_value: &str) -> ExtendedTargetModifierInfo { + #[allow(unreachable_patterns)] + match self { + $($pout)* + _ => panic!("unknown target modifier option: {:?}", *self) + } + } + pub fn is_target_modifier(flag_name: &str) -> bool { + $($substruct_enum::is_target_modifier(flag_name))||* + } + } + }; + // Adding SUBSTRUCT option group into $eout + ( + @parse {$($eout:tt)*}, ($puser_value:ident){$($pout:tt)*}; + [SUBSTRUCT $substruct_enum:ident $variant:ident] | + $($tail:tt)* + ) => { + top_level_tmod_enum! { + @parse + { + $($eout)* + $variant($substruct_enum) + }, + ($puser_value){ + $($pout)* + Self::$variant(v) => v.reparse($puser_value), + }; + $($tail)* + } + }; + // Skipping non-target-modifier and non-substruct + ( + @parse {$($eout:tt)*}, ($puser_value:ident){$($pout:tt)*}; + [$non_substruct:ident] | + $($tail:tt)* + ) => { + top_level_tmod_enum! { + @parse + { + $($eout)* + }, + ($puser_value){ + $($pout)* + }; + $($tail)* + } + }; +} + macro_rules! top_level_options { ( $( #[$top_level_attr:meta] )* pub struct Options { $( $( #[$attr:meta] )* - $opt:ident : $t:ty [$dep_tracking_marker:ident], + $opt:ident : $t:ty [$dep_tracking_marker:ident $( $tmod:ident $variant:ident )?], )* } ) => ( + top_level_tmod_enum!( {$([$dep_tracking_marker $($tmod $variant),*])|*} ); + #[derive(Clone)] $( #[$top_level_attr] )* pub struct Options { $( $( #[$attr] )* pub $opt: $t - ),* + ),*, + pub target_modifiers: BTreeMap<OptionsTargetModifiers, String>, } impl Options { @@ -98,6 +275,17 @@ macro_rules! top_level_options { })* hasher.finish() } + + pub fn gather_target_modifiers(&self) -> Vec<TargetModifier> { + let mut mods = Vec::<TargetModifier>::new(); + $({ + gather_tmods_top_level!($opt, + &self.$opt, &mut mods, &self.target_modifiers, + [$dep_tracking_marker $($tmod),*]); + })* + mods.sort_by(|a, b| a.opt.cmp(&b.opt)); + mods + } } ); } @@ -165,9 +353,9 @@ top_level_options!( #[rustc_lint_opt_deny_field_access("should only be used via `Config::hash_untracked_state`")] untracked_state_hash: Hash64 [TRACKED_NO_CRATE_HASH], - unstable_opts: UnstableOptions [SUBSTRUCT], + unstable_opts: UnstableOptions [SUBSTRUCT UnstableOptionsTargetModifiers UnstableOptions], prints: Vec<PrintRequest> [UNTRACKED], - cg: CodegenOptions [SUBSTRUCT], + cg: CodegenOptions [SUBSTRUCT CodegenOptionsTargetModifiers CodegenOptions], externs: Externs [UNTRACKED], crate_name: Option<String> [TRACKED], /// Indicates how the compiler should treat unstable features. @@ -226,6 +414,98 @@ top_level_options!( } ); +macro_rules! tmod_enum_opt { + ($struct_name:ident, $tmod_enum_name:ident, $opt:ident, $v:ident) => { + Some(OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt)) + }; + ($struct_name:ident, $tmod_enum_name:ident, $opt:ident, ) => { + None + }; +} + +macro_rules! tmod_enum { + ($tmod_enum_name:ident, $prefix:expr, $( {$($optinfo:tt)*} ),* $(,)*) => { + tmod_enum! { $tmod_enum_name, $prefix, @parse {}, (user_value){}; $($($optinfo)*|)* } + }; + // Termination + ( + $tmod_enum_name:ident, $prefix:expr, + @parse + {$($eout:tt)*}, + ($user_value:ident){$($pout:tt)*}; + ) => { + #[allow(non_camel_case_types)] + #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone, Encodable, Decodable)] + pub enum $tmod_enum_name { + $($eout),* + } + impl $tmod_enum_name { + #[allow(unused_variables)] + pub fn reparse(&self, $user_value: &str) -> ExtendedTargetModifierInfo { + #[allow(unreachable_patterns)] + match self { + $($pout)* + _ => panic!("unknown target modifier option: {:?}", *self) + } + } + pub fn is_target_modifier(flag_name: &str) -> bool { + match flag_name.replace('-', "_").as_str() { + $(stringify!($eout) => true,)* + _ => false, + } + } + } + }; + // Adding target-modifier option into $eout + ( + $tmod_enum_name:ident, $prefix:expr, + @parse {$($eout:tt)*}, ($puser_value:ident){$($pout:tt)*}; + $opt:ident, $parse:ident, $t:ty, [TARGET_MODIFIER] | + $($tail:tt)* + ) => { + tmod_enum! { + $tmod_enum_name, $prefix, + @parse + { + $($eout)* + $opt + }, + ($puser_value){ + $($pout)* + Self::$opt => { + let mut parsed : $t = Default::default(); + parse::$parse(&mut parsed, Some($puser_value)); + ExtendedTargetModifierInfo { + prefix: $prefix.to_string(), + name: stringify!($opt).to_string().replace('_', "-"), + tech_value: format!("{:?}", parsed), + } + }, + }; + $($tail)* + } + }; + // Skipping non-target-modifier + ( + $tmod_enum_name:ident, $prefix:expr, + @parse {$($eout:tt)*}, ($puser_value:ident){$($pout:tt)*}; + $opt:ident, $parse:ident, $t:ty, [] | + $($tail:tt)* + ) => { + tmod_enum! { + $tmod_enum_name, $prefix, + @parse + { + $($eout)* + }, + ($puser_value){ + $($pout)* + }; + $($tail)* + } + }; +} + /// Defines all `CodegenOptions`/`DebuggingOptions` fields and parsers all at once. The goal of this /// macro is to define an interface that can be programmatically used by the option parser /// to initialize the struct without hardcoding field names all over the place. @@ -235,11 +515,11 @@ top_level_options!( /// generated code to parse an option into its respective field in the struct. There are a few /// hand-written parsers for parsing specific types of values in this module. macro_rules! options { - ($struct_name:ident, $stat:ident, $optmod:ident, $prefix:expr, $outputname:expr, + ($struct_name:ident, $tmod_enum_name:ident, $stat:ident, $optmod:ident, $prefix:expr, $outputname:expr, $($( #[$attr:meta] )* $opt:ident : $t:ty = ( $init:expr, $parse:ident, - [$dep_tracking_marker:ident], + [$dep_tracking_marker:ident $( $tmod:ident )?], $desc:expr $(, deprecated_do_nothing: $dnn:literal )?) ),* ,) => @@ -248,6 +528,8 @@ macro_rules! options { #[rustc_lint_opt_ty] pub struct $struct_name { $( $( #[$attr] )* pub $opt: $t),* } + tmod_enum!( $tmod_enum_name, $prefix, {$($opt, $parse, $t, [$($tmod),*])|*} ); + impl Default for $struct_name { fn default() -> $struct_name { $struct_name { $($opt: $init),* } @@ -258,8 +540,9 @@ macro_rules! options { pub fn build( early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches, + target_modifiers: &mut BTreeMap<OptionsTargetModifiers, String>, ) -> $struct_name { - build_options(early_dcx, matches, $stat, $prefix, $outputname) + build_options(early_dcx, matches, target_modifiers, $stat, $prefix, $outputname) } fn dep_tracking_hash(&self, for_crate_hash: bool, error_format: ErrorOutputType) -> u64 { @@ -279,11 +562,23 @@ macro_rules! options { ); hasher.finish() } + + pub fn gather_target_modifiers( + &self, + _mods: &mut Vec<TargetModifier>, + _tmod_vals: &BTreeMap<OptionsTargetModifiers, String>, + ) { + $({ + gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, _mods, _tmod_vals, + [$dep_tracking_marker], [$($tmod),*]); + })* + } } pub const $stat: OptionDescrs<$struct_name> = &[ $( OptionDesc{ name: stringify!($opt), setter: $optmod::$opt, - type_desc: desc::$parse, desc: $desc, is_deprecated_and_do_nothing: false $( || $dnn )? } ),* ]; + type_desc: desc::$parse, desc: $desc, is_deprecated_and_do_nothing: false $( || $dnn )?, + tmod: tmod_enum_opt!($struct_name, $tmod_enum_name, $opt, $($tmod),*) } ),* ]; mod $optmod { $( @@ -328,6 +623,7 @@ pub struct OptionDesc<O> { // description for option from options table desc: &'static str, is_deprecated_and_do_nothing: bool, + tmod: Option<OptionsTargetModifiers>, } impl<O> OptionDesc<O> { @@ -344,6 +640,7 @@ impl<O> OptionDesc<O> { fn build_options<O: Default>( early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches, + target_modifiers: &mut BTreeMap<OptionsTargetModifiers, String>, descrs: OptionDescrs<O>, prefix: &str, outputname: &str, @@ -357,7 +654,14 @@ fn build_options<O: Default>( let option_to_lookup = key.replace('-', "_"); match descrs.iter().find(|opt_desc| opt_desc.name == option_to_lookup) { - Some(OptionDesc { name: _, setter, type_desc, desc, is_deprecated_and_do_nothing }) => { + Some(OptionDesc { + name: _, + setter, + type_desc, + desc, + is_deprecated_and_do_nothing, + tmod, + }) => { if *is_deprecated_and_do_nothing { // deprecation works for prefixed options only assert!(!prefix.is_empty()); @@ -377,6 +681,11 @@ fn build_options<O: Default>( ), } } + if let Some(tmod) = *tmod + && let Some(value) = value + { + target_modifiers.insert(tmod, value.to_string()); + } } None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")), } @@ -398,6 +707,7 @@ mod desc { pub(crate) const parse_list: &str = "a space-separated list of strings"; pub(crate) const parse_list_with_polarity: &str = "a comma-separated list of strings, with elements beginning with + or -"; + pub(crate) const parse_autodiff: &str = "a comma separated list of settings: `Print`, `PrintTA`, `PrintAA`, `PrintPerf`, `PrintModBefore`, `PrintModAfterOpts`, `PrintModAfterEnzyme`, `LooseTypes`, `NoModOptAfter`, `EnableFncOpt`, `NoVecUnroll`, `Inline`"; pub(crate) const parse_comma_list: &str = "a comma-separated list of strings"; pub(crate) const parse_opt_comma_list: &str = parse_comma_list; pub(crate) const parse_number: &str = "a number"; @@ -1029,6 +1339,38 @@ pub mod parse { } } + pub(crate) fn parse_autodiff(slot: &mut Vec<AutoDiff>, v: Option<&str>) -> bool { + let Some(v) = v else { + *slot = vec![]; + return true; + }; + let mut v: Vec<&str> = v.split(",").collect(); + v.sort_unstable(); + for &val in v.iter() { + let variant = match val { + "PrintTA" => AutoDiff::PrintTA, + "PrintAA" => AutoDiff::PrintAA, + "PrintPerf" => AutoDiff::PrintPerf, + "Print" => AutoDiff::Print, + "PrintModBefore" => AutoDiff::PrintModBefore, + "PrintModAfterOpts" => AutoDiff::PrintModAfterOpts, + "PrintModAfterEnzyme" => AutoDiff::PrintModAfterEnzyme, + "LooseTypes" => AutoDiff::LooseTypes, + "NoModOptAfter" => AutoDiff::NoModOptAfter, + "EnableFncOpt" => AutoDiff::EnableFncOpt, + "NoVecUnroll" => AutoDiff::NoVecUnroll, + "Inline" => AutoDiff::Inline, + _ => { + // FIXME(ZuseZ4): print an error saying which value is not recognized + return false; + } + }; + slot.push(variant); + } + + true + } + pub(crate) fn parse_instrument_coverage( slot: &mut InstrumentCoverage, v: Option<&str>, @@ -1581,7 +1923,7 @@ pub mod parse { } options! { - CodegenOptions, CG_OPTIONS, cgopts, "C", "codegen", + CodegenOptions, CodegenOptionsTargetModifiers, CG_OPTIONS, cgopts, "C", "codegen", // If you add a new option, please update: // - compiler/rustc_interface/src/tests.rs @@ -1712,6 +2054,8 @@ options! { target_feature: String = (String::new(), parse_target_feature, [TRACKED], "target specific attributes. (`rustc --print target-features` for details). \ This feature is unsafe."), + unsafe_allow_abi_mismatch: Vec<String> = (Vec::new(), parse_comma_list, [UNTRACKED], + "Allow incompatible target modifiers in dependency crates (comma separated list)"), // tidy-alphabetical-end // If you add a new option, please update: @@ -1720,7 +2064,7 @@ options! { } options! { - UnstableOptions, Z_OPTIONS, dbopts, "Z", "unstable", + UnstableOptions, UnstableOptionsTargetModifiers, Z_OPTIONS, dbopts, "Z", "unstable", // If you add a new option, please update: // - compiler/rustc_interface/src/tests.rs @@ -1736,6 +2080,22 @@ options! { either `loaded` or `not-loaded`."), assume_incomplete_release: bool = (false, parse_bool, [TRACKED], "make cfg(version) treat the current version as incomplete (default: no)"), + autodiff: Vec<crate::config::AutoDiff> = (Vec::new(), parse_autodiff, [TRACKED], + "a list of optional autodiff flags to enable + Optional extra settings: + `=PrintTA` + `=PrintAA` + `=PrintPerf` + `=Print` + `=PrintModBefore` + `=PrintModAfterOpts` + `=PrintModAfterEnzyme` + `=LooseTypes` + `=NoModOptAfter` + `=EnableFncOpt` + `=NoVecUnroll` + `=Inline` + Multiple options can be combined with commas."), #[rustc_lint_opt_deny_field_access("use `Session::binary_dep_depinfo` instead of this field")] binary_dep_depinfo: bool = (false, parse_bool, [TRACKED], "include artifacts (sysroot, crate dependencies) used during compilation in dep-info \ @@ -1754,6 +2114,8 @@ options! { "the backend to use"), combine_cgu: bool = (false, parse_bool, [TRACKED], "combine CGUs into a single one"), + contract_checks: Option<bool> = (None, parse_opt_bool, [TRACKED], + "emit runtime checks for contract pre- and post-conditions (default: no)"), coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED], "control details of coverage instrumentation"), crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED], @@ -1803,6 +2165,7 @@ options! { "output statistics about monomorphization collection"), dump_mono_stats_format: DumpMonoStatsFormat = (DumpMonoStatsFormat::Markdown, parse_dump_mono_stats, [UNTRACKED], "the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)"), + #[rustc_lint_opt_deny_field_access("use `Session::dwarf_version` instead of this field")] dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED], "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), dylib_lto: bool = (false, parse_bool, [UNTRACKED], @@ -1870,8 +2233,6 @@ options! { "verify extended properties for incr. comp. (default: no): - hashes of green query instances - hash collisions of query keys"), - inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED], - "control whether `#[inline]` functions are in all CGUs"), inline_llvm: bool = (true, parse_bool, [TRACKED], "enable LLVM inlining (default: yes)"), inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED], @@ -2035,8 +2396,6 @@ options! { Note that this overwrites the effect `-Clink-dead-code` has on collection!"), print_type_sizes: bool = (false, parse_bool, [UNTRACKED], "print layout information for each type encountered (default: no)"), - print_vtable_sizes: bool = (false, parse_bool, [UNTRACKED], - "print size comparison between old and new vtable layouts (default: no)"), proc_macro_backtrace: bool = (false, parse_bool, [UNTRACKED], "show backtraces for panics during proc-macro execution (default: no)"), proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread, @@ -2052,10 +2411,10 @@ options! { "enable queries of the dependency graph for regression testing (default: no)"), randomize_layout: bool = (false, parse_bool, [TRACKED], "randomize the layout of types (default: no)"), - reg_struct_return: bool = (false, parse_bool, [TRACKED], + reg_struct_return: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER], "On x86-32 targets, it overrides the default ABI to return small structs in registers. It is UNSOUND to link together crates that use different values for this flag!"), - regparm: Option<u32> = (None, parse_opt_number, [TRACKED], + regparm: Option<u32> = (None, parse_opt_number, [TRACKED TARGET_MODIFIER], "On x86-32 targets, setting this to N causes the compiler to pass N arguments \ in registers EAX, EDX, and ECX instead of on the stack for\ \"C\", \"cdecl\", and \"stdcall\" fn.\ diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 90361efed84..e0405a71f65 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -2,11 +2,12 @@ //! It also serves as an input to the parser itself. use std::str; +use std::sync::Arc; use rustc_ast::attr::AttrIdGenerator; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; -use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; +use rustc_data_structures::sync::{AppendOnlyVec, Lock}; use rustc_errors::emitter::{HumanEmitter, SilentEmitter, stderr_destination}; use rustc_errors::{ ColorConfig, Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, EmissionGuarantee, MultiSpan, @@ -214,7 +215,7 @@ pub struct ParseSess { /// should be. Useful to avoid bad tokenization when encountering emoji. We group them to /// provide a single error per unique incorrect identifier. pub bad_unicode_identifiers: Lock<FxIndexMap<Symbol, Vec<Span>>>, - source_map: Lrc<SourceMap>, + source_map: Arc<SourceMap>, pub buffered_lints: Lock<Vec<BufferedEarlyLint>>, /// Contains the spans of block expressions that could have been incomplete based on the /// operation token that followed it, but that the parser cannot identify without further @@ -239,16 +240,16 @@ impl ParseSess { /// Used for testing. pub fn new(locale_resources: Vec<&'static str>) -> Self { let fallback_bundle = fallback_fluent_bundle(locale_resources, false); - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new( HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle) - .sm(Some(Lrc::clone(&sm))), + .sm(Some(Arc::clone(&sm))), ); let dcx = DiagCtxt::new(emitter); ParseSess::with_dcx(dcx, sm) } - pub fn with_dcx(dcx: DiagCtxt, source_map: Lrc<SourceMap>) -> Self { + pub fn with_dcx(dcx: DiagCtxt, source_map: Arc<SourceMap>) -> Self { Self { dcx, unstable_features: UnstableFeatures::from_environment(None), @@ -276,15 +277,11 @@ impl ParseSess { emit_fatal_diagnostic: bool, ) -> Self { let fallback_bundle = fallback_fluent_bundle(locale_resources, false); - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let emitter = Box::new(HumanEmitter::new( - stderr_destination(ColorConfig::Auto), - Lrc::clone(&fallback_bundle), - )); - let fatal_dcx = DiagCtxt::new(emitter); + let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); + let fatal_emitter = + Box::new(HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle)); let dcx = DiagCtxt::new(Box::new(SilentEmitter { - fallback_bundle, - fatal_dcx, + fatal_emitter, fatal_note: Some(fatal_note), emit_fatal_diagnostic, })) @@ -297,8 +294,8 @@ impl ParseSess { &self.source_map } - pub fn clone_source_map(&self) -> Lrc<SourceMap> { - Lrc::clone(&self.source_map) + pub fn clone_source_map(&self) -> Arc<SourceMap> { + Arc::clone(&self.source_map) } pub fn buffer_lint( @@ -341,8 +338,4 @@ impl ParseSess { pub fn dcx(&self) -> DiagCtxtHandle<'_> { self.dcx.handle() } - - pub fn set_dcx(&mut self, dcx: DiagCtxt) { - self.dcx = dcx; - } } diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs index 78473fccd2d..b750d870cb6 100644 --- a/compiler/rustc_session/src/search_paths.rs +++ b/compiler/rustc_session/src/search_paths.rs @@ -140,10 +140,10 @@ impl SearchPath { e.ok().and_then(|e| { e.file_name().to_str().map(|s| { let file_name_str: Arc<str> = s.into(); - (Arc::clone(&file_name_str), SearchPathFile { - path: e.path().into(), - file_name_str, - }) + ( + Arc::clone(&file_name_str), + SearchPathFile { path: e.path().into(), file_name_str }, + ) }) }) }) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 60f1154dc6d..f795ad1ee17 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -9,9 +9,7 @@ use std::{env, fmt, io}; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; -use rustc_data_structures::sync::{ - DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock, -}; +use rustc_data_structures::sync::{DynSend, DynSync, Lock, MappedReadGuard, ReadGuard, RwLock}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; use rustc_errors::codes::*; use rustc_errors::emitter::{ @@ -138,8 +136,8 @@ pub struct Session { pub target: Target, pub host: Target, pub opts: config::Options, - pub host_tlib_path: Lrc<SearchPath>, - pub target_tlib_path: Lrc<SearchPath>, + pub host_tlib_path: Arc<SearchPath>, + pub target_tlib_path: Arc<SearchPath>, pub psess: ParseSess, pub sysroot: PathBuf, /// Input, input file path and output file path to this compilation process. @@ -154,7 +152,7 @@ pub struct Session { pub code_stats: CodeStats, /// This only ever stores a `LintStore` but we don't want a dependency on that type here. - pub lint_store: Option<Lrc<dyn LintStoreMarker>>, + pub lint_store: Option<Arc<dyn LintStoreMarker>>, /// Cap lint level specified by a driver specifically. pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>, @@ -189,7 +187,7 @@ pub struct Session { /// enabled. Makes it so that "please report a bug" is hidden, as ICEs with /// internal features are wontfix, and they are usually the cause of the ICEs. /// None signifies that this is not tracked. - pub using_internal_features: Arc<AtomicBool>, + pub using_internal_features: &'static AtomicBool, /// All commandline args used to invoke the compiler, with @file args fully expanded. /// This will only be used within debug info, e.g. in the pdb file on windows @@ -709,6 +707,10 @@ impl Session { self.opts.unstable_opts.ub_checks.unwrap_or(self.opts.debug_assertions) } + pub fn contract_checks(&self) -> bool { + self.opts.unstable_opts.contract_checks.unwrap_or(false) + } + pub fn relocation_model(&self) -> RelocModel { self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model) } @@ -732,6 +734,11 @@ impl Session { self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo) } + /// Returns the DWARF version passed on the CLI or the default for the target. + pub fn dwarf_version(&self) -> u32 { + self.opts.unstable_opts.dwarf_version.unwrap_or(self.target.default_dwarf_version) + } + pub fn stack_protector(&self) -> StackProtector { if self.target.options.supports_stack_protector { self.opts.unstable_opts.stack_protector @@ -876,8 +883,8 @@ impl Session { #[allow(rustc::bad_opt_access)] fn default_emitter( sopts: &config::Options, - source_map: Lrc<SourceMap>, - bundle: Option<Lrc<FluentBundle>>, + source_map: Arc<SourceMap>, + bundle: Option<Arc<FluentBundle>>, fallback_bundle: LazyFallbackBundle, ) -> Box<DynEmitter> { let macro_backtrace = sopts.unstable_opts.macro_backtrace; @@ -895,13 +902,16 @@ fn default_emitter( } t => t, }; + + let source_map = if sopts.unstable_opts.link_only { None } else { Some(source_map) }; + match sopts.error_format { config::ErrorOutputType::HumanReadable(kind, color_config) => { let short = kind.short(); if let HumanReadableErrorType::AnnotateSnippet = kind { let emitter = AnnotateSnippetEmitter::new( - Some(source_map), + source_map, bundle, fallback_bundle, short, @@ -911,7 +921,7 @@ fn default_emitter( } else { let emitter = HumanEmitter::new(stderr_destination(color_config), fallback_bundle) .fluent_bundle(bundle) - .sm(Some(source_map)) + .sm(source_map) .short_message(short) .teach(sopts.unstable_opts.teach) .diagnostic_width(sopts.diagnostic_width) @@ -955,10 +965,9 @@ fn default_emitter( #[allow(rustc::bad_opt_access)] #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub fn build_session( - early_dcx: EarlyDiagCtxt, sopts: config::Options, io: CompilerIO, - bundle: Option<Lrc<rustc_errors::FluentBundle>>, + bundle: Option<Arc<rustc_errors::FluentBundle>>, registry: rustc_errors::registry::Registry, fluent_resources: Vec<&'static str>, driver_lint_caps: FxHashMap<lint::LintId, lint::Level>, @@ -966,7 +975,7 @@ pub fn build_session( sysroot: PathBuf, cfg_version: &'static str, ice_file: Option<PathBuf>, - using_internal_features: Arc<AtomicBool>, + using_internal_features: &'static AtomicBool, expanded_args: Vec<String>, ) -> Session { // FIXME: This is not general enough to make the warning lint completely override @@ -980,20 +989,12 @@ pub fn build_session( let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow); let can_emit_warnings = !(warnings_allow || cap_lints_allow); - let host_triple = TargetTuple::from_tuple(config::host_tuple()); - let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| { - early_dcx.early_fatal(format!("Error loading host specification: {e}")) - }); - for warning in target_warnings.warning_messages() { - early_dcx.early_warn(warning) - } - let fallback_bundle = fallback_fluent_bundle( fluent_resources, sopts.unstable_opts.translate_directionality_markers, ); let source_map = rustc_span::source_map::get_source_map().unwrap(); - let emitter = default_emitter(&sopts, Lrc::clone(&source_map), bundle, fallback_bundle); + let emitter = default_emitter(&sopts, Arc::clone(&source_map), bundle, fallback_bundle); let mut dcx = DiagCtxt::new(emitter) .with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings)) @@ -1002,9 +1003,12 @@ pub fn build_session( dcx = dcx.with_ice_file(ice_file); } - // Now that the proper handler has been constructed, drop early_dcx to - // prevent accidental use. - drop(early_dcx); + let host_triple = TargetTuple::from_tuple(config::host_tuple()); + let (host, target_warnings) = Target::search(&host_triple, &sysroot) + .unwrap_or_else(|e| dcx.handle().fatal(format!("Error loading host specification: {e}"))); + for warning in target_warnings.warning_messages() { + dcx.handle().warn(warning) + } let self_profiler = if let SwitchWithOptPath::Enabled(ref d) = sopts.unstable_opts.self_profile { @@ -1033,13 +1037,13 @@ pub fn build_session( let host_triple = config::host_tuple(); let target_triple = sopts.target_triple.tuple(); - let host_tlib_path = Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, host_triple)); + let host_tlib_path = Arc::new(SearchPath::from_sysroot_and_triple(&sysroot, host_triple)); let target_tlib_path = if host_triple == target_triple { // Use the same `SearchPath` if host and target triple are identical to avoid unnecessary // rescanning of the target lib path and an unnecessary allocation. - Lrc::clone(&host_tlib_path) + Arc::clone(&host_tlib_path) } else { - Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, target_triple)) + Arc::new(SearchPath::from_sysroot_and_triple(&sysroot, target_triple)) }; let prof = SelfProfilerRef::new( @@ -1247,7 +1251,8 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version { - if dwarf_version > 5 { + // DWARF 1 is not supported by LLVM and DWARF 6 is not yet finalized. + if dwarf_version < 2 || dwarf_version > 5 { sess.dcx().emit_err(errors::UnsupportedDwarfVersion { dwarf_version }); } } @@ -1260,8 +1265,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } if sess.opts.unstable_opts.embed_source { - let dwarf_version = - sess.opts.unstable_opts.dwarf_version.unwrap_or(sess.target.default_dwarf_version); + let dwarf_version = sess.dwarf_version(); if dwarf_version < 5 { sess.dcx().emit_warn(errors::EmbedSourceInsufficientDwarfVersion { dwarf_version }); @@ -1355,12 +1359,6 @@ pub struct EarlyDiagCtxt { dcx: DiagCtxt, } -impl Default for EarlyDiagCtxt { - fn default() -> Self { - Self::new(ErrorOutputType::default()) - } -} - impl EarlyDiagCtxt { pub fn new(output: ErrorOutputType) -> Self { let emitter = mk_emitter(output); @@ -1368,10 +1366,9 @@ impl EarlyDiagCtxt { } /// Swap out the underlying dcx once we acquire the user's preference on error emission - /// format. Any errors prior to that will cause an abort and all stashed diagnostics of the - /// previous dcx will be emitted. - pub fn abort_if_error_and_set_error_format(&mut self, output: ErrorOutputType) { - self.dcx.handle().abort_if_errors(); + /// format. If `early_err` was previously called this will panic. + pub fn set_error_format(&mut self, output: ErrorOutputType) { + assert!(self.dcx.handle().has_errors().is_none()); let emitter = mk_emitter(output); self.dcx = DiagCtxt::new(emitter); @@ -1391,7 +1388,7 @@ impl EarlyDiagCtxt { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - #[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"] + #[must_use = "raise_fatal must be called on the returned ErrorGuaranteed in order to exit with a non-zero status code"] pub fn early_err(&self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed { self.dcx.handle().err(msg) } @@ -1442,7 +1439,7 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> { config::ErrorOutputType::Json { pretty, json_rendered, color_config } => { Box::new(JsonEmitter::new( Box::new(io::BufWriter::new(io::stderr())), - Lrc::new(SourceMap::new(FilePathMapping::empty())), + Some(Arc::new(SourceMap::new(FilePathMapping::empty()))), fallback_bundle, pretty, json_rendered, | 
