]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_ssa/src/base.rs
Rollup merge of #91593 - upsuper-forks:hashmap-set-methods-bound, r=dtolnay
[rust.git] / compiler / rustc_codegen_ssa / src / base.rs
1 use crate::back::metadata::create_compressed_metadata_file;
2 use crate::back::write::{
3     compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm,
4     submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen,
5 };
6 use crate::common::{IntPredicate, RealPredicate, TypeKind};
7 use crate::meth;
8 use crate::mir;
9 use crate::mir::operand::OperandValue;
10 use crate::mir::place::PlaceRef;
11 use crate::traits::*;
12 use crate::{CachedModuleCodegen, CompiledModule, CrateInfo, MemFlags, ModuleCodegen, ModuleKind};
13
14 use rustc_attr as attr;
15 use rustc_data_structures::fx::FxHashMap;
16 use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
17 use rustc_data_structures::sync::{par_iter, ParallelIterator};
18 use rustc_hir as hir;
19 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
20 use rustc_hir::lang_items::LangItem;
21 use rustc_index::vec::Idx;
22 use rustc_metadata::EncodedMetadata;
23 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
24 use rustc_middle::middle::exported_symbols;
25 use rustc_middle::middle::lang_items;
26 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
27 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
28 use rustc_middle::ty::query::Providers;
29 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
30 use rustc_session::cgu_reuse_tracker::CguReuse;
31 use rustc_session::config::{self, EntryFnType, OutputType};
32 use rustc_session::Session;
33 use rustc_span::symbol::sym;
34 use rustc_target::abi::{Align, VariantIdx};
35
36 use std::convert::TryFrom;
37 use std::ops::{Deref, DerefMut};
38 use std::time::{Duration, Instant};
39
40 use itertools::Itertools;
41
42 pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind, signed: bool) -> IntPredicate {
43     match op {
44         hir::BinOpKind::Eq => IntPredicate::IntEQ,
45         hir::BinOpKind::Ne => IntPredicate::IntNE,
46         hir::BinOpKind::Lt => {
47             if signed {
48                 IntPredicate::IntSLT
49             } else {
50                 IntPredicate::IntULT
51             }
52         }
53         hir::BinOpKind::Le => {
54             if signed {
55                 IntPredicate::IntSLE
56             } else {
57                 IntPredicate::IntULE
58             }
59         }
60         hir::BinOpKind::Gt => {
61             if signed {
62                 IntPredicate::IntSGT
63             } else {
64                 IntPredicate::IntUGT
65             }
66         }
67         hir::BinOpKind::Ge => {
68             if signed {
69                 IntPredicate::IntSGE
70             } else {
71                 IntPredicate::IntUGE
72             }
73         }
74         op => bug!(
75             "comparison_op_to_icmp_predicate: expected comparison operator, \
76              found {:?}",
77             op
78         ),
79     }
80 }
81
82 pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> RealPredicate {
83     match op {
84         hir::BinOpKind::Eq => RealPredicate::RealOEQ,
85         hir::BinOpKind::Ne => RealPredicate::RealUNE,
86         hir::BinOpKind::Lt => RealPredicate::RealOLT,
87         hir::BinOpKind::Le => RealPredicate::RealOLE,
88         hir::BinOpKind::Gt => RealPredicate::RealOGT,
89         hir::BinOpKind::Ge => RealPredicate::RealOGE,
90         op => {
91             bug!(
92                 "comparison_op_to_fcmp_predicate: expected comparison operator, \
93                  found {:?}",
94                 op
95             );
96         }
97     }
98 }
99
100 pub fn compare_simd_types<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
101     bx: &mut Bx,
102     lhs: Bx::Value,
103     rhs: Bx::Value,
104     t: Ty<'tcx>,
105     ret_ty: Bx::Type,
106     op: hir::BinOpKind,
107 ) -> Bx::Value {
108     let signed = match t.kind() {
109         ty::Float(_) => {
110             let cmp = bin_op_to_fcmp_predicate(op);
111             let cmp = bx.fcmp(cmp, lhs, rhs);
112             return bx.sext(cmp, ret_ty);
113         }
114         ty::Uint(_) => false,
115         ty::Int(_) => true,
116         _ => bug!("compare_simd_types: invalid SIMD type"),
117     };
118
119     let cmp = bin_op_to_icmp_predicate(op, signed);
120     let cmp = bx.icmp(cmp, lhs, rhs);
121     // LLVM outputs an `< size x i1 >`, so we need to perform a sign extension
122     // to get the correctly sized type. This will compile to a single instruction
123     // once the IR is converted to assembly if the SIMD instruction is supported
124     // by the target architecture.
125     bx.sext(cmp, ret_ty)
126 }
127
128 /// Retrieves the information we are losing (making dynamic) in an unsizing
129 /// adjustment.
130 ///
131 /// The `old_info` argument is a bit odd. It is intended for use in an upcast,
132 /// where the new vtable for an object will be derived from the old one.
133 pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
134     bx: &mut Bx,
135     source: Ty<'tcx>,
136     target: Ty<'tcx>,
137     old_info: Option<Bx::Value>,
138 ) -> Bx::Value {
139     let cx = bx.cx();
140     let (source, target) =
141         cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, bx.param_env());
142     match (source.kind(), target.kind()) {
143         (&ty::Array(_, len), &ty::Slice(_)) => {
144             cx.const_usize(len.eval_usize(cx.tcx(), ty::ParamEnv::reveal_all()))
145         }
146         (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
147             let old_info =
148                 old_info.expect("unsized_info: missing old info for trait upcasting coercion");
149             if data_a.principal_def_id() == data_b.principal_def_id() {
150                 return old_info;
151             }
152
153             // trait upcasting coercion
154
155             let vptr_entry_idx =
156                 cx.tcx().vtable_trait_upcasting_coercion_new_vptr_slot((source, target));
157
158             if let Some(entry_idx) = vptr_entry_idx {
159                 let ptr_ty = cx.type_i8p();
160                 let ptr_align = cx.tcx().data_layout.pointer_align.abi;
161                 let llvtable = bx.pointercast(old_info, bx.type_ptr_to(ptr_ty));
162                 let gep = bx.inbounds_gep(
163                     ptr_ty,
164                     llvtable,
165                     &[bx.const_usize(u64::try_from(entry_idx).unwrap())],
166                 );
167                 let new_vptr = bx.load(ptr_ty, gep, ptr_align);
168                 bx.nonnull_metadata(new_vptr);
169                 // Vtable loads are invariant.
170                 bx.set_invariant_load(new_vptr);
171                 new_vptr
172             } else {
173                 old_info
174             }
175         }
176         (_, &ty::Dynamic(ref data, ..)) => {
177             let vtable_ptr_ty = cx.scalar_pair_element_backend_type(
178                 cx.layout_of(cx.tcx().mk_mut_ptr(target)),
179                 1,
180                 true,
181             );
182             cx.const_ptrcast(meth::get_vtable(cx, source, data.principal()), vtable_ptr_ty)
183         }
184         _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target),
185     }
186 }
187
188 /// Coerces `src` to `dst_ty`. `src_ty` must be a pointer.
189 pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
190     bx: &mut Bx,
191     src: Bx::Value,
192     src_ty: Ty<'tcx>,
193     dst_ty: Ty<'tcx>,
194     old_info: Option<Bx::Value>,
195 ) -> (Bx::Value, Bx::Value) {
196     debug!("unsize_ptr: {:?} => {:?}", src_ty, dst_ty);
197     match (src_ty.kind(), dst_ty.kind()) {
198         (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(ty::TypeAndMut { ty: b, .. }))
199         | (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
200             assert_eq!(bx.cx().type_is_sized(a), old_info.is_none());
201             let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b)));
202             (bx.pointercast(src, ptr_ty), unsized_info(bx, a, b, old_info))
203         }
204         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
205             assert_eq!(def_a, def_b);
206             let src_layout = bx.cx().layout_of(src_ty);
207             let dst_layout = bx.cx().layout_of(dst_ty);
208             if src_ty == dst_ty {
209                 return (src, old_info.unwrap());
210             }
211             let mut result = None;
212             for i in 0..src_layout.fields.count() {
213                 let src_f = src_layout.field(bx.cx(), i);
214                 assert_eq!(src_layout.fields.offset(i).bytes(), 0);
215                 assert_eq!(dst_layout.fields.offset(i).bytes(), 0);
216                 if src_f.is_zst() {
217                     continue;
218                 }
219                 assert_eq!(src_layout.size, src_f.size);
220
221                 let dst_f = dst_layout.field(bx.cx(), i);
222                 assert_ne!(src_f.ty, dst_f.ty);
223                 assert_eq!(result, None);
224                 result = Some(unsize_ptr(bx, src, src_f.ty, dst_f.ty, old_info));
225             }
226             let (lldata, llextra) = result.unwrap();
227             let lldata_ty = bx.cx().scalar_pair_element_backend_type(dst_layout, 0, true);
228             let llextra_ty = bx.cx().scalar_pair_element_backend_type(dst_layout, 1, true);
229             // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
230             (bx.bitcast(lldata, lldata_ty), bx.bitcast(llextra, llextra_ty))
231         }
232         _ => bug!("unsize_ptr: called on bad types"),
233     }
234 }
235
236 /// Coerces `src`, which is a reference to a value of type `src_ty`,
237 /// to a value of type `dst_ty`, and stores the result in `dst`.
238 pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
239     bx: &mut Bx,
240     src: PlaceRef<'tcx, Bx::Value>,
241     dst: PlaceRef<'tcx, Bx::Value>,
242 ) {
243     let src_ty = src.layout.ty;
244     let dst_ty = dst.layout.ty;
245     match (src_ty.kind(), dst_ty.kind()) {
246         (&ty::Ref(..), &ty::Ref(..) | &ty::RawPtr(..)) | (&ty::RawPtr(..), &ty::RawPtr(..)) => {
247             let (base, info) = match bx.load_operand(src).val {
248                 OperandValue::Pair(base, info) => unsize_ptr(bx, base, src_ty, dst_ty, Some(info)),
249                 OperandValue::Immediate(base) => unsize_ptr(bx, base, src_ty, dst_ty, None),
250                 OperandValue::Ref(..) => bug!(),
251             };
252             OperandValue::Pair(base, info).store(bx, dst);
253         }
254
255         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
256             assert_eq!(def_a, def_b);
257
258             for i in 0..def_a.variants[VariantIdx::new(0)].fields.len() {
259                 let src_f = src.project_field(bx, i);
260                 let dst_f = dst.project_field(bx, i);
261
262                 if dst_f.layout.is_zst() {
263                     continue;
264                 }
265
266                 if src_f.layout.ty == dst_f.layout.ty {
267                     memcpy_ty(
268                         bx,
269                         dst_f.llval,
270                         dst_f.align,
271                         src_f.llval,
272                         src_f.align,
273                         src_f.layout,
274                         MemFlags::empty(),
275                     );
276                 } else {
277                     coerce_unsized_into(bx, src_f, dst_f);
278                 }
279             }
280         }
281         _ => bug!("coerce_unsized_into: invalid coercion {:?} -> {:?}", src_ty, dst_ty,),
282     }
283 }
284
285 pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
286     bx: &mut Bx,
287     op: hir::BinOpKind,
288     lhs: Bx::Value,
289     rhs: Bx::Value,
290 ) -> Bx::Value {
291     cast_shift_rhs(bx, op, lhs, rhs)
292 }
293
294 fn cast_shift_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
295     bx: &mut Bx,
296     op: hir::BinOpKind,
297     lhs: Bx::Value,
298     rhs: Bx::Value,
299 ) -> Bx::Value {
300     // Shifts may have any size int on the rhs
301     if op.is_shift() {
302         let mut rhs_llty = bx.cx().val_ty(rhs);
303         let mut lhs_llty = bx.cx().val_ty(lhs);
304         if bx.cx().type_kind(rhs_llty) == TypeKind::Vector {
305             rhs_llty = bx.cx().element_type(rhs_llty)
306         }
307         if bx.cx().type_kind(lhs_llty) == TypeKind::Vector {
308             lhs_llty = bx.cx().element_type(lhs_llty)
309         }
310         let rhs_sz = bx.cx().int_width(rhs_llty);
311         let lhs_sz = bx.cx().int_width(lhs_llty);
312         if lhs_sz < rhs_sz {
313             bx.trunc(rhs, lhs_llty)
314         } else if lhs_sz > rhs_sz {
315             // FIXME (#1877: If in the future shifting by negative
316             // values is no longer undefined then this is wrong.
317             bx.zext(rhs, lhs_llty)
318         } else {
319             rhs
320         }
321     } else {
322         rhs
323     }
324 }
325
326 /// Returns `true` if this session's target will use SEH-based unwinding.
327 ///
328 /// This is only true for MSVC targets, and even then the 64-bit MSVC target
329 /// currently uses SEH-ish unwinding with DWARF info tables to the side (same as
330 /// 64-bit MinGW) instead of "full SEH".
331 pub fn wants_msvc_seh(sess: &Session) -> bool {
332     sess.target.is_like_msvc
333 }
334
335 pub fn memcpy_ty<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
336     bx: &mut Bx,
337     dst: Bx::Value,
338     dst_align: Align,
339     src: Bx::Value,
340     src_align: Align,
341     layout: TyAndLayout<'tcx>,
342     flags: MemFlags,
343 ) {
344     let size = layout.size.bytes();
345     if size == 0 {
346         return;
347     }
348
349     bx.memcpy(dst, dst_align, src, src_align, bx.cx().const_usize(size), flags);
350 }
351
352 pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
353     cx: &'a Bx::CodegenCx,
354     instance: Instance<'tcx>,
355 ) {
356     // this is an info! to allow collecting monomorphization statistics
357     // and to allow finding the last function before LLVM aborts from
358     // release builds.
359     info!("codegen_instance({})", instance);
360
361     mir::codegen_mir::<Bx>(cx, instance);
362 }
363
364 /// Creates the `main` function which will initialize the rust runtime and call
365 /// users main function.
366 pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
367     cx: &'a Bx::CodegenCx,
368 ) -> Option<Bx::Function> {
369     let (main_def_id, entry_type) = cx.tcx().entry_fn(())?;
370     let main_is_local = main_def_id.is_local();
371     let instance = Instance::mono(cx.tcx(), main_def_id);
372
373     if main_is_local {
374         // We want to create the wrapper in the same codegen unit as Rust's main
375         // function.
376         if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) {
377             return None;
378         }
379     } else if !cx.codegen_unit().is_primary() {
380         // We want to create the wrapper only when the codegen unit is the primary one
381         return None;
382     }
383
384     let main_llfn = cx.get_fn_addr(instance);
385
386     let use_start_lang_item = EntryFnType::Start != entry_type;
387     let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, use_start_lang_item);
388     return Some(entry_fn);
389
390     fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
391         cx: &'a Bx::CodegenCx,
392         rust_main: Bx::Value,
393         rust_main_def_id: DefId,
394         use_start_lang_item: bool,
395     ) -> Bx::Function {
396         // The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
397         // depending on whether the target needs `argc` and `argv` to be passed in.
398         let llfty = if cx.sess().target.main_needs_argc_argv {
399             cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int())
400         } else {
401             cx.type_func(&[], cx.type_int())
402         };
403
404         let main_ret_ty = cx.tcx().fn_sig(rust_main_def_id).output();
405         // Given that `main()` has no arguments,
406         // then its return type cannot have
407         // late-bound regions, since late-bound
408         // regions must appear in the argument
409         // listing.
410         let main_ret_ty = cx.tcx().erase_regions(main_ret_ty.no_bound_vars().unwrap());
411
412         let llfn = match cx.declare_c_main(llfty) {
413             Some(llfn) => llfn,
414             None => {
415                 // FIXME: We should be smart and show a better diagnostic here.
416                 let span = cx.tcx().def_span(rust_main_def_id);
417                 cx.sess()
418                     .struct_span_err(span, "entry symbol `main` declared multiple times")
419                     .help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead")
420                     .emit();
421                 cx.sess().abort_if_errors();
422                 bug!();
423             }
424         };
425
426         // `main` should respect same config for frame pointer elimination as rest of code
427         cx.set_frame_pointer_type(llfn);
428         cx.apply_target_cpu_attr(llfn);
429
430         let llbb = Bx::append_block(&cx, llfn, "top");
431         let mut bx = Bx::build(&cx, llbb);
432
433         bx.insert_reference_to_gdb_debug_scripts_section_global();
434
435         let isize_ty = cx.type_isize();
436         let i8pp_ty = cx.type_ptr_to(cx.type_i8p());
437         let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx);
438
439         let (start_fn, start_ty, args) = if use_start_lang_item {
440             let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
441             let start_fn = cx.get_fn_addr(
442                 ty::Instance::resolve(
443                     cx.tcx(),
444                     ty::ParamEnv::reveal_all(),
445                     start_def_id,
446                     cx.tcx().intern_substs(&[main_ret_ty.into()]),
447                 )
448                 .unwrap()
449                 .unwrap(),
450             );
451             let start_ty = cx.type_func(&[cx.val_ty(rust_main), isize_ty, i8pp_ty], isize_ty);
452             (start_fn, start_ty, vec![rust_main, arg_argc, arg_argv])
453         } else {
454             debug!("using user-defined start fn");
455             let start_ty = cx.type_func(&[isize_ty, i8pp_ty], isize_ty);
456             (rust_main, start_ty, vec![arg_argc, arg_argv])
457         };
458
459         let result = bx.call(start_ty, start_fn, &args, None);
460         let cast = bx.intcast(result, cx.type_int(), true);
461         bx.ret(cast);
462
463         llfn
464     }
465 }
466
467 /// Obtain the `argc` and `argv` values to pass to the rust start function.
468 fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
469     cx: &'a Bx::CodegenCx,
470     bx: &mut Bx,
471 ) -> (Bx::Value, Bx::Value) {
472     if cx.sess().target.main_needs_argc_argv {
473         // Params from native `main()` used as args for rust start function
474         let param_argc = bx.get_param(0);
475         let param_argv = bx.get_param(1);
476         let arg_argc = bx.intcast(param_argc, cx.type_isize(), true);
477         let arg_argv = param_argv;
478         (arg_argc, arg_argv)
479     } else {
480         // The Rust start function doesn't need `argc` and `argv`, so just pass zeros.
481         let arg_argc = bx.const_int(cx.type_int(), 0);
482         let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p()));
483         (arg_argc, arg_argv)
484     }
485 }
486
487 pub fn codegen_crate<B: ExtraBackendMethods>(
488     backend: B,
489     tcx: TyCtxt<'_>,
490     target_cpu: String,
491     metadata: EncodedMetadata,
492     need_metadata_module: bool,
493 ) -> OngoingCodegen<B> {
494     // Skip crate items and just output metadata in -Z no-codegen mode.
495     if tcx.sess.opts.debugging_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
496         let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None, 1);
497
498         ongoing_codegen.codegen_finished(tcx);
499
500         ongoing_codegen.check_for_errors(tcx.sess);
501
502         return ongoing_codegen;
503     }
504
505     let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
506
507     // Run the monomorphization collector and partition the collected items into
508     // codegen units.
509     let codegen_units = tcx.collect_and_partition_mono_items(()).1;
510
511     // Force all codegen_unit queries so they are already either red or green
512     // when compile_codegen_unit accesses them. We are not able to re-execute
513     // the codegen_unit query from just the DepNode, so an unknown color would
514     // lead to having to re-execute compile_codegen_unit, possibly
515     // unnecessarily.
516     if tcx.dep_graph.is_fully_enabled() {
517         for cgu in codegen_units {
518             tcx.ensure().codegen_unit(cgu.name());
519         }
520     }
521
522     let metadata_module = if need_metadata_module {
523         // Emit compressed metadata object.
524         let metadata_cgu_name =
525             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
526         tcx.sess.time("write_compressed_metadata", || {
527             let file_name =
528                 tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
529             let data = create_compressed_metadata_file(
530                 tcx.sess,
531                 &metadata,
532                 &exported_symbols::metadata_symbol_name(tcx),
533             );
534             if let Err(err) = std::fs::write(&file_name, data) {
535                 tcx.sess.fatal(&format!("error writing metadata object file: {}", err));
536             }
537             Some(CompiledModule {
538                 name: metadata_cgu_name,
539                 kind: ModuleKind::Metadata,
540                 object: Some(file_name),
541                 dwarf_object: None,
542                 bytecode: None,
543             })
544         })
545     } else {
546         None
547     };
548
549     let ongoing_codegen = start_async_codegen(
550         backend.clone(),
551         tcx,
552         target_cpu,
553         metadata,
554         metadata_module,
555         codegen_units.len(),
556     );
557     let ongoing_codegen = AbortCodegenOnDrop::<B>(Some(ongoing_codegen));
558
559     // Codegen an allocator shim, if necessary.
560     //
561     // If the crate doesn't have an `allocator_kind` set then there's definitely
562     // no shim to generate. Otherwise we also check our dependency graph for all
563     // our output crate types. If anything there looks like its a `Dynamic`
564     // linkage, then it's already got an allocator shim and we'll be using that
565     // one instead. If nothing exists then it's our job to generate the
566     // allocator!
567     let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| {
568         use rustc_middle::middle::dependency_format::Linkage;
569         list.iter().any(|&linkage| linkage == Linkage::Dynamic)
570     });
571     let allocator_module = if any_dynamic_crate {
572         None
573     } else if let Some(kind) = tcx.allocator_kind(()) {
574         let llmod_id =
575             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
576         let mut module_llvm = backend.new_metadata(tcx, &llmod_id);
577         tcx.sess.time("write_allocator_module", || {
578             backend.codegen_allocator(
579                 tcx,
580                 &mut module_llvm,
581                 &llmod_id,
582                 kind,
583                 tcx.lang_items().oom().is_some(),
584             )
585         });
586
587         Some(ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator })
588     } else {
589         None
590     };
591
592     if let Some(allocator_module) = allocator_module {
593         ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module);
594     }
595
596     // For better throughput during parallel processing by LLVM, we used to sort
597     // CGUs largest to smallest. This would lead to better thread utilization
598     // by, for example, preventing a large CGU from being processed last and
599     // having only one LLVM thread working while the rest remained idle.
600     //
601     // However, this strategy would lead to high memory usage, as it meant the
602     // LLVM-IR for all of the largest CGUs would be resident in memory at once.
603     //
604     // Instead, we can compromise by ordering CGUs such that the largest and
605     // smallest are first, second largest and smallest are next, etc. If there
606     // are large size variations, this can reduce memory usage significantly.
607     let codegen_units: Vec<_> = {
608         let mut sorted_cgus = codegen_units.iter().collect::<Vec<_>>();
609         sorted_cgus.sort_by_cached_key(|cgu| cgu.size_estimate());
610
611         let (first_half, second_half) = sorted_cgus.split_at(sorted_cgus.len() / 2);
612         second_half.iter().rev().interleave(first_half).copied().collect()
613     };
614
615     // The non-parallel compiler can only translate codegen units to LLVM IR
616     // on a single thread, leading to a staircase effect where the N LLVM
617     // threads have to wait on the single codegen threads to generate work
618     // for them. The parallel compiler does not have this restriction, so
619     // we can pre-load the LLVM queue in parallel before handing off
620     // coordination to the OnGoingCodegen scheduler.
621     //
622     // This likely is a temporary measure. Once we don't have to support the
623     // non-parallel compiler anymore, we can compile CGUs end-to-end in
624     // parallel and get rid of the complicated scheduling logic.
625     let pre_compile_cgus = |cgu_reuse: &[CguReuse]| {
626         if cfg!(parallel_compiler) {
627             tcx.sess.time("compile_first_CGU_batch", || {
628                 // Try to find one CGU to compile per thread.
629                 let cgus: Vec<_> = cgu_reuse
630                     .iter()
631                     .enumerate()
632                     .filter(|&(_, reuse)| reuse == &CguReuse::No)
633                     .take(tcx.sess.threads())
634                     .collect();
635
636                 // Compile the found CGUs in parallel.
637                 let start_time = Instant::now();
638
639                 let pre_compiled_cgus = par_iter(cgus)
640                     .map(|(i, _)| {
641                         let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
642                         (i, module)
643                     })
644                     .collect();
645
646                 (pre_compiled_cgus, start_time.elapsed())
647             })
648         } else {
649             (FxHashMap::default(), Duration::new(0, 0))
650         }
651     };
652
653     let mut cgu_reuse = Vec::new();
654     let mut pre_compiled_cgus: Option<FxHashMap<usize, _>> = None;
655     let mut total_codegen_time = Duration::new(0, 0);
656     let start_rss = tcx.sess.time_passes().then(|| get_resident_set_size());
657
658     for (i, cgu) in codegen_units.iter().enumerate() {
659         ongoing_codegen.wait_for_signal_to_codegen_item();
660         ongoing_codegen.check_for_errors(tcx.sess);
661
662         // Do some setup work in the first iteration
663         if pre_compiled_cgus.is_none() {
664             // Calculate the CGU reuse
665             cgu_reuse = tcx.sess.time("find_cgu_reuse", || {
666                 codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect()
667             });
668             // Pre compile some CGUs
669             let (compiled_cgus, codegen_time) = pre_compile_cgus(&cgu_reuse);
670             pre_compiled_cgus = Some(compiled_cgus);
671             total_codegen_time += codegen_time;
672         }
673
674         let cgu_reuse = cgu_reuse[i];
675         tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse);
676
677         match cgu_reuse {
678             CguReuse::No => {
679                 let (module, cost) =
680                     if let Some(cgu) = pre_compiled_cgus.as_mut().unwrap().remove(&i) {
681                         cgu
682                     } else {
683                         let start_time = Instant::now();
684                         let module = backend.compile_codegen_unit(tcx, cgu.name());
685                         total_codegen_time += start_time.elapsed();
686                         module
687                     };
688                 // This will unwind if there are errors, which triggers our `AbortCodegenOnDrop`
689                 // guard. Unfortunately, just skipping the `submit_codegened_module_to_llvm` makes
690                 // compilation hang on post-monomorphization errors.
691                 tcx.sess.abort_if_errors();
692
693                 submit_codegened_module_to_llvm(
694                     &backend,
695                     &ongoing_codegen.coordinator_send,
696                     module,
697                     cost,
698                 );
699                 false
700             }
701             CguReuse::PreLto => {
702                 submit_pre_lto_module_to_llvm(
703                     &backend,
704                     tcx,
705                     &ongoing_codegen.coordinator_send,
706                     CachedModuleCodegen {
707                         name: cgu.name().to_string(),
708                         source: cgu.work_product(tcx),
709                     },
710                 );
711                 true
712             }
713             CguReuse::PostLto => {
714                 submit_post_lto_module_to_llvm(
715                     &backend,
716                     &ongoing_codegen.coordinator_send,
717                     CachedModuleCodegen {
718                         name: cgu.name().to_string(),
719                         source: cgu.work_product(tcx),
720                     },
721                 );
722                 true
723             }
724         };
725     }
726
727     ongoing_codegen.codegen_finished(tcx);
728
729     // Since the main thread is sometimes blocked during codegen, we keep track
730     // -Ztime-passes output manually.
731     if tcx.sess.time_passes() {
732         let end_rss = get_resident_set_size();
733
734         print_time_passes_entry(
735             "codegen_to_LLVM_IR",
736             total_codegen_time,
737             start_rss.unwrap(),
738             end_rss,
739         );
740     }
741
742     ongoing_codegen.check_for_errors(tcx.sess);
743
744     ongoing_codegen.into_inner()
745 }
746
747 /// A curious wrapper structure whose only purpose is to call `codegen_aborted`
748 /// when it's dropped abnormally.
749 ///
750 /// In the process of working on rust-lang/rust#55238 a mysterious segfault was
751 /// stumbled upon. The segfault was never reproduced locally, but it was
752 /// suspected to be related to the fact that codegen worker threads were
753 /// sticking around by the time the main thread was exiting, causing issues.
754 ///
755 /// This structure is an attempt to fix that issue where the `codegen_aborted`
756 /// message will block until all workers have finished. This should ensure that
757 /// even if the main codegen thread panics we'll wait for pending work to
758 /// complete before returning from the main thread, hopefully avoiding
759 /// segfaults.
760 ///
761 /// If you see this comment in the code, then it means that this workaround
762 /// worked! We may yet one day track down the mysterious cause of that
763 /// segfault...
764 struct AbortCodegenOnDrop<B: ExtraBackendMethods>(Option<OngoingCodegen<B>>);
765
766 impl<B: ExtraBackendMethods> AbortCodegenOnDrop<B> {
767     fn into_inner(mut self) -> OngoingCodegen<B> {
768         self.0.take().unwrap()
769     }
770 }
771
772 impl<B: ExtraBackendMethods> Deref for AbortCodegenOnDrop<B> {
773     type Target = OngoingCodegen<B>;
774
775     fn deref(&self) -> &OngoingCodegen<B> {
776         self.0.as_ref().unwrap()
777     }
778 }
779
780 impl<B: ExtraBackendMethods> DerefMut for AbortCodegenOnDrop<B> {
781     fn deref_mut(&mut self) -> &mut OngoingCodegen<B> {
782         self.0.as_mut().unwrap()
783     }
784 }
785
786 impl<B: ExtraBackendMethods> Drop for AbortCodegenOnDrop<B> {
787     fn drop(&mut self) {
788         if let Some(codegen) = self.0.take() {
789             codegen.codegen_aborted();
790         }
791     }
792 }
793
794 impl CrateInfo {
795     pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
796         let exported_symbols = tcx
797             .sess
798             .crate_types()
799             .iter()
800             .map(|&c| (c, crate::back::linker::exported_symbols(tcx, c)))
801             .collect();
802         let local_crate_name = tcx.crate_name(LOCAL_CRATE);
803         let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
804         let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
805         let windows_subsystem = subsystem.map(|subsystem| {
806             if subsystem != sym::windows && subsystem != sym::console {
807                 tcx.sess.fatal(&format!(
808                     "invalid windows subsystem `{}`, only \
809                                      `windows` and `console` are allowed",
810                     subsystem
811                 ));
812             }
813             subsystem.to_string()
814         });
815
816         // This list is used when generating the command line to pass through to
817         // system linker. The linker expects undefined symbols on the left of the
818         // command line to be defined in libraries on the right, not the other way
819         // around. For more info, see some comments in the add_used_library function
820         // below.
821         //
822         // In order to get this left-to-right dependency ordering, we use the reverse
823         // postorder of all crates putting the leaves at the right-most positions.
824         let used_crates = tcx
825             .postorder_cnums(())
826             .iter()
827             .rev()
828             .copied()
829             .filter(|&cnum| !tcx.dep_kind(cnum).macros_only())
830             .collect();
831
832         let mut info = CrateInfo {
833             target_cpu,
834             exported_symbols,
835             local_crate_name,
836             compiler_builtins: None,
837             profiler_runtime: None,
838             is_no_builtins: Default::default(),
839             native_libraries: Default::default(),
840             used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(),
841             crate_name: Default::default(),
842             used_crates,
843             used_crate_source: Default::default(),
844             lang_item_to_crate: Default::default(),
845             missing_lang_items: Default::default(),
846             dependency_formats: tcx.dependency_formats(()),
847             windows_subsystem,
848         };
849         let lang_items = tcx.lang_items();
850
851         let crates = tcx.crates(());
852
853         let n_crates = crates.len();
854         info.native_libraries.reserve(n_crates);
855         info.crate_name.reserve(n_crates);
856         info.used_crate_source.reserve(n_crates);
857         info.missing_lang_items.reserve(n_crates);
858
859         for &cnum in crates.iter() {
860             info.native_libraries
861                 .insert(cnum, tcx.native_libraries(cnum).iter().map(Into::into).collect());
862             info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
863             info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
864             if tcx.is_compiler_builtins(cnum) {
865                 info.compiler_builtins = Some(cnum);
866             }
867             if tcx.is_profiler_runtime(cnum) {
868                 info.profiler_runtime = Some(cnum);
869             }
870             if tcx.is_no_builtins(cnum) {
871                 info.is_no_builtins.insert(cnum);
872             }
873             let missing = tcx.missing_lang_items(cnum);
874             for &item in missing.iter() {
875                 if let Ok(id) = lang_items.require(item) {
876                     info.lang_item_to_crate.insert(item, id.krate);
877                 }
878             }
879
880             // No need to look for lang items that don't actually need to exist.
881             let missing =
882                 missing.iter().cloned().filter(|&l| lang_items::required(tcx, l)).collect();
883             info.missing_lang_items.insert(cnum, missing);
884         }
885
886         info
887     }
888 }
889
890 pub fn provide(providers: &mut Providers) {
891     providers.backend_optimization_level = |tcx, cratenum| {
892         let for_speed = match tcx.sess.opts.optimize {
893             // If globally no optimisation is done, #[optimize] has no effect.
894             //
895             // This is done because if we ended up "upgrading" to `-O2` here, we’d populate the
896             // pass manager and it is likely that some module-wide passes (such as inliner or
897             // cross-function constant propagation) would ignore the `optnone` annotation we put
898             // on the functions, thus necessarily involving these functions into optimisations.
899             config::OptLevel::No => return config::OptLevel::No,
900             // If globally optimise-speed is already specified, just use that level.
901             config::OptLevel::Less => return config::OptLevel::Less,
902             config::OptLevel::Default => return config::OptLevel::Default,
903             config::OptLevel::Aggressive => return config::OptLevel::Aggressive,
904             // If globally optimize-for-size has been requested, use -O2 instead (if optimize(size)
905             // are present).
906             config::OptLevel::Size => config::OptLevel::Default,
907             config::OptLevel::SizeMin => config::OptLevel::Default,
908         };
909
910         let (defids, _) = tcx.collect_and_partition_mono_items(cratenum);
911         for id in &*defids {
912             let CodegenFnAttrs { optimize, .. } = tcx.codegen_fn_attrs(*id);
913             match optimize {
914                 attr::OptimizeAttr::None => continue,
915                 attr::OptimizeAttr::Size => continue,
916                 attr::OptimizeAttr::Speed => {
917                     return for_speed;
918                 }
919             }
920         }
921         tcx.sess.opts.optimize
922     };
923 }
924
925 fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguReuse {
926     if !tcx.dep_graph.is_fully_enabled() {
927         return CguReuse::No;
928     }
929
930     let work_product_id = &cgu.work_product_id();
931     if tcx.dep_graph.previous_work_product(work_product_id).is_none() {
932         // We don't have anything cached for this CGU. This can happen
933         // if the CGU did not exist in the previous session.
934         return CguReuse::No;
935     }
936
937     // Try to mark the CGU as green. If it we can do so, it means that nothing
938     // affecting the LLVM module has changed and we can re-use a cached version.
939     // If we compile with any kind of LTO, this means we can re-use the bitcode
940     // of the Pre-LTO stage (possibly also the Post-LTO version but we'll only
941     // know that later). If we are not doing LTO, there is only one optimized
942     // version of each module, so we re-use that.
943     let dep_node = cgu.codegen_dep_node(tcx);
944     assert!(
945         !tcx.dep_graph.dep_node_exists(&dep_node),
946         "CompileCodegenUnit dep-node for CGU `{}` already exists before marking.",
947         cgu.name()
948     );
949
950     if tcx.try_mark_green(&dep_node) {
951         // We can re-use either the pre- or the post-thinlto state. If no LTO is
952         // being performed then we can use post-LTO artifacts, otherwise we must
953         // reuse pre-LTO artifacts
954         match compute_per_cgu_lto_type(
955             &tcx.sess.lto(),
956             &tcx.sess.opts,
957             &tcx.sess.crate_types(),
958             ModuleKind::Regular,
959         ) {
960             ComputedLtoType::No => CguReuse::PostLto,
961             _ => CguReuse::PreLto,
962         }
963     } else {
964         CguReuse::No
965     }
966 }