From eb963ffe451bfbc001ea86712a94619903bfbaf8 Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Fri, 11 Dec 2020 18:28:37 -0800 Subject: [PATCH 1/3] Fixes reported bugs in Rust Coverage Fixes: #79569 Fixes: #79566 Fixes: #79565 For the first issue (#79569), I got hit a `debug_assert!()` before encountering the reported error message (because I have `debug = true` enabled in my config.toml). The assertion showed me that some `SwitchInt`s can have more than one target pointing to the same `BasicBlock`. I had thought that was invalid, but since it seems to be possible, I'm allowing this now. I added a new test for this. ---- In the last two cases above, both tests (intentionally) fail to compile, but the `InstrumentCoverage` pass is invoked anyway. The MIR starts with an `Unreachable` `BasicBlock`, which I hadn't encountered before. (I had assumed the `InstrumentCoverage` pass would only be invoked with MIRs from successful compilations.) I don't have test infrastructure set up to test coverage on files that fail to compile, so I didn't add a new test. --- .../rustc_mir/src/transform/coverage/graph.rs | 28 +- .../rustc_mir/src/transform/coverage/mod.rs | 8 + ...cted_export_coverage.match_or_pattern.json | 59 ++++ ...xpected_show_coverage.match_or_pattern.txt | 50 ++++ .../expected_show_coverage_counters.async.txt | 12 +- ...how_coverage_counters.match_or_pattern.txt | 98 +++++++ ...ern.main.-------.InstrumentCoverage.0.html | 271 ++++++++++++++++++ .../coverage/match_or_pattern.rs | 45 +++ 8 files changed, 553 insertions(+), 18 deletions(-) create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_export_coverage.match_or_pattern.json create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.match_or_pattern.txt create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.match_or_pattern.txt create mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html create mode 100644 src/test/run-make-fulldeps/coverage/match_or_pattern.rs diff --git a/compiler/rustc_mir/src/transform/coverage/graph.rs b/compiler/rustc_mir/src/transform/coverage/graph.rs index 2408a999c05a3..b1a1bb957e79d 100644 --- a/compiler/rustc_mir/src/transform/coverage/graph.rs +++ b/compiler/rustc_mir/src/transform/coverage/graph.rs @@ -32,24 +32,28 @@ impl CoverageGraph { // Pre-transform MIR `BasicBlock` successors and predecessors into the BasicCoverageBlock // equivalents. Note that since the BasicCoverageBlock graph has been fully simplified, the - // each predecessor of a BCB leader_bb should be in a unique BCB, and each successor of a - // BCB last_bb should be in its own unique BCB. Therefore, collecting the BCBs using - // `bb_to_bcb` should work without requiring a deduplication step. + // each predecessor of a BCB leader_bb should be in a unique BCB. It is possible for a + // `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so + // de-duplication is required. This is done without reordering the successors. + let bcbs_len = bcbs.len(); + let mut seen = IndexVec::from_elem_n(false, bcbs_len); let successors = IndexVec::from_fn_n( |bcb| { + for b in seen.iter_mut() { + *b = false; + } let bcb_data = &bcbs[bcb]; - let bcb_successors = + let mut bcb_successors = Vec::new(); + for successor in bcb_filtered_successors(&mir_body, &bcb_data.terminator(mir_body).kind) .filter_map(|&successor_bb| bb_to_bcb[successor_bb]) - .collect::>(); - debug_assert!({ - let mut sorted = bcb_successors.clone(); - sorted.sort_unstable(); - let initial_len = sorted.len(); - sorted.dedup(); - sorted.len() == initial_len - }); + { + if !seen[successor] { + seen[successor] = true; + bcb_successors.push(successor); + } + } bcb_successors }, bcbs.len(), diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs index f69748db238c0..53f7c28ee35be 100644 --- a/compiler/rustc_mir/src/transform/coverage/mod.rs +++ b/compiler/rustc_mir/src/transform/coverage/mod.rs @@ -78,6 +78,14 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { return; } + match mir_body.basic_blocks()[mir::START_BLOCK].terminator().kind { + TerminatorKind::Unreachable => { + trace!("InstrumentCoverage skipped for unreachable `START_BLOCK`"); + return; + } + _ => {} + } + trace!("InstrumentCoverage starting for {:?}", mir_source.def_id()); Instrumentor::new(&self.name(), tcx, mir_body).inject_counters(); trace!("InstrumentCoverage starting for {:?}", mir_source.def_id()); diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_export_coverage.match_or_pattern.json b/src/test/run-make-fulldeps/coverage-reports/expected_export_coverage.match_or_pattern.json new file mode 100644 index 0000000000000..8559fc84aa937 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_export_coverage.match_or_pattern.json @@ -0,0 +1,59 @@ +{ + "data": [ + { + "files": [ + { + "filename": "../coverage/match_or_pattern.rs", + "summary": { + "functions": { + "count": 1, + "covered": 1, + "percent": 100 + }, + "instantiations": { + "count": 1, + "covered": 1, + "percent": 100 + }, + "lines": { + "count": 37, + "covered": 33, + "percent": 89.1891891891892 + }, + "regions": { + "count": 25, + "covered": 17, + "notcovered": 8, + "percent": 68 + } + } + } + ], + "totals": { + "functions": { + "count": 1, + "covered": 1, + "percent": 100 + }, + "instantiations": { + "count": 1, + "covered": 1, + "percent": 100 + }, + "lines": { + "count": 37, + "covered": 33, + "percent": 89.1891891891892 + }, + "regions": { + "count": 25, + "covered": 17, + "notcovered": 8, + "percent": 68 + } + } + } + ], + "type": "llvm.coverage.json.export", + "version": "2.0.1" +} diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.match_or_pattern.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.match_or_pattern.txt new file mode 100644 index 0000000000000..a0fccb24f9980 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.match_or_pattern.txt @@ -0,0 +1,50 @@ + 1| |#![feature(or_patterns)] + 2| | + 3| 1|fn main() { + 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure + 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + 6| 1| // dependent conditions. + 7| 1| let is_true = std::env::args().len() == 1; + 8| 1| + 9| 1| let mut a: u8 = 0; + 10| 1| let mut b: u8 = 0; + 11| 1| if is_true { + 12| 1| a = 2; + 13| 1| b = 0; + 14| 1| } + ^0 + 15| 1| match (a, b) { + 16| | // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`. + 17| | // This test confirms a fix for Issue #79569. + 18| 0| (0 | 1, 2 | 3) => {} + 19| 1| _ => {} + 20| | } + 21| 1| if is_true { + 22| 1| a = 0; + 23| 1| b = 0; + 24| 1| } + ^0 + 25| 1| match (a, b) { + 26| 0| (0 | 1, 2 | 3) => {} + 27| 1| _ => {} + 28| | } + 29| 1| if is_true { + 30| 1| a = 2; + 31| 1| b = 2; + 32| 1| } + ^0 + 33| 1| match (a, b) { + 34| 0| (0 | 1, 2 | 3) => {} + 35| 1| _ => {} + 36| | } + 37| 1| if is_true { + 38| 1| a = 0; + 39| 1| b = 2; + 40| 1| } + ^0 + 41| 1| match (a, b) { + 42| 1| (0 | 1, 2 | 3) => {} + 43| 0| _ => {} + 44| | } + 45| 1|} + diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt index ed91e8898ee98..4df0bac8c866c 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt @@ -28,11 +28,8 @@ Counter in file 0 79:14 -> 79:16, 0 Counter in file 0 81:1 -> 81:2, 0 Counter in file 0 91:25 -> 91:34, 0 Counter in file 0 5:1 -> 5:25, #1 -Counter in file 0 5:25 -> 6:14, #1 -Counter in file 0 7:9 -> 7:10, #2 -Counter in file 0 9:9 -> 9:10, (#1 - #2) -Counter in file 0 11:1 -> 11:2, (#2 + (#1 - #2)) Counter in file 0 21:1 -> 21:23, #1 +Counter in file 0 17:20 -> 17:21, #1 Counter in file 0 67:5 -> 67:23, #1 Counter in file 0 38:1 -> 38:19, #1 Counter in file 0 38:19 -> 42:12, #1 @@ -46,14 +43,18 @@ Counter in file 0 44:27 -> 44:32, #8 Counter in file 0 44:36 -> 44:38, (#6 + 0) Counter in file 0 45:14 -> 45:16, #7 Counter in file 0 47:1 -> 47:2, (#5 + (#6 + #7)) +Counter in file 0 13:20 -> 13:21, #1 Counter in file 0 29:1 -> 29:22, #1 Counter in file 0 93:1 -> 101:2, #1 Counter in file 0 91:1 -> 91:25, #1 +Counter in file 0 5:25 -> 6:14, #1 +Counter in file 0 7:9 -> 7:10, #2 +Counter in file 0 9:9 -> 9:10, (#1 - #2) +Counter in file 0 11:1 -> 11:2, (#2 + (#1 - #2)) Counter in file 0 51:5 -> 52:18, #1 Counter in file 0 53:13 -> 53:14, #2 Counter in file 0 63:13 -> 63:14, (#1 - #2) Counter in file 0 65:5 -> 65:6, (#2 + (#1 - #2)) -Counter in file 0 17:20 -> 17:21, #1 Counter in file 0 49:1 -> 68:12, #1 Counter in file 0 69:9 -> 69:10, #2 Counter in file 0 69:14 -> 69:27, (#1 + 0) @@ -70,7 +71,6 @@ Counter in file 0 87:14 -> 87:16, #3 Counter in file 0 89:1 -> 89:2, (#3 + (#2 + (#1 - (#3 + #2)))) Counter in file 0 17:1 -> 17:20, #1 Counter in file 0 66:5 -> 66:23, #1 -Counter in file 0 13:20 -> 13:21, #1 Counter in file 0 17:9 -> 17:10, #1 Counter in file 0 17:9 -> 17:10, #1 Counter in file 0 117:17 -> 117:19, #1 diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.match_or_pattern.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.match_or_pattern.txt new file mode 100644 index 0000000000000..fc12612ce7d7e --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.match_or_pattern.txt @@ -0,0 +1,98 @@ +Counter in file 0 3:1 -> 11:15, #1 +Counter in file 0 11:16 -> 14:6, #2 +Counter in file 0 14:6 -> 14:7, (#1 - #2) +Counter in file 0 15:11 -> 15:17, (#2 + (#1 - #2)) +Counter in file 0 18:27 -> 18:29, #5 +Counter in file 0 19:14 -> 19:16, (#3 + #4) +Counter in file 0 21:8 -> 21:15, ((#3 + #4) + #5) +Counter in file 0 21:16 -> 24:6, #6 +Counter in file 0 24:6 -> 24:7, (((#3 + #4) + #5) - #6) +Counter in file 0 25:11 -> 25:17, (#6 + (((#3 + #4) + #5) - #6)) +Counter in file 0 26:27 -> 26:29, #9 +Counter in file 0 27:14 -> 27:16, (#7 + #8) +Counter in file 0 29:8 -> 29:15, ((#7 + #8) + #9) +Counter in file 0 29:16 -> 32:6, #10 +Counter in file 0 32:6 -> 32:7, (((#7 + #8) + #9) - #10) +Counter in file 0 33:11 -> 33:17, (#10 + (((#7 + #8) + #9) - #10)) +Counter in file 0 34:27 -> 34:29, #13 +Counter in file 0 35:14 -> 35:16, (#11 + #12) +Counter in file 0 37:8 -> 37:15, ((#11 + #12) + #13) +Counter in file 0 37:16 -> 40:6, #14 +Counter in file 0 40:6 -> 40:7, (((#11 + #12) + #13) - #14) +Counter in file 0 41:11 -> 41:17, (#14 + (((#11 + #12) + #13) - #14)) +Counter in file 0 42:27 -> 42:29, #17 +Counter in file 0 43:14 -> 43:16, (#15 + #16) +Counter in file 0 45:1 -> 45:2, ((#15 + #16) + #17) +Emitting segments for file: ../coverage/match_or_pattern.rs +Combined regions: + 3:1 -> 11:15 (count=1) + 11:16 -> 14:6 (count=1) + 14:6 -> 14:7 (count=0) + 15:11 -> 15:17 (count=1) + 18:27 -> 18:29 (count=0) + 19:14 -> 19:16 (count=1) + 21:8 -> 21:15 (count=1) + 21:16 -> 24:6 (count=1) + 24:6 -> 24:7 (count=0) + 25:11 -> 25:17 (count=1) + 26:27 -> 26:29 (count=0) + 27:14 -> 27:16 (count=1) + 29:8 -> 29:15 (count=1) + 29:16 -> 32:6 (count=1) + 32:6 -> 32:7 (count=0) + 33:11 -> 33:17 (count=1) + 34:27 -> 34:29 (count=0) + 35:14 -> 35:16 (count=1) + 37:8 -> 37:15 (count=1) + 37:16 -> 40:6 (count=1) + 40:6 -> 40:7 (count=0) + 41:11 -> 41:17 (count=1) + 42:27 -> 42:29 (count=1) + 43:14 -> 43:16 (count=0) + 45:1 -> 45:2 (count=1) +Segment at 3:1 (count = 1), RegionEntry +Segment at 11:15 (count = 0), Skipped +Segment at 11:16 (count = 1), RegionEntry +Segment at 14:6 (count = 0), RegionEntry +Segment at 14:7 (count = 0), Skipped +Segment at 15:11 (count = 1), RegionEntry +Segment at 15:17 (count = 0), Skipped +Segment at 18:27 (count = 0), RegionEntry +Segment at 18:29 (count = 0), Skipped +Segment at 19:14 (count = 1), RegionEntry +Segment at 19:16 (count = 0), Skipped +Segment at 21:8 (count = 1), RegionEntry +Segment at 21:15 (count = 0), Skipped +Segment at 21:16 (count = 1), RegionEntry +Segment at 24:6 (count = 0), RegionEntry +Segment at 24:7 (count = 0), Skipped +Segment at 25:11 (count = 1), RegionEntry +Segment at 25:17 (count = 0), Skipped +Segment at 26:27 (count = 0), RegionEntry +Segment at 26:29 (count = 0), Skipped +Segment at 27:14 (count = 1), RegionEntry +Segment at 27:16 (count = 0), Skipped +Segment at 29:8 (count = 1), RegionEntry +Segment at 29:15 (count = 0), Skipped +Segment at 29:16 (count = 1), RegionEntry +Segment at 32:6 (count = 0), RegionEntry +Segment at 32:7 (count = 0), Skipped +Segment at 33:11 (count = 1), RegionEntry +Segment at 33:17 (count = 0), Skipped +Segment at 34:27 (count = 0), RegionEntry +Segment at 34:29 (count = 0), Skipped +Segment at 35:14 (count = 1), RegionEntry +Segment at 35:16 (count = 0), Skipped +Segment at 37:8 (count = 1), RegionEntry +Segment at 37:15 (count = 0), Skipped +Segment at 37:16 (count = 1), RegionEntry +Segment at 40:6 (count = 0), RegionEntry +Segment at 40:7 (count = 0), Skipped +Segment at 41:11 (count = 1), RegionEntry +Segment at 41:17 (count = 0), Skipped +Segment at 42:27 (count = 1), RegionEntry +Segment at 42:29 (count = 0), Skipped +Segment at 43:14 (count = 0), RegionEntry +Segment at 43:16 (count = 0), Skipped +Segment at 45:1 (count = 1), RegionEntry +Segment at 45:2 (count = 0), Skipped diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html new file mode 100644 index 0000000000000..133a85c83945e --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.match_or_pattern/match_or_pattern.main.-------.InstrumentCoverage.0.html @@ -0,0 +1,271 @@ + + + + +match_or_pattern.main - Coverage Spans + + + +
@0,1,2,3⦊fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut a: u8 = 0; + let mut b: u8 = 0; + if is_true⦉@0,1,2,3 @4,6⦊{ + a = 2; + b = 0; + }⦉@4,6@5⦊⦉@5 + match @7⦊(a, b)⦉@7 { + // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`. + // This test confirms a fix for Issue #79569. + (0 | 1, 2 | 3) => @10,11⦊{}⦉@10,11 + _ => @8⦊{}⦉@8 + } + if @12⦊is_true⦉@12 @13,15⦊{ + a = 0; + b = 0; + }⦉@13,15@14⦊⦉@14 + match @16⦊(a, b)⦉@16 { + (0 | 1, 2 | 3) => @19,20⦊{}⦉@19,20 + _ => @17⦊{}⦉@17 + } + if @21⦊is_true⦉@21 @22,24⦊{ + a = 2; + b = 2; + }⦉@22,24@23⦊⦉@23 + match @25⦊(a, b)⦉@25 { + (0 | 1, 2 | 3) => @28,29⦊{}⦉@28,29 + _ => @26⦊{}⦉@26 + } + if @30⦊is_true⦉@30 @31,33⦊{ + a = 0; + b = 2; + }⦉@31,33@32⦊⦉@32 + match @34⦊(a, b)⦉@34 { + (0 | 1, 2 | 3) => @37,38⦊{}⦉@37,38 + _ => @35⦊{}⦉@35 + } +}@39⦊⦉@39
+ + diff --git a/src/test/run-make-fulldeps/coverage/match_or_pattern.rs b/src/test/run-make-fulldeps/coverage/match_or_pattern.rs new file mode 100644 index 0000000000000..4c6a8a9b7037c --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/match_or_pattern.rs @@ -0,0 +1,45 @@ +#![feature(or_patterns)] + +fn main() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + + let mut a: u8 = 0; + let mut b: u8 = 0; + if is_true { + a = 2; + b = 0; + } + match (a, b) { + // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`. + // This test confirms a fix for Issue #79569. + (0 | 1, 2 | 3) => {} + _ => {} + } + if is_true { + a = 0; + b = 0; + } + match (a, b) { + (0 | 1, 2 | 3) => {} + _ => {} + } + if is_true { + a = 2; + b = 2; + } + match (a, b) { + (0 | 1, 2 | 3) => {} + _ => {} + } + if is_true { + a = 0; + b = 2; + } + match (a, b) { + (0 | 1, 2 | 3) => {} + _ => {} + } +} From 4f550f1f930b9201bbeeb9fa10d42392a66cc9f2 Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Mon, 14 Dec 2020 00:25:29 -0800 Subject: [PATCH 2/3] Improve warnings on incompatible options involving -Zinstrument-coverage Adds checks for: * `no_core` attribute * explicitly-enabled `legacy` symbol mangling * mir_opt_level > 1 (which enables inlining) I removed code from the `Inline` MIR pass that forcibly disabled inlining if `-Zinstrument-coverage` was set. The default `mir_opt_level` does not enable inlining anyway. But if the level is explicitly set and is greater than 1, I issue a warning. The new warnings show up in tests, which is much better for diagnosing potential option conflicts in these cases. --- compiler/rustc_interface/src/tests.rs | 4 +- compiler/rustc_metadata/src/creader.rs | 11 +++++- compiler/rustc_metadata/src/rmeta/encoder.rs | 7 +++- .../rustc_mir/src/transform/const_prop.rs | 8 ++-- compiler/rustc_mir/src/transform/dest_prop.rs | 3 +- .../src/transform/early_otherwise_branch.rs | 3 +- compiler/rustc_mir/src/transform/inline.rs | 11 +----- .../rustc_mir/src/transform/match_branches.rs | 3 +- compiler/rustc_mir/src/transform/mod.rs | 3 +- .../transform/multiple_return_terminators.rs | 3 +- compiler/rustc_mir/src/transform/nrvo.rs | 3 +- .../src/transform/unreachable_prop.rs | 3 +- compiler/rustc_session/src/config.rs | 38 ++++++++++++++++++- compiler/rustc_session/src/options.rs | 12 +++--- compiler/rustc_symbol_mangling/src/lib.rs | 6 ++- src/tools/clippy/src/driver.rs | 34 +++++++++-------- 16 files changed, 103 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2273266a3ff82..7a7def0696dbd 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -561,7 +561,7 @@ fn test_debugging_options_tracking_hash() { tracked!(link_only, true); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); - tracked!(mir_opt_level, 3); + tracked!(mir_opt_level, Some(3)); tracked!(mutable_noalias, true); tracked!(new_llvm_pass_manager, true); tracked!(no_codegen, true); @@ -587,7 +587,7 @@ fn test_debugging_options_tracking_hash() { tracked!(share_generics, Some(true)); tracked!(show_span, Some(String::from("abc"))); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); - tracked!(symbol_mangling_version, SymbolManglingVersion::V0); + tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(tune_cpu, Some(String::from("abc"))); diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 33cbf0fb2345e..019ca5174a223 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -706,7 +706,7 @@ impl<'a> CrateLoader<'a> { self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime()); } - fn inject_profiler_runtime(&mut self) { + fn inject_profiler_runtime(&mut self, krate: &ast::Crate) { if (self.sess.opts.debugging_opts.instrument_coverage || self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled()) @@ -714,6 +714,13 @@ impl<'a> CrateLoader<'a> { { info!("loading profiler"); + if self.sess.contains_name(&krate.attrs, sym::no_core) { + self.sess.err( + "`profiler_builtins` crate (required by compiler options) \ + is not compatible with crate attribute `#![no_core]`", + ); + } + let name = sym::profiler_builtins; let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None); let data = self.cstore.get_crate_data(cnum); @@ -879,7 +886,7 @@ impl<'a> CrateLoader<'a> { } pub fn postprocess(&mut self, krate: &ast::Crate) { - self.inject_profiler_runtime(); + self.inject_profiler_runtime(krate); self.inject_allocator_crate(krate); self.inject_panic_runtime(krate); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 46dd0df65e06f..b0c75c1de9d17 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -663,7 +663,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins), panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime), profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime), - symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version, + symbol_mangling_version: tcx + .sess + .opts + .debugging_opts + .symbol_mangling_version + .unwrap_or(SymbolManglingVersion::default()), crate_deps, dylib_dependency_formats, diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 1d949e020ed5c..49b1cf92600e8 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -22,6 +22,7 @@ use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{ self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable, }; +use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; use rustc_session::lint; use rustc_span::{def_id::DefId, Span}; use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout}; @@ -708,7 +709,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } - if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 3 { + if self.tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) >= 3 { self.eval_rvalue_with_identities(rvalue, place) } else { self.use_ecx(|this| this.ecx.eval_rvalue_into_place(rvalue, place)) @@ -886,7 +887,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { /// Returns `true` if and only if this `op` should be const-propagated into. fn should_const_prop(&mut self, op: OpTy<'tcx>) -> bool { - let mir_opt_level = self.tcx.sess.opts.debugging_opts.mir_opt_level; + let mir_opt_level = + self.tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT); if mir_opt_level == 0 { return false; @@ -1056,7 +1058,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { // Only const prop copies and moves on `mir_opt_level=2` as doing so // currently slightly increases compile time in some cases. - if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { + if self.tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) >= 2 { self.propagate_operand(operand) } } diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs index 46de5dba6e0ed..2363b6d58e1d8 100644 --- a/compiler/rustc_mir/src/transform/dest_prop.rs +++ b/compiler/rustc_mir/src/transform/dest_prop.rs @@ -115,6 +115,7 @@ use rustc_middle::mir::{ Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; // Empirical measurements have resulted in some observations: // - Running on a body with a single block and 500 locals takes barely any time @@ -129,7 +130,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Only run at mir-opt-level=2 or higher for now (we don't fix up debuginfo and remove // storage statements at the moment). - if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { + if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) <= 1 { return; } diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs index f91477911a489..023561923eebf 100644 --- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs +++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs @@ -1,6 +1,7 @@ use crate::{transform::MirPass, util::patch::MirPatch}; use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; use std::fmt::Debug; use super::simplify::simplify_cfg; @@ -26,7 +27,7 @@ pub struct EarlyOtherwiseBranch; impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level < 2 { + if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 2 { return; } trace!("running EarlyOtherwiseBranch on {:?}", body.source); diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index 4eeb8969bb110..1a927f9bf505c 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -9,6 +9,7 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; +use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; use rustc_span::{hygiene::ExpnKind, ExpnData, Span}; use rustc_target::spec::abi::Abi; @@ -37,15 +38,7 @@ struct CallSite<'tcx> { impl<'tcx> MirPass<'tcx> for Inline { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level < 2 { - return; - } - - if tcx.sess.opts.debugging_opts.instrument_coverage { - // The current implementation of source code coverage injects code region counters - // into the MIR, and assumes a 1-to-1 correspondence between MIR and source-code- - // based function. - debug!("function inlining is disabled when compiling with `instrument_coverage`"); + if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 2 { return; } diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs index 53eeecc780f6f..e28e3f59a5e00 100644 --- a/compiler/rustc_mir/src/transform/match_branches.rs +++ b/compiler/rustc_mir/src/transform/match_branches.rs @@ -1,6 +1,7 @@ use crate::transform::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; pub struct MatchBranchSimplification; @@ -38,7 +39,7 @@ pub struct MatchBranchSimplification; impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { + if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) <= 1 { return; } diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index e86d11e248fce..039dfe2c0d500 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -10,6 +10,7 @@ use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; +use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; use rustc_span::{Span, Symbol}; use std::borrow::Cow; @@ -373,7 +374,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc } fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level; + let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT); // Lowering generator control-flow and variables has to happen before we do anything else // to them. We run some optimizations before that, because they may be harder to do on the state diff --git a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs index 617086622cc1a..de4aee7ddbcc2 100644 --- a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs +++ b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs @@ -5,12 +5,13 @@ use crate::transform::{simplify, MirPass}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; pub struct MultipleReturnTerminators; impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level < 3 { + if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 3 { return; } diff --git a/compiler/rustc_mir/src/transform/nrvo.rs b/compiler/rustc_mir/src/transform/nrvo.rs index ce02fb261df6f..6e1dc03b9cb31 100644 --- a/compiler/rustc_mir/src/transform/nrvo.rs +++ b/compiler/rustc_mir/src/transform/nrvo.rs @@ -5,6 +5,7 @@ use rustc_index::bit_set::HybridBitSet; use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, BasicBlock, Local, Location}; use rustc_middle::ty::TyCtxt; +use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; use crate::transform::MirPass; @@ -34,7 +35,7 @@ pub struct RenameReturnPlace; impl<'tcx> MirPass<'tcx> for RenameReturnPlace { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { + if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) == 0 { return; } diff --git a/compiler/rustc_mir/src/transform/unreachable_prop.rs b/compiler/rustc_mir/src/transform/unreachable_prop.rs index e39c8656021b2..c9053ce81cd00 100644 --- a/compiler/rustc_mir/src/transform/unreachable_prop.rs +++ b/compiler/rustc_mir/src/transform/unreachable_prop.rs @@ -7,12 +7,13 @@ use crate::transform::MirPass; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; pub struct UnreachablePropagation; impl MirPass<'_> for UnreachablePropagation { fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level < 3 { + if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 3 { // Enable only under -Zmir-opt-level=3 as in some cases (check the deeply-nested-opt // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code. return; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 54abb65dc3883..47e494b78c7df 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -174,6 +174,8 @@ pub enum MirSpanview { Block, } +pub const MIR_OPT_LEVEL_DEFAULT: usize = 1; + #[derive(Clone, PartialEq, Hash)] pub enum LinkerPluginLto { LinkerPlugin(PathBuf), @@ -212,6 +214,12 @@ pub enum SymbolManglingVersion { V0, } +impl SymbolManglingVersion { + pub fn default() -> Self { + SymbolManglingVersion::Legacy + } +} + impl_stable_hash_via_hash!(SymbolManglingVersion); #[derive(Clone, Copy, Debug, PartialEq, Hash)] @@ -1757,7 +1765,33 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { // and reversible name mangling. Note, LLVM coverage tools can analyze coverage over // multiple runs, including some changes to source code; so mangled names must be consistent // across compilations. - debugging_opts.symbol_mangling_version = SymbolManglingVersion::V0; + match debugging_opts.symbol_mangling_version { + None => { + debugging_opts.symbol_mangling_version = Some(SymbolManglingVersion::V0); + } + Some(SymbolManglingVersion::Legacy) => { + early_warn( + error_format, + "-Z instrument-coverage requires symbol mangling version `v0`, \ + but `-Z symbol-mangling-version=legacy` was specified", + ); + } + Some(SymbolManglingVersion::V0) => {} + } + + match debugging_opts.mir_opt_level { + Some(level) if level > 1 => { + early_warn( + error_format, + &format!( + "`-Z mir-opt-level={}` (any level > 1) enables function inlining, which \ + limits the effectiveness of `-Z instrument-coverage`.", + level, + ), + ); + } + _ => {} + } } if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") { @@ -2162,7 +2196,7 @@ crate mod dep_tracking { impl_dep_tracking_hash_via_hash!(Edition); impl_dep_tracking_hash_via_hash!(LinkerPluginLto); impl_dep_tracking_hash_via_hash!(SwitchWithOptPath); - impl_dep_tracking_hash_via_hash!(SymbolManglingVersion); + impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(TrimmedDefPaths); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 74578f2dc179f..1909550aca489 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -677,12 +677,12 @@ macro_rules! options { } fn parse_symbol_mangling_version( - slot: &mut SymbolManglingVersion, + slot: &mut Option, v: Option<&str>, ) -> bool { *slot = match v { - Some("legacy") => SymbolManglingVersion::Legacy, - Some("v0") => SymbolManglingVersion::V0, + Some("legacy") => Some(SymbolManglingVersion::Legacy), + Some("v0") => Some(SymbolManglingVersion::V0), _ => return false, }; true @@ -970,7 +970,7 @@ 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_opt_level: Option = (None, parse_opt_uint, [TRACKED], "MIR optimization level (0-3; default: 1)"), mutable_noalias: bool = (false, parse_bool, [TRACKED], "emit noalias metadata for mutable references (default: no)"), @@ -1088,9 +1088,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), - symbol_mangling_version: SymbolManglingVersion = (SymbolManglingVersion::Legacy, + symbol_mangling_version: Option = (None, parse_symbol_mangling_version, [TRACKED], - "which mangling version to use for symbol names"), + "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 = (None, parse_opt_uint, [UNTRACKED], diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 10245d21b63a5..945e788a1460c 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -245,7 +245,11 @@ fn compute_symbol_name( // 2. we favor `instantiating_crate` where possible (i.e. when `Some`) let mangling_version_crate = instantiating_crate.unwrap_or(def_id.krate); let mangling_version = if mangling_version_crate == LOCAL_CRATE { - tcx.sess.opts.debugging_opts.symbol_mangling_version + tcx.sess + .opts + .debugging_opts + .symbol_mangling_version + .unwrap_or(SymbolManglingVersion::default()) } else { tcx.symbol_mangling_version(mangling_version_crate) }; diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index ef31c72481a23..9e5ae21f7026e 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -41,7 +41,7 @@ fn arg_value<'a, T: Deref>( match arg.next().or_else(|| args.next()) { Some(v) if pred(v) => return Some(v), - _ => {}, + _ => {} } } None @@ -85,7 +85,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { // run on the unoptimized MIR. On the other hand this results in some false negatives. If // MIR passes can be enabled / disabled separately, we should figure out, what passes to // use for Clippy. - config.opts.debugging_opts.mir_opt_level = 0; + config.opts.debugging_opts.mir_opt_level = Some(0); } } @@ -121,11 +121,12 @@ You can use tool lints to allow or deny lints from your code, eg.: const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new"; -static ICE_HOOK: SyncLazy) + Sync + Send + 'static>> = SyncLazy::new(|| { - let hook = panic::take_hook(); - panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL))); - hook -}); +static ICE_HOOK: SyncLazy) + Sync + Send + 'static>> = + SyncLazy::new(|| { + let hook = panic::take_hook(); + panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL))); + hook + }); fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { // Invoke our ICE handler, which prints the actual panic message and optionally a backtrace @@ -257,14 +258,17 @@ pub fn main() { // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. // We're invoking the compiler programmatically, so we ignore this/ - let wrapper_mode = orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref()); + let wrapper_mode = + orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref()); if wrapper_mode { // we still want to be able to invoke it normally though orig_args.remove(1); } - if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) { + if !wrapper_mode + && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) + { display_help(); exit(0); } @@ -285,13 +289,11 @@ pub fn main() { if clippy_enabled { args.extend(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()]); if let Ok(extra_args) = env::var("CLIPPY_ARGS") { - args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| { - if s.is_empty() { - None - } else { - Some(s.to_string()) - } - })); + args.extend( + extra_args + .split("__CLIPPY_HACKERY__") + .filter_map(|s| if s.is_empty() { None } else { Some(s.to_string()) }), + ); } } let mut clippy = ClippyCallbacks; From 36c639a2ce2808c2c95cacf0856026235ad6350f Mon Sep 17 00:00:00 2001 From: Rich Kadel Date: Mon, 14 Dec 2020 13:12:15 -0800 Subject: [PATCH 3/3] Convenience funcs for `some_option.unwrap_or(...)` This ensures consistent handling of default values for options that are None if not specified on the command line. --- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 7 +--- .../rustc_mir/src/transform/const_prop.rs | 8 ++--- compiler/rustc_mir/src/transform/dest_prop.rs | 3 +- .../src/transform/early_otherwise_branch.rs | 3 +- compiler/rustc_mir/src/transform/inline.rs | 3 +- .../rustc_mir/src/transform/match_branches.rs | 3 +- compiler/rustc_mir/src/transform/mod.rs | 3 +- .../transform/multiple_return_terminators.rs | 3 +- compiler/rustc_mir/src/transform/nrvo.rs | 3 +- .../src/transform/unreachable_prop.rs | 3 +- compiler/rustc_session/src/config.rs | 33 ++++++++----------- compiler/rustc_session/src/options.rs | 2 +- compiler/rustc_symbol_mangling/src/lib.rs | 6 +--- src/tools/clippy/src/driver.rs | 2 +- 15 files changed, 29 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 7a7def0696dbd..3e94f1637734a 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -561,7 +561,7 @@ fn test_debugging_options_tracking_hash() { tracked!(link_only, true); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); - tracked!(mir_opt_level, Some(3)); + tracked!(mir_opt_level, 3); tracked!(mutable_noalias, true); tracked!(new_llvm_pass_manager, true); tracked!(no_codegen, true); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b0c75c1de9d17..7b67d15f64a2e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -663,12 +663,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins), panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime), profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime), - symbol_mangling_version: tcx - .sess - .opts - .debugging_opts - .symbol_mangling_version - .unwrap_or(SymbolManglingVersion::default()), + symbol_mangling_version: tcx.sess.opts.debugging_opts.get_symbol_mangling_version(), crate_deps, dylib_dependency_formats, diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 49b1cf92600e8..1d949e020ed5c 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -22,7 +22,6 @@ use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{ self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable, }; -use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; use rustc_session::lint; use rustc_span::{def_id::DefId, Span}; use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout}; @@ -709,7 +708,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } - if self.tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) >= 3 { + if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 3 { self.eval_rvalue_with_identities(rvalue, place) } else { self.use_ecx(|this| this.ecx.eval_rvalue_into_place(rvalue, place)) @@ -887,8 +886,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { /// Returns `true` if and only if this `op` should be const-propagated into. fn should_const_prop(&mut self, op: OpTy<'tcx>) -> bool { - let mir_opt_level = - self.tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT); + let mir_opt_level = self.tcx.sess.opts.debugging_opts.mir_opt_level; if mir_opt_level == 0 { return false; @@ -1058,7 +1056,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { // Only const prop copies and moves on `mir_opt_level=2` as doing so // currently slightly increases compile time in some cases. - if self.tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) >= 2 { + if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { self.propagate_operand(operand) } } diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs index 2363b6d58e1d8..46de5dba6e0ed 100644 --- a/compiler/rustc_mir/src/transform/dest_prop.rs +++ b/compiler/rustc_mir/src/transform/dest_prop.rs @@ -115,7 +115,6 @@ use rustc_middle::mir::{ Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; // Empirical measurements have resulted in some observations: // - Running on a body with a single block and 500 locals takes barely any time @@ -130,7 +129,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Only run at mir-opt-level=2 or higher for now (we don't fix up debuginfo and remove // storage statements at the moment). - if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) <= 1 { + if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { return; } diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs index 023561923eebf..f91477911a489 100644 --- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs +++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs @@ -1,7 +1,6 @@ use crate::{transform::MirPass, util::patch::MirPatch}; use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; -use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; use std::fmt::Debug; use super::simplify::simplify_cfg; @@ -27,7 +26,7 @@ pub struct EarlyOtherwiseBranch; impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 2 { + if tcx.sess.opts.debugging_opts.mir_opt_level < 2 { return; } trace!("running EarlyOtherwiseBranch on {:?}", body.source); diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index 1a927f9bf505c..6e7575c1d71bb 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -9,7 +9,6 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; -use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; use rustc_span::{hygiene::ExpnKind, ExpnData, Span}; use rustc_target::spec::abi::Abi; @@ -38,7 +37,7 @@ struct CallSite<'tcx> { impl<'tcx> MirPass<'tcx> for Inline { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 2 { + if tcx.sess.opts.debugging_opts.mir_opt_level < 2 { return; } diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs index e28e3f59a5e00..53eeecc780f6f 100644 --- a/compiler/rustc_mir/src/transform/match_branches.rs +++ b/compiler/rustc_mir/src/transform/match_branches.rs @@ -1,7 +1,6 @@ use crate::transform::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; pub struct MatchBranchSimplification; @@ -39,7 +38,7 @@ pub struct MatchBranchSimplification; impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) <= 1 { + if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { return; } diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 039dfe2c0d500..e86d11e248fce 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -10,7 +10,6 @@ use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; -use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; use rustc_span::{Span, Symbol}; use std::borrow::Cow; @@ -374,7 +373,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc } fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT); + let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level; // Lowering generator control-flow and variables has to happen before we do anything else // to them. We run some optimizations before that, because they may be harder to do on the state diff --git a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs index de4aee7ddbcc2..617086622cc1a 100644 --- a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs +++ b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs @@ -5,13 +5,12 @@ use crate::transform::{simplify, MirPass}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; pub struct MultipleReturnTerminators; impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 3 { + if tcx.sess.opts.debugging_opts.mir_opt_level < 3 { return; } diff --git a/compiler/rustc_mir/src/transform/nrvo.rs b/compiler/rustc_mir/src/transform/nrvo.rs index 6e1dc03b9cb31..ce02fb261df6f 100644 --- a/compiler/rustc_mir/src/transform/nrvo.rs +++ b/compiler/rustc_mir/src/transform/nrvo.rs @@ -5,7 +5,6 @@ use rustc_index::bit_set::HybridBitSet; use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, BasicBlock, Local, Location}; use rustc_middle::ty::TyCtxt; -use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; use crate::transform::MirPass; @@ -35,7 +34,7 @@ pub struct RenameReturnPlace; impl<'tcx> MirPass<'tcx> for RenameReturnPlace { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) == 0 { + if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { return; } diff --git a/compiler/rustc_mir/src/transform/unreachable_prop.rs b/compiler/rustc_mir/src/transform/unreachable_prop.rs index c9053ce81cd00..e39c8656021b2 100644 --- a/compiler/rustc_mir/src/transform/unreachable_prop.rs +++ b/compiler/rustc_mir/src/transform/unreachable_prop.rs @@ -7,13 +7,12 @@ use crate::transform::MirPass; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use rustc_session::config::MIR_OPT_LEVEL_DEFAULT; pub struct UnreachablePropagation; impl MirPass<'_> for UnreachablePropagation { fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 3 { + if tcx.sess.opts.debugging_opts.mir_opt_level < 3 { // Enable only under -Zmir-opt-level=3 as in some cases (check the deeply-nested-opt // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code. return; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 47e494b78c7df..b77a8b631e056 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -174,8 +174,6 @@ pub enum MirSpanview { Block, } -pub const MIR_OPT_LEVEL_DEFAULT: usize = 1; - #[derive(Clone, PartialEq, Hash)] pub enum LinkerPluginLto { LinkerPlugin(PathBuf), @@ -214,12 +212,6 @@ pub enum SymbolManglingVersion { V0, } -impl SymbolManglingVersion { - pub fn default() -> Self { - SymbolManglingVersion::Legacy - } -} - impl_stable_hash_via_hash!(SymbolManglingVersion); #[derive(Clone, Copy, Debug, PartialEq, Hash)] @@ -700,6 +692,10 @@ impl DebuggingOptions { deduplicate_diagnostics: self.deduplicate_diagnostics, } } + + pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { + self.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy) + } } // The type of entry function, so users can have their own entry functions @@ -1779,18 +1775,15 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { Some(SymbolManglingVersion::V0) => {} } - match debugging_opts.mir_opt_level { - Some(level) if level > 1 => { - early_warn( - error_format, - &format!( - "`-Z mir-opt-level={}` (any level > 1) enables function inlining, which \ - limits the effectiveness of `-Z instrument-coverage`.", - level, - ), - ); - } - _ => {} + if debugging_opts.mir_opt_level > 1 { + early_warn( + error_format, + &format!( + "`-Z mir-opt-level={}` (any level > 1) enables function inlining, which \ + limits the effectiveness of `-Z instrument-coverage`.", + debugging_opts.mir_opt_level, + ), + ); } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 1909550aca489..49a7888fd6a42 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -970,7 +970,7 @@ 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: Option = (None, parse_opt_uint, [TRACKED], + 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)"), diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 945e788a1460c..7f8cded0ac0ec 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -245,11 +245,7 @@ fn compute_symbol_name( // 2. we favor `instantiating_crate` where possible (i.e. when `Some`) let mangling_version_crate = instantiating_crate.unwrap_or(def_id.krate); let mangling_version = if mangling_version_crate == LOCAL_CRATE { - tcx.sess - .opts - .debugging_opts - .symbol_mangling_version - .unwrap_or(SymbolManglingVersion::default()) + tcx.sess.opts.debugging_opts.get_symbol_mangling_version() } else { tcx.symbol_mangling_version(mangling_version_crate) }; diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 9e5ae21f7026e..87dd19c5d4d05 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -85,7 +85,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { // run on the unoptimized MIR. On the other hand this results in some false negatives. If // MIR passes can be enabled / disabled separately, we should figure out, what passes to // use for Clippy. - config.opts.debugging_opts.mir_opt_level = Some(0); + config.opts.debugging_opts.mir_opt_level = 0; } }