1 use super::link
::{self, ensure_removed}
;
2 use super::lto
::{self, SerializedModule}
;
3 use super::symbol_export
::symbol_name_for_instance_in_crate
;
6 CachedModuleCodegen
, CodegenResults
, CompiledModule
, CrateInfo
, ModuleCodegen
, ModuleKind
,
10 use jobserver
::{Acquired, Client}
;
11 use rustc_data_structures
::fx
::FxHashMap
;
12 use rustc_data_structures
::memmap
::Mmap
;
13 use rustc_data_structures
::profiling
::SelfProfilerRef
;
14 use rustc_data_structures
::profiling
::TimingGuard
;
15 use rustc_data_structures
::profiling
::VerboseTimingGuard
;
16 use rustc_data_structures
::sync
::Lrc
;
17 use rustc_errors
::emitter
::Emitter
;
18 use rustc_errors
::{translation::Translate, DiagnosticId, FatalError, Handler, Level}
;
19 use rustc_fs_util
::link_or_copy
;
20 use rustc_hir
::def_id
::{CrateNum, LOCAL_CRATE}
;
21 use rustc_incremental
::{
22 copy_cgu_workproduct_to_incr_comp_cache_dir
, in_incr_comp_dir
, in_incr_comp_dir_sess
,
24 use rustc_metadata
::EncodedMetadata
;
25 use rustc_middle
::dep_graph
::{WorkProduct, WorkProductId}
;
26 use rustc_middle
::middle
::exported_symbols
::SymbolExportInfo
;
27 use rustc_middle
::ty
::TyCtxt
;
28 use rustc_session
::cgu_reuse_tracker
::CguReuseTracker
;
29 use rustc_session
::config
::{self, CrateType, Lto, OutputFilenames, OutputType}
;
30 use rustc_session
::config
::{Passes, SwitchWithOptPath}
;
31 use rustc_session
::Session
;
32 use rustc_span
::source_map
::SourceMap
;
33 use rustc_span
::symbol
::sym
;
34 use rustc_span
::{BytePos, FileName, InnerSpan, Pos, Span}
;
35 use rustc_target
::spec
::{MergeFunctions, SanitizerSet}
;
40 use std
::marker
::PhantomData
;
42 use std
::path
::{Path, PathBuf}
;
44 use std
::sync
::mpsc
::{channel, Receiver, Sender}
;
48 const PRE_LTO_BC_EXT
: &str = "pre-lto.bc";
50 /// What kind of object file to emit.
51 #[derive(Clone, Copy, PartialEq)]
56 // Just uncompressed llvm bitcode. Provides easy compatibility with
57 // emscripten's ecc compiler, when used as the linker.
60 // Object code, possibly augmented with a bitcode section.
61 ObjectCode(BitcodeSection
),
64 /// What kind of llvm bitcode section to embed in an object file.
65 #[derive(Clone, Copy, PartialEq)]
66 pub enum BitcodeSection
{
67 // No bitcode section.
70 // A full, uncompressed bitcode section.
74 /// Module-specific configuration for `optimize_and_codegen`.
75 pub struct ModuleConfig
{
76 /// Names of additional optimization passes to run.
77 pub passes
: Vec
<String
>,
78 /// Some(level) to optimize at a certain level, or None to run
79 /// absolutely no optimizations (used for the metadata module).
80 pub opt_level
: Option
<config
::OptLevel
>,
82 /// Some(level) to optimize binary size, or None to not affect program size.
83 pub opt_size
: Option
<config
::OptLevel
>,
85 pub pgo_gen
: SwitchWithOptPath
,
86 pub pgo_use
: Option
<PathBuf
>,
87 pub pgo_sample_use
: Option
<PathBuf
>,
88 pub debug_info_for_profiling
: bool
,
89 pub instrument_coverage
: bool
,
90 pub instrument_gcov
: bool
,
92 pub sanitizer
: SanitizerSet
,
93 pub sanitizer_recover
: SanitizerSet
,
94 pub sanitizer_memory_track_origins
: usize,
96 // Flags indicating which outputs to produce.
97 pub emit_pre_lto_bc
: bool
,
98 pub emit_no_opt_bc
: bool
,
102 pub emit_obj
: EmitObj
,
103 pub emit_thin_lto
: bool
,
104 pub bc_cmdline
: String
,
106 // Miscellaneous flags. These are mostly copied from command-line
108 pub verify_llvm_ir
: bool
,
109 pub no_prepopulate_passes
: bool
,
110 pub no_builtins
: bool
,
111 pub time_module
: bool
,
112 pub vectorize_loop
: bool
,
113 pub vectorize_slp
: bool
,
114 pub merge_functions
: bool
,
115 pub inline_threshold
: Option
<u32>,
116 pub new_llvm_pass_manager
: Option
<bool
>,
117 pub emit_lifetime_markers
: bool
,
118 pub llvm_plugins
: Vec
<String
>,
126 is_compiler_builtins
: bool
,
128 // If it's a regular module, use `$regular`, otherwise use `$other`.
129 // `$regular` and `$other` are evaluated lazily.
130 macro_rules
! if_regular
{
131 ($regular
: expr
, $other
: expr
) => {
132 if let ModuleKind
::Regular
= kind { $regular }
else { $other }
136 let opt_level_and_size
= if_regular
!(Some(sess
.opts
.optimize
), None
);
138 let save_temps
= sess
.opts
.cg
.save_temps
;
140 let should_emit_obj
= sess
.opts
.output_types
.contains_key(&OutputType
::Exe
)
142 ModuleKind
::Regular
=> sess
.opts
.output_types
.contains_key(&OutputType
::Object
),
143 ModuleKind
::Allocator
=> false,
144 ModuleKind
::Metadata
=> sess
.opts
.output_types
.contains_key(&OutputType
::Metadata
),
147 let emit_obj
= if !should_emit_obj
{
149 } else if sess
.target
.obj_is_bitcode
150 || (sess
.opts
.cg
.linker_plugin_lto
.enabled() && !no_builtins
)
152 // This case is selected if the target uses objects as bitcode, or
153 // if linker plugin LTO is enabled. In the linker plugin LTO case
154 // the assumption is that the final link-step will read the bitcode
155 // and convert it to object code. This may be done by either the
156 // native linker or rustc itself.
158 // Note, however, that the linker-plugin-lto requested here is
159 // explicitly ignored for `#![no_builtins]` crates. These crates are
160 // specifically ignored by rustc's LTO passes and wouldn't work if
161 // loaded into the linker. These crates define symbols that LLVM
162 // lowers intrinsics to, and these symbol dependencies aren't known
163 // until after codegen. As a result any crate marked
164 // `#![no_builtins]` is assumed to not participate in LTO and
165 // instead goes on to generate object code.
167 } else if need_bitcode_in_object(sess
) {
168 EmitObj
::ObjectCode(BitcodeSection
::Full
)
170 EmitObj
::ObjectCode(BitcodeSection
::None
)
174 passes
: if_regular
!(sess
.opts
.cg
.passes
.clone(), vec
![]),
176 opt_level
: opt_level_and_size
,
177 opt_size
: opt_level_and_size
,
179 pgo_gen
: if_regular
!(
180 sess
.opts
.cg
.profile_generate
.clone(),
181 SwitchWithOptPath
::Disabled
183 pgo_use
: if_regular
!(sess
.opts
.cg
.profile_use
.clone(), None
),
184 pgo_sample_use
: if_regular
!(sess
.opts
.unstable_opts
.profile_sample_use
.clone(), None
),
185 debug_info_for_profiling
: sess
.opts
.unstable_opts
.debug_info_for_profiling
,
186 instrument_coverage
: if_regular
!(sess
.instrument_coverage(), false),
187 instrument_gcov
: if_regular
!(
188 // compiler_builtins overrides the codegen-units settings,
189 // which is incompatible with -Zprofile which requires that
190 // only a single codegen unit is used per crate.
191 sess
.opts
.unstable_opts
.profile
&& !is_compiler_builtins
,
195 sanitizer
: if_regular
!(sess
.opts
.unstable_opts
.sanitizer
, SanitizerSet
::empty()),
196 sanitizer_recover
: if_regular
!(
197 sess
.opts
.unstable_opts
.sanitizer_recover
,
198 SanitizerSet
::empty()
200 sanitizer_memory_track_origins
: if_regular
!(
201 sess
.opts
.unstable_opts
.sanitizer_memory_track_origins
,
205 emit_pre_lto_bc
: if_regular
!(
206 save_temps
|| need_pre_lto_bitcode_for_incr_comp(sess
),
209 emit_no_opt_bc
: if_regular
!(save_temps
, false),
210 emit_bc
: if_regular
!(
211 save_temps
|| sess
.opts
.output_types
.contains_key(&OutputType
::Bitcode
),
214 emit_ir
: if_regular
!(
215 sess
.opts
.output_types
.contains_key(&OutputType
::LlvmAssembly
),
218 emit_asm
: if_regular
!(
219 sess
.opts
.output_types
.contains_key(&OutputType
::Assembly
),
223 emit_thin_lto
: sess
.opts
.unstable_opts
.emit_thin_lto
,
224 bc_cmdline
: sess
.target
.bitcode_llvm_cmdline
.to_string(),
226 verify_llvm_ir
: sess
.verify_llvm_ir(),
227 no_prepopulate_passes
: sess
.opts
.cg
.no_prepopulate_passes
,
228 no_builtins
: no_builtins
|| sess
.target
.no_builtins
,
230 // Exclude metadata and allocator modules from time_passes output,
231 // since they throw off the "LLVM passes" measurement.
232 time_module
: if_regular
!(true, false),
234 // Copy what clang does by turning on loop vectorization at O2 and
235 // slp vectorization at O3.
236 vectorize_loop
: !sess
.opts
.cg
.no_vectorize_loops
237 && (sess
.opts
.optimize
== config
::OptLevel
::Default
238 || sess
.opts
.optimize
== config
::OptLevel
::Aggressive
),
239 vectorize_slp
: !sess
.opts
.cg
.no_vectorize_slp
240 && sess
.opts
.optimize
== config
::OptLevel
::Aggressive
,
242 // Some targets (namely, NVPTX) interact badly with the
243 // MergeFunctions pass. This is because MergeFunctions can generate
244 // new function calls which may interfere with the target calling
245 // convention; e.g. for the NVPTX target, PTX kernels should not
246 // call other PTX kernels. MergeFunctions can also be configured to
247 // generate aliases instead, but aliases are not supported by some
248 // backends (again, NVPTX). Therefore, allow targets to opt out of
249 // the MergeFunctions pass, but otherwise keep the pass enabled (at
250 // O2 and O3) since it can be useful for reducing code size.
251 merge_functions
: match sess
255 .unwrap_or(sess
.target
.merge_functions
)
257 MergeFunctions
::Disabled
=> false,
258 MergeFunctions
::Trampolines
| MergeFunctions
::Aliases
=> {
259 use config
::OptLevel
::*;
260 match sess
.opts
.optimize
{
261 Aggressive
| Default
| SizeMin
| Size
=> true,
267 inline_threshold
: sess
.opts
.cg
.inline_threshold
,
268 new_llvm_pass_manager
: sess
.opts
.unstable_opts
.new_llvm_pass_manager
,
269 emit_lifetime_markers
: sess
.emit_lifetime_markers(),
270 llvm_plugins
: if_regular
!(sess
.opts
.unstable_opts
.llvm_plugins
.clone(), vec
![]),
274 pub fn bitcode_needed(&self) -> bool
{
276 || self.emit_obj
== EmitObj
::Bitcode
277 || self.emit_obj
== EmitObj
::ObjectCode(BitcodeSection
::Full
)
281 /// Configuration passed to the function returned by the `target_machine_factory`.
282 pub struct TargetMachineFactoryConfig
{
283 /// Split DWARF is enabled in LLVM by checking that `TM.MCOptions.SplitDwarfFile` isn't empty,
284 /// so the path to the dwarf object has to be provided when we create the target machine.
285 /// This can be ignored by backends which do not need it for their Split DWARF support.
286 pub split_dwarf_file
: Option
<PathBuf
>,
289 impl TargetMachineFactoryConfig
{
291 cgcx
: &CodegenContext
<impl WriteBackendMethods
>,
293 ) -> TargetMachineFactoryConfig
{
294 let split_dwarf_file
= if cgcx
.target_can_use_split_dwarf
{
295 cgcx
.output_filenames
.split_dwarf_path(
296 cgcx
.split_debuginfo
,
297 cgcx
.split_dwarf_kind
,
303 TargetMachineFactoryConfig { split_dwarf_file }
307 pub type TargetMachineFactoryFn
<B
> = Arc
<
308 dyn Fn(TargetMachineFactoryConfig
) -> Result
<<B
as WriteBackendMethods
>::TargetMachine
, String
>
313 pub type ExportedSymbols
= FxHashMap
<CrateNum
, Arc
<Vec
<(String
, SymbolExportInfo
)>>>;
315 /// Additional resources used by optimize_and_codegen (not module specific)
317 pub struct CodegenContext
<B
: WriteBackendMethods
> {
318 // Resources needed when running LTO
320 pub prof
: SelfProfilerRef
,
322 pub save_temps
: bool
,
323 pub fewer_names
: bool
,
324 pub time_trace
: bool
,
325 pub exported_symbols
: Option
<Arc
<ExportedSymbols
>>,
326 pub opts
: Arc
<config
::Options
>,
327 pub crate_types
: Vec
<CrateType
>,
328 pub each_linked_rlib_for_lto
: Vec
<(CrateNum
, PathBuf
)>,
329 pub output_filenames
: Arc
<OutputFilenames
>,
330 pub regular_module_config
: Arc
<ModuleConfig
>,
331 pub metadata_module_config
: Arc
<ModuleConfig
>,
332 pub allocator_module_config
: Arc
<ModuleConfig
>,
333 pub tm_factory
: TargetMachineFactoryFn
<B
>,
334 pub msvc_imps_needed
: bool
,
335 pub is_pe_coff
: bool
,
336 pub target_can_use_split_dwarf
: bool
,
337 pub target_pointer_width
: u32,
338 pub target_arch
: String
,
339 pub debuginfo
: config
::DebugInfo
,
340 pub split_debuginfo
: rustc_target
::spec
::SplitDebuginfo
,
341 pub split_dwarf_kind
: rustc_session
::config
::SplitDwarfKind
,
343 // Number of cgus excluding the allocator/metadata modules
344 pub total_cgus
: usize,
345 // Handler to use for diagnostics produced during codegen.
346 pub diag_emitter
: SharedEmitter
,
347 // LLVM optimizations for which we want to print remarks.
349 // Worker thread number
351 // The incremental compilation session directory, or None if we are not
352 // compiling incrementally
353 pub incr_comp_session_dir
: Option
<PathBuf
>,
354 // Used to update CGU re-use information during the thinlto phase.
355 pub cgu_reuse_tracker
: CguReuseTracker
,
356 // Channel back to the main control thread to send messages to
357 pub coordinator_send
: Sender
<Box
<dyn Any
+ Send
>>,
360 impl<B
: WriteBackendMethods
> CodegenContext
<B
> {
361 pub fn create_diag_handler(&self) -> Handler
{
362 Handler
::with_emitter(true, None
, Box
::new(self.diag_emitter
.clone()))
365 pub fn config(&self, kind
: ModuleKind
) -> &ModuleConfig
{
367 ModuleKind
::Regular
=> &self.regular_module_config
,
368 ModuleKind
::Metadata
=> &self.metadata_module_config
,
369 ModuleKind
::Allocator
=> &self.allocator_module_config
,
374 fn generate_lto_work
<B
: ExtraBackendMethods
>(
375 cgcx
: &CodegenContext
<B
>,
376 needs_fat_lto
: Vec
<FatLTOInput
<B
>>,
377 needs_thin_lto
: Vec
<(String
, B
::ThinBuffer
)>,
378 import_only_modules
: Vec
<(SerializedModule
<B
::ModuleBuffer
>, WorkProduct
)>,
379 ) -> Vec
<(WorkItem
<B
>, u64)> {
380 let _prof_timer
= cgcx
.prof
.generic_activity("codegen_generate_lto_work");
382 let (lto_modules
, copy_jobs
) = if !needs_fat_lto
.is_empty() {
383 assert
!(needs_thin_lto
.is_empty());
385 B
::run_fat_lto(cgcx
, needs_fat_lto
, import_only_modules
).unwrap_or_else(|e
| e
.raise());
386 (vec
![lto_module
], vec
![])
388 assert
!(needs_fat_lto
.is_empty());
389 B
::run_thin_lto(cgcx
, needs_thin_lto
, import_only_modules
).unwrap_or_else(|e
| e
.raise())
395 let cost
= module
.cost();
396 (WorkItem
::LTO(module
), cost
)
398 .chain(copy_jobs
.into_iter().map(|wp
| {
400 WorkItem
::CopyPostLtoArtifacts(CachedModuleCodegen
{
401 name
: wp
.cgu_name
.clone(),
410 pub struct CompiledModules
{
411 pub modules
: Vec
<CompiledModule
>,
412 pub allocator_module
: Option
<CompiledModule
>,
415 fn need_bitcode_in_object(sess
: &Session
) -> bool
{
416 let requested_for_rlib
= sess
.opts
.cg
.embed_bitcode
417 && sess
.crate_types().contains(&CrateType
::Rlib
)
418 && sess
.opts
.output_types
.contains_key(&OutputType
::Exe
);
419 let forced_by_target
= sess
.target
.forces_embed_bitcode
;
420 requested_for_rlib
|| forced_by_target
423 fn need_pre_lto_bitcode_for_incr_comp(sess
: &Session
) -> bool
{
424 if sess
.opts
.incremental
.is_none() {
430 Lto
::Fat
| Lto
::Thin
| Lto
::ThinLocal
=> true,
434 pub fn start_async_codegen
<B
: ExtraBackendMethods
>(
438 metadata
: EncodedMetadata
,
439 metadata_module
: Option
<CompiledModule
>,
441 ) -> OngoingCodegen
<B
> {
442 let (coordinator_send
, coordinator_receive
) = channel();
445 let crate_attrs
= tcx
.hir().attrs(rustc_hir
::CRATE_HIR_ID
);
446 let no_builtins
= tcx
.sess
.contains_name(crate_attrs
, sym
::no_builtins
);
447 let is_compiler_builtins
= tcx
.sess
.contains_name(crate_attrs
, sym
::compiler_builtins
);
449 let crate_info
= CrateInfo
::new(tcx
, target_cpu
);
452 ModuleConfig
::new(ModuleKind
::Regular
, sess
, no_builtins
, is_compiler_builtins
);
453 let metadata_config
=
454 ModuleConfig
::new(ModuleKind
::Metadata
, sess
, no_builtins
, is_compiler_builtins
);
455 let allocator_config
=
456 ModuleConfig
::new(ModuleKind
::Allocator
, sess
, no_builtins
, is_compiler_builtins
);
458 let (shared_emitter
, shared_emitter_main
) = SharedEmitter
::new();
459 let (codegen_worker_send
, codegen_worker_receive
) = channel();
461 let coordinator_thread
= start_executing_work(
469 sess
.jobserver
.clone(),
470 Arc
::new(regular_config
),
471 Arc
::new(metadata_config
),
472 Arc
::new(allocator_config
),
473 coordinator_send
.clone(),
482 codegen_worker_receive
,
484 coordinator
: Coordinator
{
485 sender
: coordinator_send
,
486 future
: Some(coordinator_thread
),
487 phantom
: PhantomData
,
489 output_filenames
: tcx
.output_filenames(()).clone(),
493 fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
495 compiled_modules
: &CompiledModules
,
496 ) -> FxHashMap
<WorkProductId
, WorkProduct
> {
497 let mut work_products
= FxHashMap
::default();
499 if sess
.opts
.incremental
.is_none() {
500 return work_products
;
503 let _timer
= sess
.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir");
505 for module
in compiled_modules
.modules
.iter().filter(|m
| m
.kind
== ModuleKind
::Regular
) {
506 let mut files
= Vec
::new();
507 if let Some(object_file_path
) = &module
.object
{
508 files
.push(("o", object_file_path
.as_path()));
510 if let Some(dwarf_object_file_path
) = &module
.dwarf_object
{
511 files
.push(("dwo", dwarf_object_file_path
.as_path()));
514 if let Some((id
, product
)) =
515 copy_cgu_workproduct_to_incr_comp_cache_dir(sess
, &module
.name
, files
.as_slice())
517 work_products
.insert(id
, product
);
524 fn produce_final_output_artifacts(
526 compiled_modules
: &CompiledModules
,
527 crate_output
: &OutputFilenames
,
529 let mut user_wants_bitcode
= false;
530 let mut user_wants_objects
= false;
532 // Produce final compile outputs.
533 let copy_gracefully
= |from
: &Path
, to
: &Path
| {
534 if let Err(e
) = fs
::copy(from
, to
) {
535 sess
.err(&format
!("could not copy {:?} to {:?}: {}", from
, to
, e
));
539 let copy_if_one_unit
= |output_type
: OutputType
, keep_numbered
: bool
| {
540 if compiled_modules
.modules
.len() == 1 {
541 // 1) Only one codegen unit. In this case it's no difficulty
542 // to copy `foo.0.x` to `foo.x`.
543 let module_name
= Some(&compiled_modules
.modules
[0].name
[..]);
544 let path
= crate_output
.temp_path(output_type
, module_name
);
545 copy_gracefully(&path
, &crate_output
.path(output_type
));
546 if !sess
.opts
.cg
.save_temps
&& !keep_numbered
{
547 // The user just wants `foo.x`, not `foo.#module-name#.x`.
548 ensure_removed(sess
.diagnostic(), &path
);
551 let ext
= crate_output
552 .temp_path(output_type
, None
)
559 if crate_output
.outputs
.contains_key(&output_type
) {
560 // 2) Multiple codegen units, with `--emit foo=some_name`. We have
561 // no good solution for this case, so warn the user.
563 "ignoring emit path because multiple .{} files \
567 } else if crate_output
.single_output_file
.is_some() {
568 // 3) Multiple codegen units, with `-o some_name`. We have
569 // no good solution for this case, so warn the user.
571 "ignoring -o because multiple .{} files \
576 // 4) Multiple codegen units, but no explicit name. We
577 // just leave the `foo.0.x` files in place.
578 // (We don't have to do any work in this case.)
583 // Flag to indicate whether the user explicitly requested bitcode.
584 // Otherwise, we produced it only as a temporary output, and will need
586 for output_type
in crate_output
.outputs
.keys() {
588 OutputType
::Bitcode
=> {
589 user_wants_bitcode
= true;
590 // Copy to .bc, but always keep the .0.bc. There is a later
591 // check to figure out if we should delete .0.bc files, or keep
592 // them for making an rlib.
593 copy_if_one_unit(OutputType
::Bitcode
, true);
595 OutputType
::LlvmAssembly
=> {
596 copy_if_one_unit(OutputType
::LlvmAssembly
, false);
598 OutputType
::Assembly
=> {
599 copy_if_one_unit(OutputType
::Assembly
, false);
601 OutputType
::Object
=> {
602 user_wants_objects
= true;
603 copy_if_one_unit(OutputType
::Object
, true);
605 OutputType
::Mir
| OutputType
::Metadata
| OutputType
::Exe
| OutputType
::DepInfo
=> {}
609 // Clean up unwanted temporary files.
611 // We create the following files by default:
612 // - #crate#.#module-name#.bc
613 // - #crate#.#module-name#.o
614 // - #crate#.crate.metadata.bc
615 // - #crate#.crate.metadata.o
616 // - #crate#.o (linked from crate.##.o)
617 // - #crate#.bc (copied from crate.##.bc)
618 // We may create additional files if requested by the user (through
619 // `-C save-temps` or `--emit=` flags).
621 if !sess
.opts
.cg
.save_temps
{
622 // Remove the temporary .#module-name#.o objects. If the user didn't
623 // explicitly request bitcode (with --emit=bc), and the bitcode is not
624 // needed for building an rlib, then we must remove .#module-name#.bc as
627 // Specific rules for keeping .#module-name#.bc:
628 // - If the user requested bitcode (`user_wants_bitcode`), and
629 // codegen_units > 1, then keep it.
630 // - If the user requested bitcode but codegen_units == 1, then we
631 // can toss .#module-name#.bc because we copied it to .bc earlier.
632 // - If we're not building an rlib and the user didn't request
633 // bitcode, then delete .#module-name#.bc.
634 // If you change how this works, also update back::link::link_rlib,
635 // where .#module-name#.bc files are (maybe) deleted after making an
637 let needs_crate_object
= crate_output
.outputs
.contains_key(&OutputType
::Exe
);
639 let keep_numbered_bitcode
= user_wants_bitcode
&& sess
.codegen_units() > 1;
641 let keep_numbered_objects
=
642 needs_crate_object
|| (user_wants_objects
&& sess
.codegen_units() > 1);
644 for module
in compiled_modules
.modules
.iter() {
645 if let Some(ref path
) = module
.object
{
646 if !keep_numbered_objects
{
647 ensure_removed(sess
.diagnostic(), path
);
651 if let Some(ref path
) = module
.dwarf_object
{
652 if !keep_numbered_objects
{
653 ensure_removed(sess
.diagnostic(), path
);
657 if let Some(ref path
) = module
.bytecode
{
658 if !keep_numbered_bitcode
{
659 ensure_removed(sess
.diagnostic(), path
);
664 if !user_wants_bitcode
{
665 if let Some(ref allocator_module
) = compiled_modules
.allocator_module
{
666 if let Some(ref path
) = allocator_module
.bytecode
{
667 ensure_removed(sess
.diagnostic(), path
);
673 // We leave the following files around by default:
675 // - #crate#.crate.metadata.o
677 // These are used in linking steps and will be cleaned up afterward.
680 pub enum WorkItem
<B
: WriteBackendMethods
> {
681 /// Optimize a newly codegened, totally unoptimized module.
682 Optimize(ModuleCodegen
<B
::Module
>),
683 /// Copy the post-LTO artifacts from the incremental cache to the output
685 CopyPostLtoArtifacts(CachedModuleCodegen
),
686 /// Performs (Thin)LTO on the given module.
687 LTO(lto
::LtoModuleCodegen
<B
>),
690 impl<B
: WriteBackendMethods
> WorkItem
<B
> {
691 pub fn module_kind(&self) -> ModuleKind
{
693 WorkItem
::Optimize(ref m
) => m
.kind
,
694 WorkItem
::CopyPostLtoArtifacts(_
) | WorkItem
::LTO(_
) => ModuleKind
::Regular
,
698 fn start_profiling
<'a
>(&self, cgcx
: &'a CodegenContext
<B
>) -> TimingGuard
<'a
> {
700 WorkItem
::Optimize(ref m
) => {
701 cgcx
.prof
.generic_activity_with_arg("codegen_module_optimize", &*m
.name
)
703 WorkItem
::CopyPostLtoArtifacts(ref m
) => cgcx
705 .generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &*m
.name
),
706 WorkItem
::LTO(ref m
) => {
707 cgcx
.prof
.generic_activity_with_arg("codegen_module_perform_lto", m
.name())
712 /// Generate a short description of this work item suitable for use as a thread name.
713 fn short_description(&self) -> String
{
714 // `pthread_setname()` on *nix is limited to 15 characters and longer names are ignored.
715 // Use very short descriptions in this case to maximize the space available for the module name.
716 // Windows does not have that limitation so use slightly more descriptive names there.
718 WorkItem
::Optimize(m
) => {
720 return format
!("optimize module {}", m
.name
);
722 return format
!("opt {}", m
.name
);
724 WorkItem
::CopyPostLtoArtifacts(m
) => {
726 return format
!("copy LTO artifacts for {}", m
.name
);
728 return format
!("copy {}", m
.name
);
730 WorkItem
::LTO(m
) => {
732 return format
!("LTO module {}", m
.name());
734 return format
!("LTO {}", m
.name());
740 enum WorkItemResult
<B
: WriteBackendMethods
> {
741 Compiled(CompiledModule
),
742 NeedsLink(ModuleCodegen
<B
::Module
>),
743 NeedsFatLTO(FatLTOInput
<B
>),
744 NeedsThinLTO(String
, B
::ThinBuffer
),
747 pub enum FatLTOInput
<B
: WriteBackendMethods
> {
748 Serialized { name: String, buffer: B::ModuleBuffer }
,
749 InMemory(ModuleCodegen
<B
::Module
>),
752 fn execute_work_item
<B
: ExtraBackendMethods
>(
753 cgcx
: &CodegenContext
<B
>,
754 work_item
: WorkItem
<B
>,
755 ) -> Result
<WorkItemResult
<B
>, FatalError
> {
756 let module_config
= cgcx
.config(work_item
.module_kind());
759 WorkItem
::Optimize(module
) => execute_optimize_work_item(cgcx
, module
, module_config
),
760 WorkItem
::CopyPostLtoArtifacts(module
) => {
761 Ok(execute_copy_from_cache_work_item(cgcx
, module
, module_config
))
763 WorkItem
::LTO(module
) => execute_lto_work_item(cgcx
, module
, module_config
),
767 // Actual LTO type we end up choosing based on multiple factors.
768 pub enum ComputedLtoType
{
774 pub fn compute_per_cgu_lto_type(
776 opts
: &config
::Options
,
777 sess_crate_types
: &[CrateType
],
778 module_kind
: ModuleKind
,
779 ) -> ComputedLtoType
{
780 // Metadata modules never participate in LTO regardless of the lto
782 if module_kind
== ModuleKind
::Metadata
{
783 return ComputedLtoType
::No
;
786 // If the linker does LTO, we don't have to do it. Note that we
787 // keep doing full LTO, if it is requested, as not to break the
788 // assumption that the output will be a single module.
789 let linker_does_lto
= opts
.cg
.linker_plugin_lto
.enabled();
791 // When we're automatically doing ThinLTO for multi-codegen-unit
792 // builds we don't actually want to LTO the allocator modules if
793 // it shows up. This is due to various linker shenanigans that
794 // we'll encounter later.
795 let is_allocator
= module_kind
== ModuleKind
::Allocator
;
797 // We ignore a request for full crate graph LTO if the crate type
798 // is only an rlib, as there is no full crate graph to process,
799 // that'll happen later.
801 // This use case currently comes up primarily for targets that
802 // require LTO so the request for LTO is always unconditionally
803 // passed down to the backend, but we don't actually want to do
804 // anything about it yet until we've got a final product.
805 let is_rlib
= sess_crate_types
.len() == 1 && sess_crate_types
[0] == CrateType
::Rlib
;
808 Lto
::ThinLocal
if !linker_does_lto
&& !is_allocator
=> ComputedLtoType
::Thin
,
809 Lto
::Thin
if !linker_does_lto
&& !is_rlib
=> ComputedLtoType
::Thin
,
810 Lto
::Fat
if !is_rlib
=> ComputedLtoType
::Fat
,
811 _
=> ComputedLtoType
::No
,
815 fn execute_optimize_work_item
<B
: ExtraBackendMethods
>(
816 cgcx
: &CodegenContext
<B
>,
817 module
: ModuleCodegen
<B
::Module
>,
818 module_config
: &ModuleConfig
,
819 ) -> Result
<WorkItemResult
<B
>, FatalError
> {
820 let diag_handler
= cgcx
.create_diag_handler();
823 B
::optimize(cgcx
, &diag_handler
, &module
, module_config
)?
;
826 // After we've done the initial round of optimizations we need to
827 // decide whether to synchronously codegen this module or ship it
828 // back to the coordinator thread for further LTO processing (which
829 // has to wait for all the initial modules to be optimized).
831 let lto_type
= compute_per_cgu_lto_type(&cgcx
.lto
, &cgcx
.opts
, &cgcx
.crate_types
, module
.kind
);
833 // If we're doing some form of incremental LTO then we need to be sure to
834 // save our module to disk first.
835 let bitcode
= if cgcx
.config(module
.kind
).emit_pre_lto_bc
{
836 let filename
= pre_lto_bitcode_filename(&module
.name
);
837 cgcx
.incr_comp_session_dir
.as_ref().map(|path
| path
.join(&filename
))
843 ComputedLtoType
::No
=> finish_intra_module_work(cgcx
, module
, module_config
),
844 ComputedLtoType
::Thin
=> {
845 let (name
, thin_buffer
) = B
::prepare_thin(module
);
846 if let Some(path
) = bitcode
{
847 fs
::write(&path
, thin_buffer
.data()).unwrap_or_else(|e
| {
848 panic
!("Error writing pre-lto-bitcode file `{}`: {}", path
.display(), e
);
851 Ok(WorkItemResult
::NeedsThinLTO(name
, thin_buffer
))
853 ComputedLtoType
::Fat
=> match bitcode
{
855 let (name
, buffer
) = B
::serialize_module(module
);
856 fs
::write(&path
, buffer
.data()).unwrap_or_else(|e
| {
857 panic
!("Error writing pre-lto-bitcode file `{}`: {}", path
.display(), e
);
859 Ok(WorkItemResult
::NeedsFatLTO(FatLTOInput
::Serialized { name, buffer }
))
861 None
=> Ok(WorkItemResult
::NeedsFatLTO(FatLTOInput
::InMemory(module
))),
866 fn execute_copy_from_cache_work_item
<B
: ExtraBackendMethods
>(
867 cgcx
: &CodegenContext
<B
>,
868 module
: CachedModuleCodegen
,
869 module_config
: &ModuleConfig
,
870 ) -> WorkItemResult
<B
> {
871 assert
!(module_config
.emit_obj
!= EmitObj
::None
);
873 let incr_comp_session_dir
= cgcx
.incr_comp_session_dir
.as_ref().unwrap();
875 let load_from_incr_comp_dir
= |output_path
: PathBuf
, saved_path
: &str| {
876 let source_file
= in_incr_comp_dir(&incr_comp_session_dir
, saved_path
);
878 "copying pre-existing module `{}` from {:?} to {}",
881 output_path
.display()
883 match link_or_copy(&source_file
, &output_path
) {
884 Ok(_
) => Some(output_path
),
886 let diag_handler
= cgcx
.create_diag_handler();
887 diag_handler
.err(&format
!(
888 "unable to copy {} to {}: {}",
889 source_file
.display(),
890 output_path
.display(),
898 let object
= load_from_incr_comp_dir(
899 cgcx
.output_filenames
.temp_path(OutputType
::Object
, Some(&module
.name
)),
900 &module
.source
.saved_files
.get("o").expect("no saved object file in work product"),
903 module
.source
.saved_files
.get("dwo").as_ref().and_then(|saved_dwarf_object_file
| {
904 let dwarf_obj_out
= cgcx
906 .split_dwarf_path(cgcx
.split_debuginfo
, cgcx
.split_dwarf_kind
, Some(&module
.name
))
908 "saved dwarf object in work product but `split_dwarf_path` returned `None`",
910 load_from_incr_comp_dir(dwarf_obj_out
, &saved_dwarf_object_file
)
913 WorkItemResult
::Compiled(CompiledModule
{
915 kind
: ModuleKind
::Regular
,
922 fn execute_lto_work_item
<B
: ExtraBackendMethods
>(
923 cgcx
: &CodegenContext
<B
>,
924 module
: lto
::LtoModuleCodegen
<B
>,
925 module_config
: &ModuleConfig
,
926 ) -> Result
<WorkItemResult
<B
>, FatalError
> {
927 let module
= unsafe { module.optimize(cgcx)? }
;
928 finish_intra_module_work(cgcx
, module
, module_config
)
931 fn finish_intra_module_work
<B
: ExtraBackendMethods
>(
932 cgcx
: &CodegenContext
<B
>,
933 module
: ModuleCodegen
<B
::Module
>,
934 module_config
: &ModuleConfig
,
935 ) -> Result
<WorkItemResult
<B
>, FatalError
> {
936 let diag_handler
= cgcx
.create_diag_handler();
938 if !cgcx
.opts
.unstable_opts
.combine_cgu
939 || module
.kind
== ModuleKind
::Metadata
940 || module
.kind
== ModuleKind
::Allocator
942 let module
= unsafe { B::codegen(cgcx, &diag_handler, module, module_config)? }
;
943 Ok(WorkItemResult
::Compiled(module
))
945 Ok(WorkItemResult
::NeedsLink(module
))
949 pub enum Message
<B
: WriteBackendMethods
> {
950 Token(io
::Result
<Acquired
>),
952 result
: FatLTOInput
<B
>,
957 thin_buffer
: B
::ThinBuffer
,
961 module
: ModuleCodegen
<B
::Module
>,
965 result
: Result
<CompiledModule
, Option
<WorkerFatalError
>>,
969 llvm_work_item
: WorkItem
<B
>,
972 AddImportOnlyModule
{
973 module_data
: SerializedModule
<B
::ModuleBuffer
>,
974 work_product
: WorkProduct
,
983 code
: Option
<DiagnosticId
>,
987 #[derive(PartialEq, Clone, Copy, Debug)]
988 enum MainThreadWorkerState
{
994 fn start_executing_work
<B
: ExtraBackendMethods
>(
997 crate_info
: &CrateInfo
,
998 shared_emitter
: SharedEmitter
,
999 codegen_worker_send
: Sender
<Message
<B
>>,
1000 coordinator_receive
: Receiver
<Box
<dyn Any
+ Send
>>,
1003 regular_config
: Arc
<ModuleConfig
>,
1004 metadata_config
: Arc
<ModuleConfig
>,
1005 allocator_config
: Arc
<ModuleConfig
>,
1006 tx_to_llvm_workers
: Sender
<Box
<dyn Any
+ Send
>>,
1007 ) -> thread
::JoinHandle
<Result
<CompiledModules
, ()>> {
1008 let coordinator_send
= tx_to_llvm_workers
;
1009 let sess
= tcx
.sess
;
1011 // Compute the set of symbols we need to retain when doing LTO (if we need to)
1012 let exported_symbols
= {
1013 let mut exported_symbols
= FxHashMap
::default();
1015 let copy_symbols
= |cnum
| {
1017 .exported_symbols(cnum
)
1019 .map(|&(s
, lvl
)| (symbol_name_for_instance_in_crate(tcx
, s
, cnum
), lvl
))
1027 exported_symbols
.insert(LOCAL_CRATE
, copy_symbols(LOCAL_CRATE
));
1028 Some(Arc
::new(exported_symbols
))
1030 Lto
::Fat
| Lto
::Thin
=> {
1031 exported_symbols
.insert(LOCAL_CRATE
, copy_symbols(LOCAL_CRATE
));
1032 for &cnum
in tcx
.crates(()).iter() {
1033 exported_symbols
.insert(cnum
, copy_symbols(cnum
));
1035 Some(Arc
::new(exported_symbols
))
1040 // First up, convert our jobserver into a helper thread so we can use normal
1041 // mpsc channels to manage our messages and such.
1042 // After we've requested tokens then we'll, when we can,
1043 // get tokens on `coordinator_receive` which will
1044 // get managed in the main loop below.
1045 let coordinator_send2
= coordinator_send
.clone();
1046 let helper
= jobserver
1047 .into_helper_thread(move |token
| {
1048 drop(coordinator_send2
.send(Box
::new(Message
::Token
::<B
>(token
))));
1050 .expect("failed to spawn helper thread");
1052 let mut each_linked_rlib_for_lto
= Vec
::new();
1053 drop(link
::each_linked_rlib(crate_info
, &mut |cnum
, path
| {
1054 if link
::ignored_for_lto(sess
, crate_info
, cnum
) {
1057 each_linked_rlib_for_lto
.push((cnum
, path
.to_path_buf()));
1061 if tcx
.sess
.opts
.unstable_opts
.no_codegen
|| !tcx
.sess
.opts
.output_types
.should_codegen() {
1062 // If we know that we won’t be doing codegen, create target machines without optimisation.
1063 config
::OptLevel
::No
1065 tcx
.backend_optimization_level(())
1067 let backend_features
= tcx
.global_backend_features(());
1068 let cgcx
= CodegenContext
::<B
> {
1069 backend
: backend
.clone(),
1070 crate_types
: sess
.crate_types().to_vec(),
1071 each_linked_rlib_for_lto
,
1073 fewer_names
: sess
.fewer_names(),
1074 save_temps
: sess
.opts
.cg
.save_temps
,
1075 time_trace
: sess
.opts
.unstable_opts
.llvm_time_trace
,
1076 opts
: Arc
::new(sess
.opts
.clone()),
1077 prof
: sess
.prof
.clone(),
1079 remark
: sess
.opts
.cg
.remark
.clone(),
1081 incr_comp_session_dir
: sess
.incr_comp_session_dir_opt().map(|r
| r
.clone()),
1082 cgu_reuse_tracker
: sess
.cgu_reuse_tracker
.clone(),
1084 diag_emitter
: shared_emitter
.clone(),
1085 output_filenames
: tcx
.output_filenames(()).clone(),
1086 regular_module_config
: regular_config
,
1087 metadata_module_config
: metadata_config
,
1088 allocator_module_config
: allocator_config
,
1089 tm_factory
: backend
.target_machine_factory(tcx
.sess
, ol
, backend_features
),
1091 msvc_imps_needed
: msvc_imps_needed(tcx
),
1092 is_pe_coff
: tcx
.sess
.target
.is_like_windows
,
1093 target_can_use_split_dwarf
: tcx
.sess
.target_can_use_split_dwarf(),
1094 target_pointer_width
: tcx
.sess
.target
.pointer_width
,
1095 target_arch
: tcx
.sess
.target
.arch
.to_string(),
1096 debuginfo
: tcx
.sess
.opts
.debuginfo
,
1097 split_debuginfo
: tcx
.sess
.split_debuginfo(),
1098 split_dwarf_kind
: tcx
.sess
.opts
.unstable_opts
.split_dwarf_kind
,
1101 // This is the "main loop" of parallel work happening for parallel codegen.
1102 // It's here that we manage parallelism, schedule work, and work with
1103 // messages coming from clients.
1105 // There are a few environmental pre-conditions that shape how the system
1108 // - Error reporting only can happen on the main thread because that's the
1109 // only place where we have access to the compiler `Session`.
1110 // - LLVM work can be done on any thread.
1111 // - Codegen can only happen on the main thread.
1112 // - Each thread doing substantial work must be in possession of a `Token`
1113 // from the `Jobserver`.
1114 // - The compiler process always holds one `Token`. Any additional `Tokens`
1115 // have to be requested from the `Jobserver`.
1119 // The error reporting restriction is handled separately from the rest: We
1120 // set up a `SharedEmitter` the holds an open channel to the main thread.
1121 // When an error occurs on any thread, the shared emitter will send the
1122 // error message to the receiver main thread (`SharedEmitterMain`). The
1123 // main thread will periodically query this error message queue and emit
1124 // any error messages it has received. It might even abort compilation if
1125 // has received a fatal error. In this case we rely on all other threads
1126 // being torn down automatically with the main thread.
1127 // Since the main thread will often be busy doing codegen work, error
1128 // reporting will be somewhat delayed, since the message queue can only be
1129 // checked in between to work packages.
1131 // Work Processing Infrastructure
1132 // ==============================
1133 // The work processing infrastructure knows three major actors:
1135 // - the coordinator thread,
1136 // - the main thread, and
1137 // - LLVM worker threads
1139 // The coordinator thread is running a message loop. It instructs the main
1140 // thread about what work to do when, and it will spawn off LLVM worker
1141 // threads as open LLVM WorkItems become available.
1143 // The job of the main thread is to codegen CGUs into LLVM work package
1144 // (since the main thread is the only thread that can do this). The main
1145 // thread will block until it receives a message from the coordinator, upon
1146 // which it will codegen one CGU, send it to the coordinator and block
1147 // again. This way the coordinator can control what the main thread is
1150 // The coordinator keeps a queue of LLVM WorkItems, and when a `Token` is
1151 // available, it will spawn off a new LLVM worker thread and let it process
1152 // that a WorkItem. When a LLVM worker thread is done with its WorkItem,
1153 // it will just shut down, which also frees all resources associated with
1154 // the given LLVM module, and sends a message to the coordinator that the
1155 // has been completed.
1159 // The scheduler's goal is to minimize the time it takes to complete all
1160 // work there is, however, we also want to keep memory consumption low
1161 // if possible. These two goals are at odds with each other: If memory
1162 // consumption were not an issue, we could just let the main thread produce
1163 // LLVM WorkItems at full speed, assuring maximal utilization of
1164 // Tokens/LLVM worker threads. However, since codegen is usually faster
1165 // than LLVM processing, the queue of LLVM WorkItems would fill up and each
1166 // WorkItem potentially holds on to a substantial amount of memory.
1168 // So the actual goal is to always produce just enough LLVM WorkItems as
1169 // not to starve our LLVM worker threads. That means, once we have enough
1170 // WorkItems in our queue, we can block the main thread, so it does not
1171 // produce more until we need them.
1173 // Doing LLVM Work on the Main Thread
1174 // ----------------------------------
1175 // Since the main thread owns the compiler processes implicit `Token`, it is
1176 // wasteful to keep it blocked without doing any work. Therefore, what we do
1177 // in this case is: We spawn off an additional LLVM worker thread that helps
1178 // reduce the queue. The work it is doing corresponds to the implicit
1179 // `Token`. The coordinator will mark the main thread as being busy with
1180 // LLVM work. (The actual work happens on another OS thread but we just care
1181 // about `Tokens`, not actual threads).
1183 // When any LLVM worker thread finishes while the main thread is marked as
1184 // "busy with LLVM work", we can do a little switcheroo: We give the Token
1185 // of the just finished thread to the LLVM worker thread that is working on
1186 // behalf of the main thread's implicit Token, thus freeing up the main
1187 // thread again. The coordinator can then again decide what the main thread
1188 // should do. This allows the coordinator to make decisions at more points
1191 // Striking a Balance between Throughput and Memory Consumption
1192 // ------------------------------------------------------------
1193 // Since our two goals, (1) use as many Tokens as possible and (2) keep
1194 // memory consumption as low as possible, are in conflict with each other,
1195 // we have to find a trade off between them. Right now, the goal is to keep
1196 // all workers busy, which means that no worker should find the queue empty
1197 // when it is ready to start.
1198 // How do we do achieve this? Good question :) We actually never know how
1199 // many `Tokens` are potentially available so it's hard to say how much to
1200 // fill up the queue before switching the main thread to LLVM work. Also we
1201 // currently don't have a means to estimate how long a running LLVM worker
1202 // will still be busy with it's current WorkItem. However, we know the
1203 // maximal count of available Tokens that makes sense (=the number of CPU
1204 // cores), so we can take a conservative guess. The heuristic we use here
1205 // is implemented in the `queue_full_enough()` function.
1207 // Some Background on Jobservers
1208 // -----------------------------
1209 // It's worth also touching on the management of parallelism here. We don't
1210 // want to just spawn a thread per work item because while that's optimal
1211 // parallelism it may overload a system with too many threads or violate our
1212 // configuration for the maximum amount of cpu to use for this process. To
1213 // manage this we use the `jobserver` crate.
1215 // Job servers are an artifact of GNU make and are used to manage
1216 // parallelism between processes. A jobserver is a glorified IPC semaphore
1217 // basically. Whenever we want to run some work we acquire the semaphore,
1218 // and whenever we're done with that work we release the semaphore. In this
1219 // manner we can ensure that the maximum number of parallel workers is
1220 // capped at any one point in time.
1222 // LTO and the coordinator thread
1223 // ------------------------------
1225 // The final job the coordinator thread is responsible for is managing LTO
1226 // and how that works. When LTO is requested what we'll to is collect all
1227 // optimized LLVM modules into a local vector on the coordinator. Once all
1228 // modules have been codegened and optimized we hand this to the `lto`
1229 // module for further optimization. The `lto` module will return back a list
1230 // of more modules to work on, which the coordinator will continue to spawn
1233 // Each LLVM module is automatically sent back to the coordinator for LTO if
1234 // necessary. There's already optimizations in place to avoid sending work
1235 // back to the coordinator if LTO isn't requested.
1236 return B
::spawn_thread(cgcx
.time_trace
, move || {
1237 let mut worker_id_counter
= 0;
1238 let mut free_worker_ids
= Vec
::new();
1239 let mut get_worker_id
= |free_worker_ids
: &mut Vec
<usize>| {
1240 if let Some(id
) = free_worker_ids
.pop() {
1243 let id
= worker_id_counter
;
1244 worker_id_counter
+= 1;
1249 // This is where we collect codegen units that have gone all the way
1250 // through codegen and LLVM.
1251 let mut compiled_modules
= vec
![];
1252 let mut compiled_allocator_module
= None
;
1253 let mut needs_link
= Vec
::new();
1254 let mut needs_fat_lto
= Vec
::new();
1255 let mut needs_thin_lto
= Vec
::new();
1256 let mut lto_import_only_modules
= Vec
::new();
1257 let mut started_lto
= false;
1258 let mut codegen_aborted
= false;
1260 // This flag tracks whether all items have gone through codegens
1261 let mut codegen_done
= false;
1263 // This is the queue of LLVM work items that still need processing.
1264 let mut work_items
= Vec
::<(WorkItem
<B
>, u64)>::new();
1266 // This are the Jobserver Tokens we currently hold. Does not include
1267 // the implicit Token the compiler process owns no matter what.
1268 let mut tokens
= Vec
::new();
1270 let mut main_thread_worker_state
= MainThreadWorkerState
::Idle
;
1271 let mut running
= 0;
1273 let prof
= &cgcx
.prof
;
1274 let mut llvm_start_time
: Option
<VerboseTimingGuard
<'_
>> = None
;
1276 // Run the message loop while there's still anything that needs message
1277 // processing. Note that as soon as codegen is aborted we simply want to
1278 // wait for all existing work to finish, so many of the conditions here
1279 // only apply if codegen hasn't been aborted as they represent pending
1283 || main_thread_worker_state
== MainThreadWorkerState
::LLVMing
1284 || (!codegen_aborted
1285 && !(work_items
.is_empty()
1286 && needs_fat_lto
.is_empty()
1287 && needs_thin_lto
.is_empty()
1288 && lto_import_only_modules
.is_empty()
1289 && main_thread_worker_state
== MainThreadWorkerState
::Idle
))
1291 // While there are still CGUs to be codegened, the coordinator has
1292 // to decide how to utilize the compiler processes implicit Token:
1293 // For codegenning more CGU or for running them through LLVM.
1295 if main_thread_worker_state
== MainThreadWorkerState
::Idle
{
1296 // Compute the number of workers that will be running once we've taken as many
1297 // items from the work queue as we can, plus one for the main thread. It's not
1298 // critically important that we use this instead of just `running`, but it
1299 // prevents the `queue_full_enough` heuristic from fluctuating just because a
1300 // worker finished up and we decreased the `running` count, even though we're
1301 // just going to increase it right after this when we put a new worker to work.
1302 let extra_tokens
= tokens
.len().checked_sub(running
).unwrap();
1303 let additional_running
= std
::cmp
::min(extra_tokens
, work_items
.len());
1304 let anticipated_running
= running
+ additional_running
+ 1;
1306 if !queue_full_enough(work_items
.len(), anticipated_running
) {
1307 // The queue is not full enough, codegen more items:
1308 if codegen_worker_send
.send(Message
::CodegenItem
).is_err() {
1309 panic
!("Could not send Message::CodegenItem to main thread")
1311 main_thread_worker_state
= MainThreadWorkerState
::Codegenning
;
1313 // The queue is full enough to not let the worker
1314 // threads starve. Use the implicit Token to do some
1317 work_items
.pop().expect("queue empty - queue_full_enough() broken?");
1318 let cgcx
= CodegenContext
{
1319 worker
: get_worker_id(&mut free_worker_ids
),
1322 maybe_start_llvm_timer(
1324 cgcx
.config(item
.module_kind()),
1325 &mut llvm_start_time
,
1327 main_thread_worker_state
= MainThreadWorkerState
::LLVMing
;
1328 spawn_work(cgcx
, item
);
1331 } else if codegen_aborted
{
1332 // don't queue up any more work if codegen was aborted, we're
1333 // just waiting for our existing children to finish
1335 // If we've finished everything related to normal codegen
1336 // then it must be the case that we've got some LTO work to do.
1337 // Perform the serial work here of figuring out what we're
1338 // going to LTO and then push a bunch of work items onto our
1340 if work_items
.is_empty()
1342 && main_thread_worker_state
== MainThreadWorkerState
::Idle
1344 assert
!(!started_lto
);
1347 let needs_fat_lto
= mem
::take(&mut needs_fat_lto
);
1348 let needs_thin_lto
= mem
::take(&mut needs_thin_lto
);
1349 let import_only_modules
= mem
::take(&mut lto_import_only_modules
);
1352 generate_lto_work(&cgcx
, needs_fat_lto
, needs_thin_lto
, import_only_modules
)
1354 let insertion_index
= work_items
1355 .binary_search_by_key(&cost
, |&(_
, cost
)| cost
)
1356 .unwrap_or_else(|e
| e
);
1357 work_items
.insert(insertion_index
, (work
, cost
));
1358 if !cgcx
.opts
.unstable_opts
.no_parallel_llvm
{
1359 helper
.request_token();
1364 // In this branch, we know that everything has been codegened,
1365 // so it's just a matter of determining whether the implicit
1366 // Token is free to use for LLVM work.
1367 match main_thread_worker_state
{
1368 MainThreadWorkerState
::Idle
=> {
1369 if let Some((item
, _
)) = work_items
.pop() {
1370 let cgcx
= CodegenContext
{
1371 worker
: get_worker_id(&mut free_worker_ids
),
1374 maybe_start_llvm_timer(
1376 cgcx
.config(item
.module_kind()),
1377 &mut llvm_start_time
,
1379 main_thread_worker_state
= MainThreadWorkerState
::LLVMing
;
1380 spawn_work(cgcx
, item
);
1382 // There is no unstarted work, so let the main thread
1383 // take over for a running worker. Otherwise the
1384 // implicit token would just go to waste.
1385 // We reduce the `running` counter by one. The
1386 // `tokens.truncate()` below will take care of
1387 // giving the Token back.
1388 debug_assert
!(running
> 0);
1390 main_thread_worker_state
= MainThreadWorkerState
::LLVMing
;
1393 MainThreadWorkerState
::Codegenning
=> bug
!(
1394 "codegen worker should not be codegenning after \
1395 codegen was already completed"
1397 MainThreadWorkerState
::LLVMing
=> {
1398 // Already making good use of that token
1403 // Spin up what work we can, only doing this while we've got available
1404 // parallelism slots and work left to spawn.
1405 while !codegen_aborted
&& !work_items
.is_empty() && running
< tokens
.len() {
1406 let (item
, _
) = work_items
.pop().unwrap();
1408 maybe_start_llvm_timer(prof
, cgcx
.config(item
.module_kind()), &mut llvm_start_time
);
1411 CodegenContext { worker: get_worker_id(&mut free_worker_ids), ..cgcx.clone() }
;
1413 spawn_work(cgcx
, item
);
1417 // Relinquish accidentally acquired extra tokens
1418 tokens
.truncate(running
);
1420 // If a thread exits successfully then we drop a token associated
1421 // with that worker and update our `running` count. We may later
1422 // re-acquire a token to continue running more work. We may also not
1423 // actually drop a token here if the worker was running with an
1424 // "ephemeral token"
1425 let mut free_worker
= |worker_id
| {
1426 if main_thread_worker_state
== MainThreadWorkerState
::LLVMing
{
1427 main_thread_worker_state
= MainThreadWorkerState
::Idle
;
1432 free_worker_ids
.push(worker_id
);
1435 let msg
= coordinator_receive
.recv().unwrap();
1436 match *msg
.downcast
::<Message
<B
>>().ok().unwrap() {
1437 // Save the token locally and the next turn of the loop will use
1438 // this to spawn a new unit of work, or it may get dropped
1439 // immediately if we have no more work to spawn.
1440 Message
::Token(token
) => {
1445 if main_thread_worker_state
== MainThreadWorkerState
::LLVMing
{
1446 // If the main thread token is used for LLVM work
1447 // at the moment, we turn that thread into a regular
1448 // LLVM worker thread, so the main thread is free
1449 // to react to codegen demand.
1450 main_thread_worker_state
= MainThreadWorkerState
::Idle
;
1455 let msg
= &format
!("failed to acquire jobserver token: {}", e
);
1456 shared_emitter
.fatal(msg
);
1457 // Exit the coordinator thread
1463 Message
::CodegenDone { llvm_work_item, cost }
=> {
1464 // We keep the queue sorted by estimated processing cost,
1465 // so that more expensive items are processed earlier. This
1466 // is good for throughput as it gives the main thread more
1467 // time to fill up the queue and it avoids scheduling
1468 // expensive items to the end.
1469 // Note, however, that this is not ideal for memory
1470 // consumption, as LLVM module sizes are not evenly
1472 let insertion_index
= work_items
.binary_search_by_key(&cost
, |&(_
, cost
)| cost
);
1473 let insertion_index
= match insertion_index
{
1474 Ok(idx
) | Err(idx
) => idx
,
1476 work_items
.insert(insertion_index
, (llvm_work_item
, cost
));
1478 if !cgcx
.opts
.unstable_opts
.no_parallel_llvm
{
1479 helper
.request_token();
1481 assert_eq
!(main_thread_worker_state
, MainThreadWorkerState
::Codegenning
);
1482 main_thread_worker_state
= MainThreadWorkerState
::Idle
;
1485 Message
::CodegenComplete
=> {
1486 codegen_done
= true;
1487 assert_eq
!(main_thread_worker_state
, MainThreadWorkerState
::Codegenning
);
1488 main_thread_worker_state
= MainThreadWorkerState
::Idle
;
1491 // If codegen is aborted that means translation was aborted due
1492 // to some normal-ish compiler error. In this situation we want
1493 // to exit as soon as possible, but we want to make sure all
1494 // existing work has finished. Flag codegen as being done, and
1495 // then conditions above will ensure no more work is spawned but
1496 // we'll keep executing this loop until `running` hits 0.
1497 Message
::CodegenAborted
=> {
1498 codegen_done
= true;
1499 codegen_aborted
= true;
1501 Message
::Done { result: Ok(compiled_module), worker_id }
=> {
1502 free_worker(worker_id
);
1503 match compiled_module
.kind
{
1504 ModuleKind
::Regular
=> {
1505 compiled_modules
.push(compiled_module
);
1507 ModuleKind
::Allocator
=> {
1508 assert
!(compiled_allocator_module
.is_none());
1509 compiled_allocator_module
= Some(compiled_module
);
1511 ModuleKind
::Metadata
=> bug
!("Should be handled separately"),
1514 Message
::NeedsLink { module, worker_id }
=> {
1515 free_worker(worker_id
);
1516 needs_link
.push(module
);
1518 Message
::NeedsFatLTO { result, worker_id }
=> {
1519 assert
!(!started_lto
);
1520 free_worker(worker_id
);
1521 needs_fat_lto
.push(result
);
1523 Message
::NeedsThinLTO { name, thin_buffer, worker_id }
=> {
1524 assert
!(!started_lto
);
1525 free_worker(worker_id
);
1526 needs_thin_lto
.push((name
, thin_buffer
));
1528 Message
::AddImportOnlyModule { module_data, work_product }
=> {
1529 assert
!(!started_lto
);
1530 assert
!(!codegen_done
);
1531 assert_eq
!(main_thread_worker_state
, MainThreadWorkerState
::Codegenning
);
1532 lto_import_only_modules
.push((module_data
, work_product
));
1533 main_thread_worker_state
= MainThreadWorkerState
::Idle
;
1535 // If the thread failed that means it panicked, so we abort immediately.
1536 Message
::Done { result: Err(None), worker_id: _ }
=> {
1537 bug
!("worker thread panicked");
1539 Message
::Done { result: Err(Some(WorkerFatalError)), worker_id }
=> {
1540 // Similar to CodegenAborted, wait for remaining work to finish.
1541 free_worker(worker_id
);
1542 codegen_done
= true;
1543 codegen_aborted
= true;
1545 Message
::CodegenItem
=> bug
!("the coordinator should not receive codegen requests"),
1549 if codegen_aborted
{
1553 let needs_link
= mem
::take(&mut needs_link
);
1554 if !needs_link
.is_empty() {
1555 assert
!(compiled_modules
.is_empty());
1556 let diag_handler
= cgcx
.create_diag_handler();
1557 let module
= B
::run_link(&cgcx
, &diag_handler
, needs_link
).map_err(|_
| ())?
;
1558 let module
= unsafe {
1559 B
::codegen(&cgcx
, &diag_handler
, module
, cgcx
.config(ModuleKind
::Regular
))
1562 compiled_modules
.push(module
);
1565 // Drop to print timings
1566 drop(llvm_start_time
);
1568 // Regardless of what order these modules completed in, report them to
1569 // the backend in the same order every time to ensure that we're handing
1570 // out deterministic results.
1571 compiled_modules
.sort_by(|a
, b
| a
.name
.cmp(&b
.name
));
1573 Ok(CompiledModules
{
1574 modules
: compiled_modules
,
1575 allocator_module
: compiled_allocator_module
,
1579 // A heuristic that determines if we have enough LLVM WorkItems in the
1580 // queue so that the main thread can do LLVM work instead of codegen
1581 fn queue_full_enough(items_in_queue
: usize, workers_running
: usize) -> bool
{
1582 // This heuristic scales ahead-of-time codegen according to available
1583 // concurrency, as measured by `workers_running`. The idea is that the
1584 // more concurrency we have available, the more demand there will be for
1585 // work items, and the fuller the queue should be kept to meet demand.
1586 // An important property of this approach is that we codegen ahead of
1587 // time only as much as necessary, so as to keep fewer LLVM modules in
1588 // memory at once, thereby reducing memory consumption.
1590 // When the number of workers running is less than the max concurrency
1591 // available to us, this heuristic can cause us to instruct the main
1592 // thread to work on an LLVM item (that is, tell it to "LLVM") instead
1593 // of codegen, even though it seems like it *should* be codegenning so
1594 // that we can create more work items and spawn more LLVM workers.
1596 // But this is not a problem. When the main thread is told to LLVM,
1597 // according to this heuristic and how work is scheduled, there is
1598 // always at least one item in the queue, and therefore at least one
1599 // pending jobserver token request. If there *is* more concurrency
1600 // available, we will immediately receive a token, which will upgrade
1601 // the main thread's LLVM worker to a real one (conceptually), and free
1602 // up the main thread to codegen if necessary. On the other hand, if
1603 // there isn't more concurrency, then the main thread working on an LLVM
1604 // item is appropriate, as long as the queue is full enough for demand.
1606 // Speaking of which, how full should we keep the queue? Probably less
1607 // full than you'd think. A lot has to go wrong for the queue not to be
1608 // full enough and for that to have a negative effect on compile times.
1610 // Workers are unlikely to finish at exactly the same time, so when one
1611 // finishes and takes another work item off the queue, we often have
1612 // ample time to codegen at that point before the next worker finishes.
1613 // But suppose that codegen takes so long that the workers exhaust the
1614 // queue, and we have one or more workers that have nothing to work on.
1615 // Well, it might not be so bad. Of all the LLVM modules we create and
1616 // optimize, one has to finish last. It's not necessarily the case that
1617 // by losing some concurrency for a moment, we delay the point at which
1618 // that last LLVM module is finished and the rest of compilation can
1619 // proceed. Also, when we can't take advantage of some concurrency, we
1620 // give tokens back to the job server. That enables some other rustc to
1621 // potentially make use of the available concurrency. That could even
1622 // *decrease* overall compile time if we're lucky. But yes, if no other
1623 // rustc can make use of the concurrency, then we've squandered it.
1625 // However, keeping the queue full is also beneficial when we have a
1626 // surge in available concurrency. Then items can be taken from the
1627 // queue immediately, without having to wait for codegen.
1629 // So, the heuristic below tries to keep one item in the queue for every
1630 // four running workers. Based on limited benchmarking, this appears to
1631 // be more than sufficient to avoid increasing compilation times.
1632 let quarter_of_workers
= workers_running
- 3 * workers_running
/ 4;
1633 items_in_queue
> 0 && items_in_queue
>= quarter_of_workers
1636 fn maybe_start_llvm_timer
<'a
>(
1637 prof
: &'a SelfProfilerRef
,
1638 config
: &ModuleConfig
,
1639 llvm_start_time
: &mut Option
<VerboseTimingGuard
<'a
>>,
1641 if config
.time_module
&& llvm_start_time
.is_none() {
1642 *llvm_start_time
= Some(prof
.extra_verbose_generic_activity("LLVM_passes", "crate"));
1647 /// `FatalError` is explicitly not `Send`.
1649 pub struct WorkerFatalError
;
1651 fn spawn_work
<B
: ExtraBackendMethods
>(cgcx
: CodegenContext
<B
>, work
: WorkItem
<B
>) {
1652 B
::spawn_named_thread(cgcx
.time_trace
, work
.short_description(), move || {
1653 // Set up a destructor which will fire off a message that we're done as
1655 struct Bomb
<B
: ExtraBackendMethods
> {
1656 coordinator_send
: Sender
<Box
<dyn Any
+ Send
>>,
1657 result
: Option
<Result
<WorkItemResult
<B
>, FatalError
>>,
1660 impl<B
: ExtraBackendMethods
> Drop
for Bomb
<B
> {
1661 fn drop(&mut self) {
1662 let worker_id
= self.worker_id
;
1663 let msg
= match self.result
.take() {
1664 Some(Ok(WorkItemResult
::Compiled(m
))) => {
1665 Message
::Done
::<B
> { result: Ok(m), worker_id }
1667 Some(Ok(WorkItemResult
::NeedsLink(m
))) => {
1668 Message
::NeedsLink
::<B
> { module: m, worker_id }
1670 Some(Ok(WorkItemResult
::NeedsFatLTO(m
))) => {
1671 Message
::NeedsFatLTO
::<B
> { result: m, worker_id }
1673 Some(Ok(WorkItemResult
::NeedsThinLTO(name
, thin_buffer
))) => {
1674 Message
::NeedsThinLTO
::<B
> { name, thin_buffer, worker_id }
1676 Some(Err(FatalError
)) => {
1677 Message
::Done
::<B
> { result: Err(Some(WorkerFatalError)), worker_id }
1679 None
=> Message
::Done
::<B
> { result: Err(None), worker_id }
,
1681 drop(self.coordinator_send
.send(Box
::new(msg
)));
1685 let mut bomb
= Bomb
::<B
> {
1686 coordinator_send
: cgcx
.coordinator_send
.clone(),
1688 worker_id
: cgcx
.worker
,
1691 // Execute the work itself, and if it finishes successfully then flag
1692 // ourselves as a success as well.
1694 // Note that we ignore any `FatalError` coming out of `execute_work_item`,
1695 // as a diagnostic was already sent off to the main thread - just
1696 // surface that there was an error in this worker.
1698 let _prof_timer
= work
.start_profiling(&cgcx
);
1699 Some(execute_work_item(&cgcx
, work
))
1702 .expect("failed to spawn thread");
1705 enum SharedEmitterMessage
{
1706 Diagnostic(Diagnostic
),
1707 InlineAsmError(u32, String
, Level
, Option
<(String
, Vec
<InnerSpan
>)>),
1713 pub struct SharedEmitter
{
1714 sender
: Sender
<SharedEmitterMessage
>,
1717 pub struct SharedEmitterMain
{
1718 receiver
: Receiver
<SharedEmitterMessage
>,
1721 impl SharedEmitter
{
1722 pub fn new() -> (SharedEmitter
, SharedEmitterMain
) {
1723 let (sender
, receiver
) = channel();
1725 (SharedEmitter { sender }
, SharedEmitterMain { receiver }
)
1728 pub fn inline_asm_error(
1733 source
: Option
<(String
, Vec
<InnerSpan
>)>,
1735 drop(self.sender
.send(SharedEmitterMessage
::InlineAsmError(cookie
, msg
, level
, source
)));
1738 pub fn fatal(&self, msg
: &str) {
1739 drop(self.sender
.send(SharedEmitterMessage
::Fatal(msg
.to_string())));
1743 impl Translate
for SharedEmitter
{
1744 fn fluent_bundle(&self) -> Option
<&Lrc
<rustc_errors
::FluentBundle
>> {
1748 fn fallback_fluent_bundle(&self) -> &rustc_errors
::FluentBundle
{
1749 panic
!("shared emitter attempted to translate a diagnostic");
1753 impl Emitter
for SharedEmitter
{
1754 fn emit_diagnostic(&mut self, diag
: &rustc_errors
::Diagnostic
) {
1755 let fluent_args
= self.to_fluent_args(diag
.args());
1756 drop(self.sender
.send(SharedEmitterMessage
::Diagnostic(Diagnostic
{
1757 msg
: self.translate_messages(&diag
.message
, &fluent_args
).to_string(),
1758 code
: diag
.code
.clone(),
1761 for child
in &diag
.children
{
1762 drop(self.sender
.send(SharedEmitterMessage
::Diagnostic(Diagnostic
{
1763 msg
: self.translate_messages(&child
.message
, &fluent_args
).to_string(),
1768 drop(self.sender
.send(SharedEmitterMessage
::AbortIfErrors
));
1771 fn source_map(&self) -> Option
<&Lrc
<SourceMap
>> {
1776 impl SharedEmitterMain
{
1777 pub fn check(&self, sess
: &Session
, blocking
: bool
) {
1779 let message
= if blocking
{
1780 match self.receiver
.recv() {
1781 Ok(message
) => Ok(message
),
1785 match self.receiver
.try_recv() {
1786 Ok(message
) => Ok(message
),
1792 Ok(SharedEmitterMessage
::Diagnostic(diag
)) => {
1793 let handler
= sess
.diagnostic();
1794 let mut d
= rustc_errors
::Diagnostic
::new(diag
.lvl
, &diag
.msg
);
1795 if let Some(code
) = diag
.code
{
1798 handler
.emit_diagnostic(&mut d
);
1800 Ok(SharedEmitterMessage
::InlineAsmError(cookie
, msg
, level
, source
)) => {
1801 let msg
= msg
.strip_prefix("error: ").unwrap_or(&msg
);
1803 let mut err
= match level
{
1804 Level
::Error { lint: false }
=> sess
.struct_err(msg
).forget_guarantee(),
1805 Level
::Warning(_
) => sess
.struct_warn(msg
),
1806 Level
::Note
=> sess
.struct_note_without_error(msg
),
1807 _
=> bug
!("Invalid inline asm diagnostic level"),
1810 // If the cookie is 0 then we don't have span information.
1812 let pos
= BytePos
::from_u32(cookie
);
1813 let span
= Span
::with_root_ctxt(pos
, pos
);
1817 // Point to the generated assembly if it is available.
1818 if let Some((buffer
, spans
)) = source
{
1821 .new_source_file(FileName
::inline_asm_source_code(&buffer
), buffer
);
1822 let source_span
= Span
::with_root_ctxt(source
.start_pos
, source
.end_pos
);
1824 spans
.iter().map(|sp
| source_span
.from_inner(*sp
)).collect();
1825 err
.span_note(spans
, "instantiated into assembly here");
1830 Ok(SharedEmitterMessage
::AbortIfErrors
) => {
1831 sess
.abort_if_errors();
1833 Ok(SharedEmitterMessage
::Fatal(msg
)) => {
1844 pub struct Coordinator
<B
: ExtraBackendMethods
> {
1845 pub sender
: Sender
<Box
<dyn Any
+ Send
>>,
1846 future
: Option
<thread
::JoinHandle
<Result
<CompiledModules
, ()>>>,
1847 // Only used for the Message type.
1848 phantom
: PhantomData
<B
>,
1851 impl<B
: ExtraBackendMethods
> Coordinator
<B
> {
1852 fn join(mut self) -> std
::thread
::Result
<Result
<CompiledModules
, ()>> {
1853 self.future
.take().unwrap().join()
1857 impl<B
: ExtraBackendMethods
> Drop
for Coordinator
<B
> {
1858 fn drop(&mut self) {
1859 if let Some(future
) = self.future
.take() {
1860 // If we haven't joined yet, signal to the coordinator that it should spawn no more
1861 // work, and wait for worker threads to finish.
1862 drop(self.sender
.send(Box
::new(Message
::CodegenAborted
::<B
>)));
1863 drop(future
.join());
1868 pub struct OngoingCodegen
<B
: ExtraBackendMethods
> {
1870 pub metadata
: EncodedMetadata
,
1871 pub metadata_module
: Option
<CompiledModule
>,
1872 pub crate_info
: CrateInfo
,
1873 pub codegen_worker_receive
: Receiver
<Message
<B
>>,
1874 pub shared_emitter_main
: SharedEmitterMain
,
1875 pub output_filenames
: Arc
<OutputFilenames
>,
1876 pub coordinator
: Coordinator
<B
>,
1879 impl<B
: ExtraBackendMethods
> OngoingCodegen
<B
> {
1880 pub fn join(self, sess
: &Session
) -> (CodegenResults
, FxHashMap
<WorkProductId
, WorkProduct
>) {
1881 let _timer
= sess
.timer("finish_ongoing_codegen");
1883 self.shared_emitter_main
.check(sess
, true);
1884 let compiled_modules
= sess
.time("join_worker_thread", || match self.coordinator
.join() {
1885 Ok(Ok(compiled_modules
)) => compiled_modules
,
1887 sess
.abort_if_errors();
1888 panic
!("expected abort due to worker thread errors")
1891 bug
!("panic during codegen/LLVM phase");
1895 sess
.cgu_reuse_tracker
.check_expected_reuse(sess
);
1897 sess
.abort_if_errors();
1900 copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess
, &compiled_modules
);
1901 produce_final_output_artifacts(sess
, &compiled_modules
, &self.output_filenames
);
1903 // FIXME: time_llvm_passes support - does this use a global context or
1905 if sess
.codegen_units() == 1 && sess
.time_llvm_passes() {
1906 self.backend
.print_pass_timings()
1911 metadata
: self.metadata
,
1912 crate_info
: self.crate_info
,
1914 modules
: compiled_modules
.modules
,
1915 allocator_module
: compiled_modules
.allocator_module
,
1916 metadata_module
: self.metadata_module
,
1922 pub fn submit_pre_codegened_module_to_llvm(
1925 module
: ModuleCodegen
<B
::Module
>,
1927 self.wait_for_signal_to_codegen_item();
1928 self.check_for_errors(tcx
.sess
);
1930 // These are generally cheap and won't throw off scheduling.
1932 submit_codegened_module_to_llvm(&self.backend
, &self.coordinator
.sender
, module
, cost
);
1935 pub fn codegen_finished(&self, tcx
: TyCtxt
<'_
>) {
1936 self.wait_for_signal_to_codegen_item();
1937 self.check_for_errors(tcx
.sess
);
1938 drop(self.coordinator
.sender
.send(Box
::new(Message
::CodegenComplete
::<B
>)));
1941 pub fn check_for_errors(&self, sess
: &Session
) {
1942 self.shared_emitter_main
.check(sess
, false);
1945 pub fn wait_for_signal_to_codegen_item(&self) {
1946 match self.codegen_worker_receive
.recv() {
1947 Ok(Message
::CodegenItem
) => {
1950 Ok(_
) => panic
!("unexpected message"),
1952 // One of the LLVM threads must have panicked, fall through so
1953 // error handling can be reached.
1959 pub fn submit_codegened_module_to_llvm
<B
: ExtraBackendMethods
>(
1961 tx_to_llvm_workers
: &Sender
<Box
<dyn Any
+ Send
>>,
1962 module
: ModuleCodegen
<B
::Module
>,
1965 let llvm_work_item
= WorkItem
::Optimize(module
);
1966 drop(tx_to_llvm_workers
.send(Box
::new(Message
::CodegenDone
::<B
> { llvm_work_item, cost }
)));
1969 pub fn submit_post_lto_module_to_llvm
<B
: ExtraBackendMethods
>(
1971 tx_to_llvm_workers
: &Sender
<Box
<dyn Any
+ Send
>>,
1972 module
: CachedModuleCodegen
,
1974 let llvm_work_item
= WorkItem
::CopyPostLtoArtifacts(module
);
1975 drop(tx_to_llvm_workers
.send(Box
::new(Message
::CodegenDone
::<B
> { llvm_work_item, cost: 0 }
)));
1978 pub fn submit_pre_lto_module_to_llvm
<B
: ExtraBackendMethods
>(
1981 tx_to_llvm_workers
: &Sender
<Box
<dyn Any
+ Send
>>,
1982 module
: CachedModuleCodegen
,
1984 let filename
= pre_lto_bitcode_filename(&module
.name
);
1985 let bc_path
= in_incr_comp_dir_sess(tcx
.sess
, &filename
);
1986 let file
= fs
::File
::open(&bc_path
)
1987 .unwrap_or_else(|e
| panic
!("failed to open bitcode file `{}`: {}", bc_path
.display(), e
));
1990 Mmap
::map(file
).unwrap_or_else(|e
| {
1991 panic
!("failed to mmap bitcode file `{}`: {}", bc_path
.display(), e
)
1994 // Schedule the module to be loaded
1995 drop(tx_to_llvm_workers
.send(Box
::new(Message
::AddImportOnlyModule
::<B
> {
1996 module_data
: SerializedModule
::FromUncompressedFile(mmap
),
1997 work_product
: module
.source
,
2001 pub fn pre_lto_bitcode_filename(module_name
: &str) -> String
{
2002 format
!("{}.{}", module_name
, PRE_LTO_BC_EXT
)
2005 fn msvc_imps_needed(tcx
: TyCtxt
<'_
>) -> bool
{
2006 // This should never be true (because it's not supported). If it is true,
2007 // something is wrong with commandline arg validation.
2009 !(tcx
.sess
.opts
.cg
.linker_plugin_lto
.enabled()
2010 && tcx
.sess
.target
.is_like_windows
2011 && tcx
.sess
.opts
.cg
.prefer_dynamic
)
2014 tcx
.sess
.target
.is_like_windows
&&
2015 tcx
.sess
.crate_types().iter().any(|ct
| *ct
== CrateType
::Rlib
) &&
2016 // ThinLTO can't handle this workaround in all cases, so we don't
2017 // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing
2018 // dynamic linking when linker plugin LTO is enabled.
2019 !tcx
.sess
.opts
.cg
.linker_plugin_lto
.enabled()