/// 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, $setter_name:ident, $defaultfn:ident,
- $buildfn:ident, $prefix:expr, $outputname:expr,
- $stat:ident,
+ ($struct_name:ident, $stat:ident, $prefix:expr, $outputname:expr,
$($( #[$attr:meta] )* $opt:ident : $t:ty = (
$init:expr,
$parse:ident,
#[derive(Clone)]
pub struct $struct_name { $(pub $opt: $t),* }
- pub fn $defaultfn() -> $struct_name {
- $struct_name { $( $( #[$attr] )* $opt: $init),* }
- }
-
- pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $struct_name
- {
- let mut op = $defaultfn();
- for option in matches.opt_strs($prefix) {
- let (key, value) = match option.split_once('=') {
- None => (option, None),
- Some((k, v)) => (k.to_string(), Some(v)),
- };
- let option_to_lookup = key.replace("-", "_");
- let mut found = false;
- for &(candidate, setter, type_desc, _) in $stat {
- if option_to_lookup != candidate { continue }
- if !setter(&mut op, value) {
- match value {
- None => {
- early_error(error_format, &format!("{0} option `{1}` requires \
- {2} ({3} {1}=<value>)",
- $outputname, key,
- type_desc, $prefix))
- }
- Some(value) => {
- early_error(error_format, &format!("incorrect value `{}` for {} \
- option `{}` - {} was expected",
- value, $outputname,
- key, type_desc))
- }
- }
- }
- found = true;
- break;
- }
- if !found {
- early_error(error_format, &format!("unknown {} option: `{}`",
- $outputname, key));
- }
+ impl Default for $struct_name {
+ fn default() -> $struct_name {
+ $struct_name { $( $( #[$attr] )* $opt: $init),* }
}
- return op;
}
impl $struct_name {
+ pub fn build(
+ matches: &getopts::Matches,
+ error_format: ErrorOutputType,
+ ) -> $struct_name {
+ build_options(matches, $stat, $prefix, $outputname, error_format)
+ }
+
fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType) -> u64 {
let mut sub_hashes = BTreeMap::new();
$({
}
}
- pub type $setter_name = fn(&mut $struct_name, v: Option<&str>) -> bool;
- pub const $stat: &[(&str, $setter_name, &str, &str)] =
- &[ $( (stringify!($opt), $crate::options::parse::$opt, $crate::options::desc::$parse, $desc) ),* ];
-
- // Sometimes different options need to build a common structure.
- // That structure can kept in one of the options' fields, the others become dummy.
- macro_rules! redirect_field {
- ($cg:ident.link_arg) => { $cg.link_args };
- ($cg:ident.pre_link_arg) => { $cg.pre_link_args };
- ($cg:ident.$field:ident) => { $cg.$field };
- }
+ pub const $stat: OptionDescrs<$struct_name> =
+ &[ $( (stringify!($opt), $opt, desc::$parse, $desc) ),* ];
$(
- pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
- $crate::options::parse::$parse(&mut redirect_field!(cg.$opt), v)
+ fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
+ parse::$parse(&mut redirect_field!(cg.$opt), v)
}
)*
) }
+// Sometimes different options need to build a common structure.
+// That structure can be kept in one of the options' fields, the others become dummy.
+macro_rules! redirect_field {
+ ($cg:ident.link_arg) => {
+ $cg.link_args
+ };
+ ($cg:ident.pre_link_arg) => {
+ $cg.pre_link_args
+ };
+ ($cg:ident.$field:ident) => {
+ $cg.$field
+ };
+}
+
+type OptionSetter<O> = fn(&mut O, v: Option<&str>) -> bool;
+type OptionDescrs<O> = &'static [(&'static str, OptionSetter<O>, &'static str, &'static str)];
+
+fn build_options<O: Default>(
+ matches: &getopts::Matches,
+ descrs: OptionDescrs<O>,
+ prefix: &str,
+ outputname: &str,
+ error_format: ErrorOutputType,
+) -> O {
+ let mut op = O::default();
+ for option in matches.opt_strs(prefix) {
+ let (key, value) = match option.split_once('=') {
+ None => (option, None),
+ Some((k, v)) => (k.to_string(), Some(v)),
+ };
+
+ let option_to_lookup = key.replace("-", "_");
+ match descrs.iter().find(|(name, ..)| *name == option_to_lookup) {
+ Some((_, setter, type_desc, _)) => {
+ if !setter(&mut op, value) {
+ match value {
+ None => early_error(
+ error_format,
+ &format!(
+ "{0} option `{1}` requires {2} ({3} {1}=<value>)",
+ outputname, key, type_desc, prefix
+ ),
+ ),
+ Some(value) => early_error(
+ error_format,
+ &format!(
+ "incorrect value `{}` for {} option `{}` - {} was expected",
+ value, outputname, key, type_desc
+ ),
+ ),
+ }
+ }
+ }
+ None => early_error(error_format, &format!("unknown {} option: `{}`", outputname, key)),
+ }
+ }
+ return op;
+}
+
#[allow(non_upper_case_globals)]
mod desc {
pub const parse_no_flag: &str = "no value";
true
}
- crate fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
+ crate fn parse_linker_flavor(slot: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
match v.and_then(LinkerFlavor::from_str) {
- Some(lf) => *slote = Some(lf),
+ Some(lf) => *slot = Some(lf),
_ => return false,
}
true
}
}
-options! {CodegenOptions, CodegenSetter, basic_codegen_options,
- build_codegen_options, "C", "codegen",
- CG_OPTIONS,
+options! {
+ CodegenOptions, CG_OPTIONS, "C", "codegen",
// This list is in alphabetical order.
//
// - src/doc/rustc/src/codegen-options/index.md
}
-options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
- build_debugging_options, "Z", "debugging",
- DB_OPTIONS,
+options! {
+ DebuggingOptions, DB_OPTIONS, "Z", "debugging",
// This list is in alphabetical order.
//
"gather statistics about the input (default: no)"),
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. Optional values are: `=all` (default coverage), \
- `=except-unused-generics`, `=except-unused-functions`, or `=off` \
- (default: instrument-coverage=off)"),
+ reports (note, the compiler build config must include `profiler = true`); \
+ implies `-Z symbol-mangling-version=v0`. Optional values are:
+ `=all` (implicit value)
+ `=except-unused-generics`
+ `=except-unused-functions`
+ `=off` (default)"),
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],
"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],
+ new_llvm_pass_manager: Option<bool> = (None, parse_opt_bool, [TRACKED],
"use new LLVM pass manager (default: no)"),
nll_facts: bool = (false, parse_bool, [UNTRACKED],
"dump facts from NLL analysis into side files (default: no)"),
"whether ELF relocations can be relaxed"),
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
"choose which RELRO level to use"),
+ simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
+ "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
+ to rust's source base directory. only meant for testing purposes"),
report_delayed_bugs: bool = (false, parse_bool, [TRACKED],
"immediately print bugs registered with `delay_span_bug` (default: no)"),
sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
"select processor to schedule for (`rustc --print target-cpus` for details)"),
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
"enable ThinLTO when possible"),
+ thir_unsafeck: bool = (false, parse_bool, [TRACKED],
+ "use the work-in-progress THIR unsafety checker. NOTE: this is unsound (default: no)"),
/// We default to 1 here since we want to behave like
/// a sequential compiler for now. This'll likely be adjusted
/// in the future. Note that -Zthreads=0 is the way to get