Skip to content

Commit 8a1ac81

Browse files
committed
Move LTO to OngoingCodegen::join
1 parent 035891f commit 8a1ac81

File tree

4 files changed

+132
-48
lines changed

4 files changed

+132
-48
lines changed

compiler/rustc_codegen_ssa/src/back/write.rs

Lines changed: 111 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_errors::emitter::Emitter;
1616
use rustc_errors::translation::Translator;
1717
use rustc_errors::{
1818
Diag, DiagArgMap, DiagCtxt, DiagCtxtHandle, DiagMessage, ErrCode, FatalError, FatalErrorMarker,
19-
Level, MultiSpan, Style, Suggestions,
19+
Level, MultiSpan, Style, Suggestions, catch_fatal_errors,
2020
};
2121
use rustc_fs_util::link_or_copy;
2222
use rustc_incremental::{
@@ -403,6 +403,29 @@ struct CompiledModules {
403403
allocator_module: Option<CompiledModule>,
404404
}
405405

406+
enum MaybeLtoModules<B: WriteBackendMethods> {
407+
NoLto {
408+
modules: Vec<CompiledModule>,
409+
allocator_module: Option<CompiledModule>,
410+
},
411+
FatLto {
412+
cgcx: CodegenContext<B>,
413+
exported_symbols_for_lto: Arc<Vec<String>>,
414+
each_linked_rlib_file_for_lto: Vec<PathBuf>,
415+
needs_fat_lto: Vec<FatLtoInput<B>>,
416+
lto_import_only_modules:
417+
Vec<(SerializedModule<<B as WriteBackendMethods>::ModuleBuffer>, WorkProduct)>,
418+
},
419+
ThinLto {
420+
cgcx: CodegenContext<B>,
421+
exported_symbols_for_lto: Arc<Vec<String>>,
422+
each_linked_rlib_file_for_lto: Vec<PathBuf>,
423+
needs_thin_lto: Vec<(String, <B as WriteBackendMethods>::ThinBuffer)>,
424+
lto_import_only_modules:
425+
Vec<(SerializedModule<<B as WriteBackendMethods>::ModuleBuffer>, WorkProduct)>,
426+
},
427+
}
428+
406429
fn need_bitcode_in_object(tcx: TyCtxt<'_>) -> bool {
407430
let sess = tcx.sess;
408431
sess.opts.cg.embed_bitcode
@@ -1239,7 +1262,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
12391262
allocator_config: Arc<ModuleConfig>,
12401263
mut allocator_module: Option<ModuleCodegen<B::Module>>,
12411264
coordinator_send: Sender<Message<B>>,
1242-
) -> thread::JoinHandle<Result<CompiledModules, ()>> {
1265+
) -> thread::JoinHandle<Result<MaybeLtoModules<B>, ()>> {
12431266
let sess = tcx.sess;
12441267

12451268
let mut each_linked_rlib_for_lto = Vec::new();
@@ -1732,51 +1755,52 @@ fn start_executing_work<B: ExtraBackendMethods>(
17321755
drop(helper);
17331756
assert!(work_items.is_empty());
17341757

1735-
if !needs_fat_lto.is_empty() {
1758+
if cgcx.lto == Lto::ThinLocal {
1759+
assert!(compiled_modules.is_empty());
1760+
assert!(needs_fat_lto.is_empty());
1761+
1762+
compiled_modules.extend(do_thin_lto(
1763+
&cgcx,
1764+
shared_emitter.clone(),
1765+
exported_symbols_for_lto,
1766+
each_linked_rlib_file_for_lto,
1767+
needs_thin_lto,
1768+
lto_import_only_modules,
1769+
));
1770+
} else if !needs_fat_lto.is_empty() {
17361771
assert!(compiled_modules.is_empty());
17371772
assert!(needs_thin_lto.is_empty());
17381773

17391774
if let Some(allocator_module) = allocator_module.take() {
17401775
needs_fat_lto.push(FatLtoInput::InMemory(allocator_module));
17411776
}
17421777

1743-
// This uses the implicit token
1744-
let module = do_fat_lto(
1745-
&cgcx,
1746-
shared_emitter.clone(),
1747-
&exported_symbols_for_lto,
1748-
&each_linked_rlib_file_for_lto,
1778+
return Ok(MaybeLtoModules::FatLto {
1779+
cgcx,
1780+
exported_symbols_for_lto,
1781+
each_linked_rlib_file_for_lto,
17491782
needs_fat_lto,
17501783
lto_import_only_modules,
1751-
);
1752-
compiled_modules.push(module);
1784+
});
17531785
} else if !needs_thin_lto.is_empty() || !lto_import_only_modules.is_empty() {
17541786
assert!(compiled_modules.is_empty());
17551787
assert!(needs_fat_lto.is_empty());
17561788

1757-
if cgcx.lto != Lto::ThinLocal {
1758-
if let Some(allocator_module) = allocator_module.take() {
1759-
let (name, thin_buffer) = B::prepare_thin(allocator_module);
1760-
needs_thin_lto.push((name, thin_buffer));
1761-
}
1789+
if let Some(allocator_module) = allocator_module.take() {
1790+
let (name, thin_buffer) = B::prepare_thin(allocator_module);
1791+
needs_thin_lto.push((name, thin_buffer));
17621792
}
17631793

1764-
compiled_modules.extend(do_thin_lto(
1765-
&cgcx,
1766-
shared_emitter.clone(),
1794+
return Ok(MaybeLtoModules::ThinLto {
1795+
cgcx,
17671796
exported_symbols_for_lto,
17681797
each_linked_rlib_file_for_lto,
17691798
needs_thin_lto,
17701799
lto_import_only_modules,
1771-
));
1800+
});
17721801
}
17731802

1774-
// Regardless of what order these modules completed in, report them to
1775-
// the backend in the same order every time to ensure that we're handing
1776-
// out deterministic results.
1777-
compiled_modules.sort_by(|a, b| a.name.cmp(&b.name));
1778-
1779-
Ok(CompiledModules {
1803+
Ok(MaybeLtoModules::NoLto {
17801804
modules: compiled_modules,
17811805
allocator_module: allocator_module.map(|allocator_module| {
17821806
B::codegen(&cgcx, &shared_emitter, allocator_module, &allocator_config)
@@ -2074,13 +2098,13 @@ impl SharedEmitterMain {
20742098

20752099
pub struct Coordinator<B: ExtraBackendMethods> {
20762100
sender: Sender<Message<B>>,
2077-
future: Option<thread::JoinHandle<Result<CompiledModules, ()>>>,
2101+
future: Option<thread::JoinHandle<Result<MaybeLtoModules<B>, ()>>>,
20782102
// Only used for the Message type.
20792103
phantom: PhantomData<B>,
20802104
}
20812105

20822106
impl<B: ExtraBackendMethods> Coordinator<B> {
2083-
fn join(mut self) -> std::thread::Result<Result<CompiledModules, ()>> {
2107+
fn join(mut self) -> std::thread::Result<Result<MaybeLtoModules<B>, ()>> {
20842108
self.future.take().unwrap().join()
20852109
}
20862110
}
@@ -2111,8 +2135,9 @@ pub struct OngoingCodegen<B: ExtraBackendMethods> {
21112135
impl<B: ExtraBackendMethods> OngoingCodegen<B> {
21122136
pub fn join(self, sess: &Session) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
21132137
self.shared_emitter_main.check(sess, true);
2114-
let compiled_modules = sess.time("join_worker_thread", || match self.coordinator.join() {
2115-
Ok(Ok(compiled_modules)) => compiled_modules,
2138+
2139+
let maybe_lto_modules = sess.time("join_worker_thread", || match self.coordinator.join() {
2140+
Ok(Ok(maybe_lto_modules)) => maybe_lto_modules,
21162141
Ok(Err(())) => {
21172142
sess.dcx().abort_if_errors();
21182143
panic!("expected abort due to worker thread errors")
@@ -2124,6 +2149,62 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
21242149

21252150
sess.dcx().abort_if_errors();
21262151

2152+
let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
2153+
2154+
// Catch fatal errors to ensure shared_emitter_main.check() can emit the actual diagnostics
2155+
let compiled_modules = catch_fatal_errors(|| match maybe_lto_modules {
2156+
MaybeLtoModules::NoLto { modules, allocator_module } => {
2157+
drop(shared_emitter);
2158+
CompiledModules { modules, allocator_module }
2159+
}
2160+
MaybeLtoModules::FatLto {
2161+
cgcx,
2162+
exported_symbols_for_lto,
2163+
each_linked_rlib_file_for_lto,
2164+
needs_fat_lto,
2165+
lto_import_only_modules,
2166+
} => CompiledModules {
2167+
modules: vec![do_fat_lto(
2168+
&cgcx,
2169+
shared_emitter,
2170+
&exported_symbols_for_lto,
2171+
&each_linked_rlib_file_for_lto,
2172+
needs_fat_lto,
2173+
lto_import_only_modules,
2174+
)],
2175+
allocator_module: None,
2176+
},
2177+
MaybeLtoModules::ThinLto {
2178+
cgcx,
2179+
exported_symbols_for_lto,
2180+
each_linked_rlib_file_for_lto,
2181+
needs_thin_lto,
2182+
lto_import_only_modules,
2183+
} => CompiledModules {
2184+
modules: do_thin_lto(
2185+
&cgcx,
2186+
shared_emitter,
2187+
exported_symbols_for_lto,
2188+
each_linked_rlib_file_for_lto,
2189+
needs_thin_lto,
2190+
lto_import_only_modules,
2191+
),
2192+
allocator_module: None,
2193+
},
2194+
});
2195+
2196+
shared_emitter_main.check(sess, true);
2197+
2198+
sess.dcx().abort_if_errors();
2199+
2200+
let mut compiled_modules =
2201+
compiled_modules.expect("fatal error emitted but not sent to SharedEmitter");
2202+
2203+
// Regardless of what order these modules completed in, report them to
2204+
// the backend in the same order every time to ensure that we're handing
2205+
// out deterministic results.
2206+
compiled_modules.modules.sort_by(|a, b| a.name.cmp(&b.name));
2207+
21272208
let work_products =
21282209
copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess, &compiled_modules);
21292210
produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames);

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::ffi::OsString;
1919
use std::fmt::Write as _;
2020
use std::fs::{self, File};
2121
use std::io::{self, IsTerminal, Read, Write};
22-
use std::panic::{self, PanicHookInfo, catch_unwind};
22+
use std::panic::{self, PanicHookInfo};
2323
use std::path::{Path, PathBuf};
2424
use std::process::{self, Command, Stdio};
2525
use std::sync::OnceLock;
@@ -33,10 +33,11 @@ use rustc_codegen_ssa::{CodegenErrors, CodegenResults};
3333
use rustc_data_structures::profiling::{
3434
TimePassesFormat, get_resident_set_size, print_time_passes_entry,
3535
};
36+
pub use rustc_errors::catch_fatal_errors;
3637
use rustc_errors::emitter::stderr_destination;
3738
use rustc_errors::registry::Registry;
3839
use rustc_errors::translation::Translator;
39-
use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, FatalError, PResult, markdown};
40+
use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, PResult, markdown};
4041
use rustc_feature::find_gated_cfg;
4142
// This avoids a false positive with `-Wunused_crate_dependencies`.
4243
// `rust_index` isn't used in this crate's code, but it must be named in the
@@ -1306,21 +1307,6 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
13061307
parser.parse_inner_attributes()
13071308
}
13081309

1309-
/// Runs a closure and catches unwinds triggered by fatal errors.
1310-
///
1311-
/// The compiler currently unwinds with a special sentinel value to abort
1312-
/// compilation on fatal errors. This function catches that sentinel and turns
1313-
/// the panic into a `Result` instead.
1314-
pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, FatalError> {
1315-
catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
1316-
if value.is::<rustc_errors::FatalErrorMarker>() {
1317-
FatalError
1318-
} else {
1319-
panic::resume_unwind(value);
1320-
}
1321-
})
1322-
}
1323-
13241310
/// Variant of `catch_fatal_errors` for the `interface::Result` return type
13251311
/// that also computes the exit code.
13261312
pub fn catch_with_exit_code(f: impl FnOnce()) -> i32 {

compiler/rustc_errors/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub use rustc_lint_defs::{Applicability, listify, pluralize};
6868
use rustc_lint_defs::{Lint, LintExpectationId};
6969
use rustc_macros::{Decodable, Encodable};
7070
pub use rustc_span::ErrorGuaranteed;
71-
pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
71+
pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors};
7272
use rustc_span::source_map::SourceMap;
7373
use rustc_span::{BytePos, DUMMY_SP, Loc, Span};
7474
pub use snippet::Style;

compiler/rustc_span/src/fatal_error.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#[must_use]
44
pub struct FatalError;
55

6+
use std::panic;
7+
68
pub use rustc_data_structures::FatalErrorMarker;
79

810
// Don't implement Send on FatalError. This makes it impossible to `panic_any!(FatalError)`.
@@ -22,3 +24,18 @@ impl std::fmt::Display for FatalError {
2224
}
2325

2426
impl std::error::Error for FatalError {}
27+
28+
/// Runs a closure and catches unwinds triggered by fatal errors.
29+
///
30+
/// The compiler currently unwinds with a special sentinel value to abort
31+
/// compilation on fatal errors. This function catches that sentinel and turns
32+
/// the panic into a `Result` instead.
33+
pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, FatalError> {
34+
panic::catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
35+
if value.is::<FatalErrorMarker>() {
36+
FatalError
37+
} else {
38+
panic::resume_unwind(value);
39+
}
40+
})
41+
}

0 commit comments

Comments
 (0)