1
Fork 0

Merge remote-tracking branch 'upstream/master' into impl-16351-nightly

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2021-04-25 00:35:25 +08:00
commit f9d390d14a
4238 changed files with 96221 additions and 81870 deletions

View file

@ -10,7 +10,6 @@ use crate::{early_error, early_warn, Session};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::impl_stable_hash_via_hash;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_target::abi::{Align, TargetDataLayout};
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple};
@ -19,7 +18,7 @@ use rustc_serialize::json;
use crate::parse::CrateConfig;
use rustc_feature::UnstableFeatures;
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST};
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
use rustc_span::source_map::{FileName, FilePathMapping};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::SourceFileHashAlgorithm;
@ -36,66 +35,6 @@ use std::iter::{self, FromIterator};
use std::path::{Path, PathBuf};
use std::str::{self, FromStr};
bitflags! {
#[derive(Default, Encodable, Decodable)]
pub struct SanitizerSet: u8 {
const ADDRESS = 1 << 0;
const LEAK = 1 << 1;
const MEMORY = 1 << 2;
const THREAD = 1 << 3;
const HWADDRESS = 1 << 4;
}
}
/// Formats a sanitizer set as a comma separated list of sanitizers' names.
impl fmt::Display for SanitizerSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut first = true;
for s in *self {
let name = match s {
SanitizerSet::ADDRESS => "address",
SanitizerSet::LEAK => "leak",
SanitizerSet::MEMORY => "memory",
SanitizerSet::THREAD => "thread",
SanitizerSet::HWADDRESS => "hwaddress",
_ => panic!("unrecognized sanitizer {:?}", s),
};
if !first {
f.write_str(",")?;
}
f.write_str(name)?;
first = false;
}
Ok(())
}
}
impl IntoIterator for SanitizerSet {
type Item = SanitizerSet;
type IntoIter = std::vec::IntoIter<SanitizerSet>;
fn into_iter(self) -> Self::IntoIter {
[
SanitizerSet::ADDRESS,
SanitizerSet::LEAK,
SanitizerSet::MEMORY,
SanitizerSet::THREAD,
SanitizerSet::HWADDRESS,
]
.iter()
.copied()
.filter(|&s| self.contains(s))
.collect::<Vec<_>>()
.into_iter()
}
}
impl<CTX> HashStable<CTX> for SanitizerSet {
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
self.bits().hash_stable(ctx, hasher);
}
}
/// The different settings that the `-Z strip` flag can have.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum Strip {
@ -136,19 +75,21 @@ impl_stable_hash_via_hash!(OptLevel);
/// This is what the `LtoCli` values get mapped to after resolving defaults and
/// and taking other command line options into account.
///
/// Note that linker plugin-based LTO is a different mechanism entirely.
#[derive(Clone, PartialEq)]
pub enum Lto {
/// Don't do any LTO whatsoever
/// Don't do any LTO whatsoever.
No,
/// Do a full crate graph LTO with ThinLTO
/// Do a full-crate-graph (inter-crate) LTO with ThinLTO.
Thin,
/// Do a local graph LTO with ThinLTO (only relevant for multiple codegen
/// units).
/// Do a local ThinLTO (intra-crate, over the CodeGen Units of the local crate only). This is
/// only relevant if multiple CGUs are used.
ThinLocal,
/// Do a full crate graph LTO with "fat" LTO
/// Do a full-crate-graph (inter-crate) LTO with "fat" LTO.
Fat,
}
@ -184,6 +125,37 @@ pub enum MirSpanview {
Block,
}
/// The different settings that the `-Z instrument-coverage` flag can have.
///
/// Coverage instrumentation now supports combining `-Z instrument-coverage`
/// 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
/// lowering the optimization level, including or excluding `-C link-dead-code`,
/// or using `-Z instrument-coverage=except-unused-functions` or `-Z
/// instrument-coverage=except-unused-generics`.
///
/// Note that `ExceptUnusedFunctions` means: When `mapgen.rs` generates the
/// coverage map, it will not attempt to generate synthetic functions for unused
/// (and not code-generated) functions (whether they are generic or not). As a
/// result, non-codegenned functions will not be included in the coverage map,
/// and will not appear, as covered or uncovered, in coverage reports.
///
/// `ExceptUnusedGenerics` will add synthetic functions to the coverage map,
/// unless the function has type parameters.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum InstrumentCoverage {
/// Default `-Z instrument-coverage` or `-Z instrument-coverage=statement`
All,
/// `-Z instrument-coverage=except-unused-generics`
ExceptUnusedGenerics,
/// `-Z instrument-coverage=except-unused-functions`
ExceptUnusedFunctions,
/// `-Z instrument-coverage=off` (or `no`, etc.)
Off,
}
#[derive(Clone, PartialEq, Hash)]
pub enum LinkerPluginLto {
LinkerPlugin(PathBuf),
@ -474,6 +446,7 @@ impl<'a> From<&'a ExternDepSpec> for rustc_lint_defs::ExternDepSpec {
}
impl Externs {
/// Used for testing.
pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs {
Externs(data)
}
@ -485,6 +458,10 @@ impl Externs {
pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> {
self.0.iter()
}
pub fn len(&self) -> usize {
self.0.len()
}
}
impl ExternEntry {
@ -573,13 +550,6 @@ impl Input {
}
}
pub fn get_input(&mut self) -> Option<&mut String> {
match *self {
Input::File(_) => None,
Input::Str { ref mut input, .. } => Some(input),
}
}
pub fn source_name(&self) -> FileName {
match *self {
Input::File(ref ifile) => ifile.clone().into(),
@ -734,6 +704,7 @@ impl Default for Options {
remap_path_prefix: Vec::new(),
edition: DEFAULT_EDITION,
json_artifact_notifications: false,
json_unused_externs: false,
pretty: None,
}
}
@ -747,12 +718,6 @@ impl Options {
|| self.debugging_opts.query_dep_graph
}
#[inline(always)]
pub fn enable_dep_node_debug_strs(&self) -> bool {
cfg!(debug_assertions)
&& (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info)
}
pub fn file_path_mapping(&self) -> FilePathMapping {
FilePathMapping::new(self.remap_path_prefix.clone())
}
@ -832,7 +797,7 @@ pub const fn default_lib_output() -> CrateType {
CrateType::Rlib
}
pub fn default_configuration(sess: &Session) -> CrateConfig {
fn default_configuration(sess: &Session) -> CrateConfig {
let end = &sess.target.endian;
let arch = &sess.target.arch;
let wordsz = sess.target.pointer_width.to_string();
@ -927,7 +892,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo
user_cfg
}
pub fn build_target_config(
pub(super) fn build_target_config(
opts: &Options,
target_override: Option<Target>,
sysroot: &PathBuf,
@ -939,7 +904,7 @@ pub fn build_target_config(
opts.error_format,
&format!(
"Error loading target specification: {}. \
Use `--print target-list` for a list of built-in targets",
Run `rustc --print target-list` for a list of built-in targets",
e
),
)
@ -1034,9 +999,6 @@ mod opt {
pub fn flag_s(a: S, b: S, c: S) -> R {
stable(longer(a, b), move |opts| opts.optflag(a, b, c))
}
pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R {
stable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d))
}
pub fn flagmulti_s(a: S, b: S, c: S) -> R {
stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
}
@ -1047,15 +1009,6 @@ mod opt {
pub fn multi(a: S, b: S, c: S, d: S) -> R {
unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
}
pub fn flag(a: S, b: S, c: S) -> R {
unstable(longer(a, b), move |opts| opts.optflag(a, b, c))
}
pub fn flagopt(a: S, b: S, c: S, d: S) -> R {
unstable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d))
}
pub fn flagmulti(a: S, b: S, c: S) -> R {
unstable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
}
}
/// Returns the "short" subset of the rustc command line options,
@ -1255,15 +1208,23 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
}
}
/// Possible json config files
pub struct JsonConfig {
pub json_rendered: HumanReadableErrorType,
pub json_artifact_notifications: bool,
pub json_unused_externs: bool,
}
/// 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.
pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) {
pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType =
HumanReadableErrorType::Default;
let mut json_color = ColorConfig::Never;
let mut json_artifact_notifications = false;
let mut json_unused_externs = false;
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
@ -1280,6 +1241,7 @@ pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool)
"diagnostic-short" => json_rendered = HumanReadableErrorType::Short,
"diagnostic-rendered-ansi" => json_color = ColorConfig::Always,
"artifacts" => json_artifact_notifications = true,
"unused-externs" => json_unused_externs = true,
s => early_error(
ErrorOutputType::default(),
&format!("unknown `--json` option `{}`", s),
@ -1287,7 +1249,12 @@ pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool)
}
}
}
(json_rendered(json_color), json_artifact_notifications)
JsonConfig {
json_rendered: json_rendered(json_color),
json_artifact_notifications,
json_unused_externs,
}
}
/// Parses the `--error-format` flag.
@ -1360,13 +1327,16 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
};
if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) {
early_error(
ErrorOutputType::default(),
&format!(
"edition {} is unstable and only available with -Z unstable-options.",
edition,
),
)
let is_nightly = nightly_options::match_is_nightly_build(matches);
let msg = if !is_nightly {
format!(
"the crate requires edition {}, but the latest edition supported by this Rust version is {}",
edition, LATEST_STABLE_EDITION
)
} else {
format!("edition {} is unstable and only available with -Z unstable-options", edition)
};
early_error(ErrorOutputType::default(), &msg)
}
edition
@ -1865,7 +1835,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let edition = parse_crate_edition(matches);
let (json_rendered, json_artifact_notifications) = parse_json(matches);
let JsonConfig { json_rendered, json_artifact_notifications, json_unused_externs } =
parse_json(matches);
let error_format = parse_error_format(matches, color, json_rendered);
@ -1878,6 +1849,14 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let mut debugging_opts = build_debugging_options(matches, error_format);
check_debug_option_stability(&debugging_opts, error_format, json_rendered);
if !debugging_opts.unstable_options && json_unused_externs {
early_error(
error_format,
"the `-Z unstable-options` flag must also be passed to enable \
the flag `--json=unused-externs`",
);
}
let output_types = parse_output_types(&debugging_opts, matches, error_format);
let mut cg = build_codegen_options(matches, error_format);
@ -1916,7 +1895,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
);
}
if debugging_opts.instrument_coverage {
if debugging_opts.instrument_coverage.is_some()
&& debugging_opts.instrument_coverage != Some(InstrumentCoverage::Off)
{
if cg.profile_generate.enabled() || cg.profile_use.is_some() {
early_error(
error_format,
@ -1942,23 +1923,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
}
Some(SymbolManglingVersion::V0) => {}
}
if debugging_opts.mir_opt_level > 1 {
// Functions inlined during MIR transform can, at best, make it impossible to
// effectively cover inlined functions, and, at worst, break coverage map generation
// during LLVM codegen. For example, function counter IDs are only unique within a
// function. Inlining after these counters are injected can produce duplicate counters,
// resulting in an invalid coverage map (and ICE); so this option combination is not
// allowed.
early_warn(
error_format,
&format!(
"`-Z mir-opt-level={}` (or any level > 1) enables function inlining, which \
is incompatible with `-Z instrument-coverage`. Inlining will be disabled.",
debugging_opts.mir_opt_level,
),
);
}
}
if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
@ -2053,6 +2017,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
remap_path_prefix,
edition,
json_artifact_notifications,
json_unused_externs,
pretty,
}
}
@ -2077,6 +2042,7 @@ fn parse_pretty(
("hir,identified", true) => Hir(PpHirMode::Identified),
("hir,typed", true) => Hir(PpHirMode::Typed),
("hir-tree", true) => HirTree,
("thir-tree", true) => ThirTree,
("mir", true) => Mir,
("mir-cfg", true) => MirCFG,
_ => {
@ -2268,6 +2234,8 @@ pub enum PpMode {
Hir(PpHirMode),
/// `-Zunpretty=hir-tree`
HirTree,
/// `-Zunpretty=thir-tree`
ThirTree,
/// `-Zunpretty=mir`
Mir,
/// `-Zunpretty=mir-cfg`
@ -2285,6 +2253,7 @@ impl PpMode {
| AstTree(PpAstTreeMode::Expanded)
| Hir(_)
| HirTree
| ThirTree
| Mir
| MirCFG => true,
}
@ -2292,7 +2261,7 @@ impl PpMode {
pub fn needs_analysis(&self) -> bool {
use PpMode::*;
matches!(*self, Mir | MirCFG)
matches!(*self, Mir | MirCFG | ThirTree)
}
}
@ -2316,8 +2285,8 @@ impl PpMode {
/// how the hash should be calculated when adding a new command-line argument.
crate mod dep_tracking {
use super::{
CFGuard, CrateType, DebugInfo, ErrorOutputType, LinkerPluginLto, LtoCli, OptLevel,
OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm, SwitchWithOptPath,
CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto,
LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath,
SymbolManglingVersion, TrimmedDefPaths,
};
use crate::lint;
@ -2326,7 +2295,7 @@ crate mod dep_tracking {
use rustc_feature::UnstableFeatures;
use rustc_span::edition::Edition;
use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel};
use rustc_target::spec::{RelroLevel, SplitDebuginfo, TargetTriple, TlsModel};
use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, TargetTriple, TlsModel};
use std::collections::hash_map::DefaultHasher;
use std::collections::BTreeMap;
use std::hash::Hash;
@ -2370,6 +2339,7 @@ crate mod dep_tracking {
impl_dep_tracking_hash_via_hash!(PathBuf);
impl_dep_tracking_hash_via_hash!(lint::Level);
impl_dep_tracking_hash_via_hash!(Option<bool>);
impl_dep_tracking_hash_via_hash!(Option<u32>);
impl_dep_tracking_hash_via_hash!(Option<usize>);
impl_dep_tracking_hash_via_hash!(Option<NonZeroUsize>);
impl_dep_tracking_hash_via_hash!(Option<String>);
@ -2382,6 +2352,7 @@ crate mod dep_tracking {
impl_dep_tracking_hash_via_hash!(Option<WasiExecModel>);
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
impl_dep_tracking_hash_via_hash!(Option<InstrumentCoverage>);
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
impl_dep_tracking_hash_via_hash!(CrateType);
@ -2443,7 +2414,7 @@ crate mod dep_tracking {
}
// This is a stable hash because BTreeMap is a sorted container
pub fn stable_hash(
crate fn stable_hash(
sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
hasher: &mut DefaultHasher,
error_format: ErrorOutputType,

View file

@ -1,9 +1,8 @@
#![feature(crate_visibility_modifier)]
#![feature(once_cell)]
#![feature(or_patterns)]
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate rustc_macros;

View file

@ -5,7 +5,7 @@ use crate::lint;
use crate::search_paths::SearchPath;
use crate::utils::NativeLibKind;
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel};
use rustc_feature::UnstableFeatures;
@ -147,6 +147,9 @@ top_level_options!(
// by the compiler.
json_artifact_notifications: bool [TRACKED],
// `true` if we're emitting a JSON blob containing the unused externs
json_unused_externs: bool [UNTRACKED],
pretty: Option<PpMode> [UNTRACKED],
}
);
@ -248,9 +251,9 @@ macro_rules! options {
pub const parse_list: &str = "a space-separated list of strings";
pub const parse_opt_list: &str = parse_list;
pub const parse_opt_comma_list: &str = "a comma-separated list of strings";
pub const parse_uint: &str = "a number";
pub const parse_opt_uint: &str = parse_uint;
pub const parse_threads: &str = parse_uint;
pub const parse_number: &str = "a number";
pub const parse_opt_number: &str = parse_number;
pub const parse_threads: &str = parse_number;
pub const parse_passes: &str = "a space-separated list of passes, or `all`";
pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
@ -262,6 +265,7 @@ macro_rules! options {
pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of();
pub const parse_optimization_fuel: &str = "crate=integer";
pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
pub const parse_instrument_coverage: &str = "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`";
pub const parse_unpretty: &str = "`string` or `string=string`";
pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0";
pub const parse_lto: &str =
@ -413,16 +417,16 @@ macro_rules! options {
}
}
/// Use this for any uint option that has a static default.
fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool {
/// Use this for any numeric option that has a static default.
fn parse_number<T: Copy + FromStr>(slot: &mut T, v: Option<&str>) -> bool {
match v.and_then(|s| s.parse().ok()) {
Some(i) => { *slot = i; true },
None => false
}
}
/// Use this for any uint option that lacks a static default.
fn parse_opt_uint(slot: &mut Option<usize>, v: Option<&str>) -> bool {
/// Use this for any numeric option that lacks a static default.
fn parse_opt_number<T: Copy + FromStr>(slot: &mut Option<T>, v: Option<&str>) -> bool {
match v {
Some(s) => { *slot = s.parse().ok(); slot.is_some() }
None => false
@ -592,6 +596,41 @@ macro_rules! options {
true
}
fn parse_instrument_coverage(slot: &mut Option<InstrumentCoverage>, v: Option<&str>) -> bool {
if v.is_some() {
let mut bool_arg = None;
if parse_opt_bool(&mut bool_arg, v) {
*slot = if bool_arg.unwrap() {
Some(InstrumentCoverage::All)
} else {
None
};
return true
}
}
let v = match v {
None => {
*slot = Some(InstrumentCoverage::All);
return true;
}
Some(v) => v,
};
*slot = Some(match v {
"all" => InstrumentCoverage::All,
"except-unused-generics" | "except_unused_generics" => {
InstrumentCoverage::ExceptUnusedGenerics
}
"except-unused-functions" | "except_unused_functions" => {
InstrumentCoverage::ExceptUnusedFunctions
}
"off" | "no" | "n" | "false" | "0" => InstrumentCoverage::Off,
_ => return false,
});
true
}
fn parse_treat_err_as_bug(slot: &mut Option<NonZeroUsize>, v: Option<&str>) -> bool {
match v {
Some(s) => { *slot = s.parse().ok(); slot.is_some() }
@ -748,13 +787,13 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
"this option is deprecated and does nothing"),
code_model: Option<CodeModel> = (None, parse_code_model, [TRACKED],
"choose the code model to use (`rustc --print code-models` for details)"),
codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
codegen_units: Option<usize> = (None, parse_opt_number, [UNTRACKED],
"divide crate into N units to optimize in parallel"),
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
"use Windows Control Flow Guard (default: no)"),
debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
"explicitly enable the `cfg(debug_assertions)` directive"),
debuginfo: usize = (0, parse_uint, [TRACKED],
debuginfo: usize = (0, parse_number, [TRACKED],
"debug info emission level (0 = no debug info, 1 = line tables only, \
2 = full debug info with variable and type information; default: 0)"),
default_linker_libraries: bool = (false, parse_bool, [UNTRACKED],
@ -769,13 +808,13 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
"force use of unwind tables"),
incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
"enable incremental compilation"),
inline_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
inline_threshold: Option<u32> = (None, parse_opt_number, [TRACKED],
"set the threshold for inlining a function"),
link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED],
"a single extra argument to append to the linker invocation (can be used several times)"),
link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
"extra arguments to append to the linker invocation (space separated)"),
link_dead_code: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
link_dead_code: Option<bool> = (None, parse_opt_bool, [TRACKED],
"keep dead code at link time (useful for code coverage) (default: no)"),
link_self_contained: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
"control whether to link Rust provided C objects/libraries or rely
@ -870,8 +909,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
(default: no)"),
borrowck: String = ("migrate".to_string(), parse_string, [UNTRACKED],
"select which borrowck is used (`mir` or `migrate`) (default: `migrate`)"),
borrowck_stats: bool = (false, parse_bool, [UNTRACKED],
"gather borrowck statistics (default: no)"),
cgu_partitioning_strategy: Option<String> = (None, parse_opt_string, [TRACKED],
"the codegen unit partitioning strategy to use"),
chalk: bool = (false, parse_bool, [TRACKED],
@ -959,24 +996,22 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"verify incr. comp. hashes of green query instances (default: no)"),
inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
"enable MIR inlining (default: no)"),
inline_mir_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
inline_mir_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
"a default MIR inlining threshold (default: 50)"),
inline_mir_hint_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
inline_mir_hint_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
"inlining threshold for functions with inline hint (default: 100)"),
inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
"control whether `#[inline]` functions are in all CGUs"),
input_stats: bool = (false, parse_bool, [UNTRACKED],
"gather statistics about the input (default: no)"),
insert_sideeffect: bool = (false, parse_bool, [TRACKED],
"fix undefined behavior when a thread doesn't eventually make progress \
(such as entering an empty infinite loop) by inserting llvm.sideeffect \
(default: no)"),
instrument_coverage: bool = (false, parse_bool, [TRACKED],
instrument_coverage: Option<InstrumentCoverage> = (None, parse_instrument_coverage, [TRACKED],
"instrument the generated code to support LLVM source-based code coverage \
reports (note, the compiler build config must include `profiler = true`, \
and is mutually exclusive with `-C profile-generate`/`-C profile-use`); \
implies `-Z symbol-mangling-version=v0`; disables/overrides some Rust \
optimizations (default: no)"),
optimizations. Optional values are: `=all` (default coverage), \
`=except-unused-generics`, `=except-unused-functions`, or `=off` \
(default: instrument-coverage=off)"),
instrument_mcount: bool = (false, parse_bool, [TRACKED],
"insert function instrument code for mcount-based tracing (default: no)"),
keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],
@ -999,10 +1034,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
mir_emit_retag: bool = (false, parse_bool, [TRACKED],
"emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
(default: no)"),
mir_opt_level: usize = (1, parse_uint, [TRACKED],
"MIR optimization level (0-3; default: 1)"),
mutable_noalias: bool = (false, parse_bool, [TRACKED],
"emit noalias metadata for mutable references (default: no)"),
mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
"MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
"emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"),
new_llvm_pass_manager: bool = (false, parse_bool, [TRACKED],
"use new LLVM pass manager (default: no)"),
nll_facts: bool = (false, parse_bool, [UNTRACKED],
@ -1120,7 +1155,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
teach: bool = (false, parse_bool, [TRACKED],
"show extended diagnostic help (default: no)"),
terminal_width: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
terminal_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
"set the current terminal width"),
tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
"select processor to schedule for (`rustc --print target-cpus` for details)"),

View file

@ -13,7 +13,6 @@ use rustc_span::hygiene::ExpnId;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use rustc_span::{MultiSpan, Span, Symbol};
use std::path::PathBuf;
use std::str;
/// The set of keys (and, optionally, values) that define the compilation
@ -122,8 +121,6 @@ pub struct ParseSess {
pub missing_fragment_specifiers: Lock<FxHashMap<Span, NodeId>>,
/// Places where raw identifiers were used. This is used for feature-gating raw identifiers.
pub raw_identifier_spans: Lock<Vec<Span>>,
/// Used to determine and report recursive module inclusions.
pub included_mod_stack: Lock<Vec<PathBuf>>,
source_map: Lrc<SourceMap>,
pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
/// Contains the spans of block expressions that could have been incomplete based on the
@ -143,6 +140,7 @@ pub struct ParseSess {
}
impl ParseSess {
/// Used for testing.
pub fn new(file_path_mapping: FilePathMapping) -> Self {
let sm = Lrc::new(SourceMap::new(file_path_mapping));
let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, None, Some(sm.clone()));
@ -157,7 +155,6 @@ impl ParseSess {
edition: ExpnId::root().expn_data().edition,
missing_fragment_specifiers: Default::default(),
raw_identifier_spans: Lock::new(Vec::new()),
included_mod_stack: Lock::new(vec![]),
source_map,
buffered_lints: Lock::new(vec![]),
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),

View file

@ -1,14 +1,13 @@
use crate::cgu_reuse_tracker::CguReuseTracker;
use crate::code_stats::CodeStats;
pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
use crate::config::{self, CrateType, OutputType, PrintRequest, SanitizerSet, SwitchWithOptPath};
use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath};
use crate::filesearch;
use crate::lint::{self, LintId};
use crate::parse::ParseSess;
use crate::search_paths::{PathKind, SearchPath};
pub use rustc_ast::attr::MarkedAttrs;
pub use rustc_ast::crate_disambiguator::CrateDisambiguator;
pub use rustc_ast::Attribute;
use rustc_data_structures::flock;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@ -21,14 +20,15 @@ use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter;
use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
use rustc_errors::json::JsonEmitter;
use rustc_errors::registry::Registry;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
use rustc_lint_defs::FutureBreakage;
pub use rustc_span::crate_disambiguator::CrateDisambiguator;
use rustc_span::edition::Edition;
use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
use rustc_target::asm::InlineAsmArch;
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TlsModel};
use rustc_target::spec::{SanitizerSet, SplitDebuginfo, Target, TargetTriple, TlsModel};
use std::cell::{self, RefCell};
use std::env;
@ -241,8 +241,7 @@ pub struct PerfStats {
enum DiagnosticBuilderMethod {
Note,
SpanNote,
SpanSuggestion(String), // suggestion
// Add more variants as needed to support one-time diagnostics.
// Add more variants as needed to support one-time diagnostics.
}
/// Trait implemented by error types. This should not be implemented manually. Instead, use
@ -551,15 +550,6 @@ impl Session {
let span = span_maybe.expect("`span_note` needs a span");
diag_builder.span_note(span, message);
}
DiagnosticBuilderMethod::SpanSuggestion(suggestion) => {
let span = span_maybe.expect("`span_suggestion_*` needs a span");
diag_builder.span_suggestion(
span,
message,
suggestion,
Applicability::Unspecified,
);
}
}
}
}
@ -589,23 +579,6 @@ impl Session {
self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, msg_id, message, None);
}
pub fn diag_span_suggestion_once<'a, 'b>(
&'a self,
diag_builder: &'b mut DiagnosticBuilder<'a>,
msg_id: DiagnosticMessageId,
span: Span,
message: &str,
suggestion: String,
) {
self.diag_once(
diag_builder,
DiagnosticBuilderMethod::SpanSuggestion(suggestion),
msg_id,
message,
Some(span),
);
}
#[inline]
pub fn source_map(&self) -> &SourceMap {
self.parse_sess.source_map()
@ -631,15 +604,18 @@ impl Session {
pub fn verify_llvm_ir(&self) -> bool {
self.opts.debugging_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some()
}
pub fn borrowck_stats(&self) -> bool {
self.opts.debugging_opts.borrowck_stats
}
pub fn print_llvm_passes(&self) -> bool {
self.opts.debugging_opts.print_llvm_passes
}
pub fn binary_dep_depinfo(&self) -> bool {
self.opts.debugging_opts.binary_dep_depinfo
}
pub fn mir_opt_level(&self) -> usize {
self.opts
.debugging_opts
.mir_opt_level
.unwrap_or_else(|| if self.opts.optimize != config::OptLevel::No { 2 } else { 1 })
}
/// Gets the features enabled for the current compilation session.
/// DO NOT USE THIS METHOD if there is a TyCtxt available, as it circumvents
@ -831,8 +807,11 @@ impl Session {
// This is used to control the emission of the `uwtable` attribute on
// LLVM functions.
//
// At the very least, unwind tables are needed when compiling with
// `-C panic=unwind`.
// Unwind tables are needed when compiling with `-C panic=unwind`, but
// LLVM won't omit unwind tables unless the function is also marked as
// `nounwind`, so users are allowed to disable `uwtable` emission.
// Historically rustc always emits `uwtable` attributes by default, so
// even they can be disabled, they're still emitted by default.
//
// On some targets (including windows), however, exceptions include
// other events such as illegal instructions, segfaults, etc. This means
@ -845,13 +824,10 @@ impl Session {
// If a target requires unwind tables, then they must be emitted.
// Otherwise, we can defer to the `-C force-unwind-tables=<yes/no>`
// value, if it is provided, or disable them, if not.
if self.panic_strategy() == PanicStrategy::Unwind {
true
} else if self.target.requires_uwtable {
true
} else {
self.opts.cg.force_unwind_tables.unwrap_or(false)
}
self.target.requires_uwtable
|| self.opts.cg.force_unwind_tables.unwrap_or(
self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable,
)
}
/// Returns the symbol name for the registrar function,
@ -884,22 +860,6 @@ impl Session {
)
}
pub fn set_incr_session_load_dep_graph(&self, load: bool) {
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
if let IncrCompSession::Active { ref mut load_dep_graph, .. } = *incr_comp_session {
*load_dep_graph = load;
}
}
pub fn incr_session_load_dep_graph(&self) -> bool {
let incr_comp_session = self.incr_comp_session.borrow();
match *incr_comp_session {
IncrCompSession::Active { load_dep_graph, .. } => load_dep_graph,
_ => false,
}
}
pub fn init_incr_comp_session(
&self,
session_dir: PathBuf,
@ -1137,6 +1097,21 @@ impl Session {
self.opts.cg.link_dead_code.unwrap_or(false)
}
pub fn instrument_coverage(&self) -> bool {
self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
!= config::InstrumentCoverage::Off
}
pub fn instrument_coverage_except_unused_generics(&self) -> bool {
self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
== config::InstrumentCoverage::ExceptUnusedGenerics
}
pub fn instrument_coverage_except_unused_functions(&self) -> bool {
self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
== config::InstrumentCoverage::ExceptUnusedFunctions
}
pub fn mark_attr_known(&self, attr: &Attribute) {
self.known_attrs.lock().mark(attr)
}
@ -1509,13 +1484,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
// Unwind tables cannot be disabled if the target requires them.
if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables {
if sess.panic_strategy() == PanicStrategy::Unwind && !include_uwtables {
sess.err(
"panic=unwind requires unwind tables, they cannot be disabled \
with `-C force-unwind-tables=no`.",
);
}
if sess.target.requires_uwtable && !include_uwtables {
sess.err(
"target requires unwind tables, they cannot be disabled with \
@ -1543,59 +1511,22 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
);
}
const ASAN_SUPPORTED_TARGETS: &[&str] = &[
"aarch64-apple-darwin",
"aarch64-fuchsia",
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-fuchsia",
"x86_64-unknown-freebsd",
"x86_64-unknown-linux-gnu",
];
const LSAN_SUPPORTED_TARGETS: &[&str] = &[
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-unknown-linux-gnu",
];
const MSAN_SUPPORTED_TARGETS: &[&str] =
&["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
const TSAN_SUPPORTED_TARGETS: &[&str] = &[
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-unknown-freebsd",
"x86_64-unknown-linux-gnu",
];
const HWASAN_SUPPORTED_TARGETS: &[&str] =
&["aarch64-linux-android", "aarch64-unknown-linux-gnu"];
// Sanitizers can only be used on some tested platforms.
for s in sess.opts.debugging_opts.sanitizer {
let supported_targets = match s {
SanitizerSet::ADDRESS => ASAN_SUPPORTED_TARGETS,
SanitizerSet::LEAK => LSAN_SUPPORTED_TARGETS,
SanitizerSet::MEMORY => MSAN_SUPPORTED_TARGETS,
SanitizerSet::THREAD => TSAN_SUPPORTED_TARGETS,
SanitizerSet::HWADDRESS => HWASAN_SUPPORTED_TARGETS,
_ => panic!("unrecognized sanitizer {}", s),
};
if !supported_targets.contains(&&*sess.opts.target_triple.triple()) {
sess.err(&format!(
"`-Zsanitizer={}` only works with targets: {}",
s,
supported_targets.join(", ")
));
}
let conflicting = sess.opts.debugging_opts.sanitizer - s;
if !conflicting.is_empty() {
sess.err(&format!(
"`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`",
s, conflicting,
));
// Don't report additional errors.
break;
}
// Sanitizers can only be used on platforms that we know have working sanitizer codegen.
let supported_sanitizers = sess.target.options.supported_sanitizers;
let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
match unsupported_sanitizers.into_iter().count() {
0 => {}
1 => sess
.err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)),
_ => sess.err(&format!(
"{} sanitizers are not supported for this target",
unsupported_sanitizers
)),
}
// Cannot mix and match sanitizers.
let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter();
if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
sess.err(&format!("`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", first, second));
}
}

View file

@ -1,7 +1,13 @@
use crate::parse::ParseSess;
use crate::session::Session;
use rustc_ast::token::{self, DelimToken, Nonterminal, Token};
use rustc_ast::tokenstream::CanSynthesizeMissingTokens;
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
use rustc_data_structures::profiling::VerboseTimingGuard;
use std::path::{Path, PathBuf};
pub type NtToTokenstream = fn(&Nonterminal, &ParseSess, CanSynthesizeMissingTokens) -> TokenStream;
impl Session {
pub fn timer<'a>(&'a self, what: &'static str) -> VerboseTimingGuard<'a> {
self.prof.verbose_generic_activity(what)
@ -53,3 +59,52 @@ impl CanonicalizedPath {
&self.original
}
}
// FIXME: Find a better spot for this - it needs to be accessible from `rustc_ast_lowering`,
// and needs to access `ParseSess
pub struct FlattenNonterminals<'a> {
pub parse_sess: &'a ParseSess,
pub synthesize_tokens: CanSynthesizeMissingTokens,
pub nt_to_tokenstream: NtToTokenstream,
}
impl<'a> FlattenNonterminals<'a> {
pub fn process_token_stream(&mut self, tokens: TokenStream) -> TokenStream {
fn can_skip(stream: &TokenStream) -> bool {
stream.trees().all(|tree| match tree {
TokenTree::Token(token) => !matches!(token.kind, token::Interpolated(_)),
TokenTree::Delimited(_, _, inner) => can_skip(&inner),
})
}
if can_skip(&tokens) {
return tokens;
}
tokens.into_trees().flat_map(|tree| self.process_token_tree(tree).into_trees()).collect()
}
pub fn process_token_tree(&mut self, tree: TokenTree) -> TokenStream {
match tree {
TokenTree::Token(token) => self.process_token(token),
TokenTree::Delimited(span, delim, tts) => {
TokenTree::Delimited(span, delim, self.process_token_stream(tts)).into()
}
}
}
pub fn process_token(&mut self, token: Token) -> TokenStream {
match token.kind {
token::Interpolated(nt) => {
let tts = (self.nt_to_tokenstream)(&nt, self.parse_sess, self.synthesize_tokens);
TokenTree::Delimited(
DelimSpan::from_single(token.span),
DelimToken::NoDelim,
self.process_token_stream(tts),
)
.into()
}
_ => TokenTree::Token(token).into(),
}
}
}