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