1 //! Codegen the completed AST to the LLVM IR.
3 //! Some functions here, such as `codegen_block` and `codegen_expr`, return a value --
4 //! the result of the codegen to LLVM -- while others, such as `codegen_fn`
5 //! and `mono_item`, are called only for the side effect of adding a
6 //! particular definition to the LLVM IR output we're producing.
8 //! Hopefully useful general knowledge about codegen:
10 //! * There's no way to find out the `Ty` type of a `Value`. Doing so
11 //! would be "trying to get the eggs out of an omelette" (credit:
12 //! pcwalton). You can, instead, find out its `llvm::Type` by calling `val_ty`,
13 //! but one `llvm::Type` corresponds to many `Ty`s; for instance, `tup(int, int,
14 //! int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`.
16 use crate::back
::write
::{
17 compute_per_cgu_lto_type
, start_async_codegen
, submit_codegened_module_to_llvm
,
18 submit_post_lto_module_to_llvm
, submit_pre_lto_module_to_llvm
, ComputedLtoType
, OngoingCodegen
,
20 use crate::common
::{IntPredicate, RealPredicate, TypeKind}
;
23 use crate::mir
::operand
::OperandValue
;
24 use crate::mir
::place
::PlaceRef
;
26 use crate::{CachedModuleCodegen, CrateInfo, MemFlags, ModuleCodegen, ModuleKind}
;
28 use rustc_attr
as attr
;
29 use rustc_data_structures
::fx
::FxHashMap
;
30 use rustc_data_structures
::profiling
::print_time_passes_entry
;
31 use rustc_data_structures
::sync
::{par_iter, Lock, ParallelIterator}
;
33 use rustc_hir
::def_id
::{LocalDefId, LOCAL_CRATE}
;
34 use rustc_hir
::lang_items
::LangItem
;
35 use rustc_index
::vec
::Idx
;
36 use rustc_middle
::middle
::codegen_fn_attrs
::CodegenFnAttrs
;
37 use rustc_middle
::middle
::cstore
::EncodedMetadata
;
38 use rustc_middle
::middle
::cstore
::{self, LinkagePreference}
;
39 use rustc_middle
::middle
::lang_items
;
40 use rustc_middle
::mir
::mono
::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}
;
41 use rustc_middle
::ty
::layout
::{HasTyCtxt, TyAndLayout}
;
42 use rustc_middle
::ty
::layout
::{FAT_PTR_ADDR, FAT_PTR_EXTRA}
;
43 use rustc_middle
::ty
::query
::Providers
;
44 use rustc_middle
::ty
::{self, Instance, Ty, TyCtxt}
;
45 use rustc_session
::cgu_reuse_tracker
::CguReuse
;
46 use rustc_session
::config
::{self, EntryFnType}
;
47 use rustc_session
::utils
::NativeLibKind
;
48 use rustc_session
::Session
;
49 use rustc_symbol_mangling
::test
as symbol_names_test
;
50 use rustc_target
::abi
::{Align, LayoutOf, VariantIdx}
;
53 use std
::ops
::{Deref, DerefMut}
;
54 use std
::time
::{Duration, Instant}
;
56 pub fn bin_op_to_icmp_predicate(op
: hir
::BinOpKind
, signed
: bool
) -> IntPredicate
{
58 hir
::BinOpKind
::Eq
=> IntPredicate
::IntEQ
,
59 hir
::BinOpKind
::Ne
=> IntPredicate
::IntNE
,
60 hir
::BinOpKind
::Lt
=> {
67 hir
::BinOpKind
::Le
=> {
74 hir
::BinOpKind
::Gt
=> {
81 hir
::BinOpKind
::Ge
=> {
89 "comparison_op_to_icmp_predicate: expected comparison operator, \
96 pub fn bin_op_to_fcmp_predicate(op
: hir
::BinOpKind
) -> RealPredicate
{
98 hir
::BinOpKind
::Eq
=> RealPredicate
::RealOEQ
,
99 hir
::BinOpKind
::Ne
=> RealPredicate
::RealUNE
,
100 hir
::BinOpKind
::Lt
=> RealPredicate
::RealOLT
,
101 hir
::BinOpKind
::Le
=> RealPredicate
::RealOLE
,
102 hir
::BinOpKind
::Gt
=> RealPredicate
::RealOGT
,
103 hir
::BinOpKind
::Ge
=> RealPredicate
::RealOGE
,
106 "comparison_op_to_fcmp_predicate: expected comparison operator, \
114 pub fn compare_simd_types
<'a
, 'tcx
, Bx
: BuilderMethods
<'a
, 'tcx
>>(
122 let signed
= match t
.kind() {
124 let cmp
= bin_op_to_fcmp_predicate(op
);
125 let cmp
= bx
.fcmp(cmp
, lhs
, rhs
);
126 return bx
.sext(cmp
, ret_ty
);
128 ty
::Uint(_
) => false,
130 _
=> bug
!("compare_simd_types: invalid SIMD type"),
133 let cmp
= bin_op_to_icmp_predicate(op
, signed
);
134 let cmp
= bx
.icmp(cmp
, lhs
, rhs
);
135 // LLVM outputs an `< size x i1 >`, so we need to perform a sign extension
136 // to get the correctly sized type. This will compile to a single instruction
137 // once the IR is converted to assembly if the SIMD instruction is supported
138 // by the target architecture.
142 /// Retrieves the information we are losing (making dynamic) in an unsizing
145 /// The `old_info` argument is a bit odd. It is intended for use in an upcast,
146 /// where the new vtable for an object will be derived from the old one.
147 pub fn unsized_info
<'tcx
, Cx
: CodegenMethods
<'tcx
>>(
151 old_info
: Option
<Cx
::Value
>,
153 let (source
, target
) =
154 cx
.tcx().struct_lockstep_tails_erasing_lifetimes(source
, target
, cx
.param_env());
155 match (source
.kind(), target
.kind()) {
156 (&ty
::Array(_
, len
), &ty
::Slice(_
)) => {
157 cx
.const_usize(len
.eval_usize(cx
.tcx(), ty
::ParamEnv
::reveal_all()))
159 (&ty
::Dynamic(..), &ty
::Dynamic(..)) => {
160 // For now, upcasts are limited to changes in marker
161 // traits, and hence never actually require an actual
162 // change to the vtable.
163 old_info
.expect("unsized_info: missing old info for trait upcast")
165 (_
, &ty
::Dynamic(ref data
, ..)) => {
166 let vtable_ptr
= cx
.layout_of(cx
.tcx().mk_mut_ptr(target
)).field(cx
, FAT_PTR_EXTRA
);
168 meth
::get_vtable(cx
, source
, data
.principal()),
169 cx
.backend_type(vtable_ptr
),
172 _
=> bug
!("unsized_info: invalid unsizing {:?} -> {:?}", source
, target
),
176 /// Coerces `src` to `dst_ty`. `src_ty` must be a thin pointer.
177 pub fn unsize_thin_ptr
<'a
, 'tcx
, Bx
: BuilderMethods
<'a
, 'tcx
>>(
182 ) -> (Bx
::Value
, Bx
::Value
) {
183 debug
!("unsize_thin_ptr: {:?} => {:?}", src_ty
, dst_ty
);
184 match (src_ty
.kind(), dst_ty
.kind()) {
185 (&ty
::Ref(_
, a
, _
), &ty
::Ref(_
, b
, _
) | &ty
::RawPtr(ty
::TypeAndMut { ty: b, .. }
))
186 | (&ty
::RawPtr(ty
::TypeAndMut { ty: a, .. }
), &ty
::RawPtr(ty
::TypeAndMut { ty: b, .. }
)) => {
187 assert
!(bx
.cx().type_is_sized(a
));
188 let ptr_ty
= bx
.cx().type_ptr_to(bx
.cx().backend_type(bx
.cx().layout_of(b
)));
189 (bx
.pointercast(src
, ptr_ty
), unsized_info(bx
.cx(), a
, b
, None
))
191 (&ty
::Adt(def_a
, _
), &ty
::Adt(def_b
, _
)) => {
192 assert_eq
!(def_a
, def_b
);
194 let src_layout
= bx
.cx().layout_of(src_ty
);
195 let dst_layout
= bx
.cx().layout_of(dst_ty
);
196 let mut result
= None
;
197 for i
in 0..src_layout
.fields
.count() {
198 let src_f
= src_layout
.field(bx
.cx(), i
);
199 assert_eq
!(src_layout
.fields
.offset(i
).bytes(), 0);
200 assert_eq
!(dst_layout
.fields
.offset(i
).bytes(), 0);
204 assert_eq
!(src_layout
.size
, src_f
.size
);
206 let dst_f
= dst_layout
.field(bx
.cx(), i
);
207 assert_ne
!(src_f
.ty
, dst_f
.ty
);
208 assert_eq
!(result
, None
);
209 result
= Some(unsize_thin_ptr(bx
, src
, src_f
.ty
, dst_f
.ty
));
211 let (lldata
, llextra
) = result
.unwrap();
212 // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
213 // FIXME(eddyb) move these out of this `match` arm, so they're always
214 // applied, uniformly, no matter the source/destination types.
216 bx
.bitcast(lldata
, bx
.cx().scalar_pair_element_backend_type(dst_layout
, 0, true)),
217 bx
.bitcast(llextra
, bx
.cx().scalar_pair_element_backend_type(dst_layout
, 1, true)),
220 _
=> bug
!("unsize_thin_ptr: called on bad types"),
224 /// Coerces `src`, which is a reference to a value of type `src_ty`,
225 /// to a value of type `dst_ty`, and stores the result in `dst`.
226 pub fn coerce_unsized_into
<'a
, 'tcx
, Bx
: BuilderMethods
<'a
, 'tcx
>>(
228 src
: PlaceRef
<'tcx
, Bx
::Value
>,
229 dst
: PlaceRef
<'tcx
, Bx
::Value
>,
231 let src_ty
= src
.layout
.ty
;
232 let dst_ty
= dst
.layout
.ty
;
233 match (src_ty
.kind(), dst_ty
.kind()) {
234 (&ty
::Ref(..), &ty
::Ref(..) | &ty
::RawPtr(..)) | (&ty
::RawPtr(..), &ty
::RawPtr(..)) => {
235 let (base
, info
) = match bx
.load_operand(src
).val
{
236 OperandValue
::Pair(base
, info
) => {
237 // fat-ptr to fat-ptr unsize preserves the vtable
238 // i.e., &'a fmt::Debug+Send => &'a fmt::Debug
239 // So we need to pointercast the base to ensure
240 // the types match up.
241 // FIXME(eddyb) use `scalar_pair_element_backend_type` here,
242 // like `unsize_thin_ptr` does.
243 let thin_ptr
= dst
.layout
.field(bx
.cx(), FAT_PTR_ADDR
);
244 (bx
.pointercast(base
, bx
.cx().backend_type(thin_ptr
)), info
)
246 OperandValue
::Immediate(base
) => unsize_thin_ptr(bx
, base
, src_ty
, dst_ty
),
247 OperandValue
::Ref(..) => bug
!(),
249 OperandValue
::Pair(base
, info
).store(bx
, dst
);
252 (&ty
::Adt(def_a
, _
), &ty
::Adt(def_b
, _
)) => {
253 assert_eq
!(def_a
, def_b
);
255 for i
in 0..def_a
.variants
[VariantIdx
::new(0)].fields
.len() {
256 let src_f
= src
.project_field(bx
, i
);
257 let dst_f
= dst
.project_field(bx
, i
);
259 if dst_f
.layout
.is_zst() {
263 if src_f
.layout
.ty
== dst_f
.layout
.ty
{
274 coerce_unsized_into(bx
, src_f
, dst_f
);
278 _
=> bug
!("coerce_unsized_into: invalid coercion {:?} -> {:?}", src_ty
, dst_ty
,),
282 pub fn cast_shift_expr_rhs
<'a
, 'tcx
, Bx
: BuilderMethods
<'a
, 'tcx
>>(
288 cast_shift_rhs(bx
, op
, lhs
, rhs
)
291 fn cast_shift_rhs
<'a
, 'tcx
, Bx
: BuilderMethods
<'a
, 'tcx
>>(
297 // Shifts may have any size int on the rhs
299 let mut rhs_llty
= bx
.cx().val_ty(rhs
);
300 let mut lhs_llty
= bx
.cx().val_ty(lhs
);
301 if bx
.cx().type_kind(rhs_llty
) == TypeKind
::Vector
{
302 rhs_llty
= bx
.cx().element_type(rhs_llty
)
304 if bx
.cx().type_kind(lhs_llty
) == TypeKind
::Vector
{
305 lhs_llty
= bx
.cx().element_type(lhs_llty
)
307 let rhs_sz
= bx
.cx().int_width(rhs_llty
);
308 let lhs_sz
= bx
.cx().int_width(lhs_llty
);
310 bx
.trunc(rhs
, lhs_llty
)
311 } else if lhs_sz
> rhs_sz
{
312 // FIXME (#1877: If in the future shifting by negative
313 // values is no longer undefined then this is wrong.
314 bx
.zext(rhs
, lhs_llty
)
323 /// Returns `true` if this session's target will use SEH-based unwinding.
325 /// This is only true for MSVC targets, and even then the 64-bit MSVC target
326 /// currently uses SEH-ish unwinding with DWARF info tables to the side (same as
327 /// 64-bit MinGW) instead of "full SEH".
328 pub fn wants_msvc_seh(sess
: &Session
) -> bool
{
329 sess
.target
.is_like_msvc
332 pub fn memcpy_ty
<'a
, 'tcx
, Bx
: BuilderMethods
<'a
, 'tcx
>>(
338 layout
: TyAndLayout
<'tcx
>,
341 let size
= layout
.size
.bytes();
346 bx
.memcpy(dst
, dst_align
, src
, src_align
, bx
.cx().const_usize(size
), flags
);
349 pub fn codegen_instance
<'a
, 'tcx
: 'a
, Bx
: BuilderMethods
<'a
, 'tcx
>>(
350 cx
: &'a Bx
::CodegenCx
,
351 instance
: Instance
<'tcx
>,
353 // this is an info! to allow collecting monomorphization statistics
354 // and to allow finding the last function before LLVM aborts from
356 info
!("codegen_instance({})", instance
);
358 mir
::codegen_mir
::<Bx
>(cx
, instance
);
361 /// Creates the `main` function which will initialize the rust runtime and call
362 /// users main function.
363 pub fn maybe_create_entry_wrapper
<'a
, 'tcx
, Bx
: BuilderMethods
<'a
, 'tcx
>>(
364 cx
: &'a Bx
::CodegenCx
,
365 ) -> Option
<Bx
::Function
> {
366 let main_def_id
= cx
.tcx().entry_fn(LOCAL_CRATE
).map(|(def_id
, _
)| def_id
)?
;
367 let instance
= Instance
::mono(cx
.tcx(), main_def_id
.to_def_id());
369 if !cx
.codegen_unit().contains_item(&MonoItem
::Fn(instance
)) {
370 // We want to create the wrapper in the same codegen unit as Rust's main
375 let main_llfn
= cx
.get_fn_addr(instance
);
377 return cx
.tcx().entry_fn(LOCAL_CRATE
).map(|(_
, et
)| {
378 let use_start_lang_item
= EntryFnType
::Start
!= et
;
379 create_entry_fn
::<Bx
>(cx
, main_llfn
, main_def_id
, use_start_lang_item
)
382 fn create_entry_fn
<'a
, 'tcx
, Bx
: BuilderMethods
<'a
, 'tcx
>>(
383 cx
: &'a Bx
::CodegenCx
,
384 rust_main
: Bx
::Value
,
385 rust_main_def_id
: LocalDefId
,
386 use_start_lang_item
: bool
,
388 // The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
389 // depending on whether the target needs `argc` and `argv` to be passed in.
390 let llfty
= if cx
.sess().target
.main_needs_argc_argv
{
391 cx
.type_func(&[cx
.type_int(), cx
.type_ptr_to(cx
.type_i8p())], cx
.type_int())
393 cx
.type_func(&[], cx
.type_int())
396 let main_ret_ty
= cx
.tcx().fn_sig(rust_main_def_id
).output();
397 // Given that `main()` has no arguments,
398 // then its return type cannot have
399 // late-bound regions, since late-bound
400 // regions must appear in the argument
402 let main_ret_ty
= cx
.tcx().erase_regions(&main_ret_ty
.no_bound_vars().unwrap());
404 let llfn
= match cx
.declare_c_main(llfty
) {
407 // FIXME: We should be smart and show a better diagnostic here.
408 let span
= cx
.tcx().def_span(rust_main_def_id
);
410 .struct_span_err(span
, "entry symbol `main` declared multiple times")
411 .help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead")
413 cx
.sess().abort_if_errors();
418 // `main` should respect same config for frame pointer elimination as rest of code
419 cx
.set_frame_pointer_elimination(llfn
);
420 cx
.apply_target_cpu_attr(llfn
);
422 let mut bx
= Bx
::new_block(&cx
, llfn
, "top");
424 bx
.insert_reference_to_gdb_debug_scripts_section_global();
426 let (arg_argc
, arg_argv
) = get_argc_argv(cx
, &mut bx
);
428 let (start_fn
, args
) = if use_start_lang_item
{
429 let start_def_id
= cx
.tcx().require_lang_item(LangItem
::Start
, None
);
430 let start_fn
= cx
.get_fn_addr(
431 ty
::Instance
::resolve(
433 ty
::ParamEnv
::reveal_all(),
435 cx
.tcx().intern_substs(&[main_ret_ty
.into()]),
442 vec
![bx
.pointercast(rust_main
, cx
.type_ptr_to(cx
.type_i8p())), arg_argc
, arg_argv
],
445 debug
!("using user-defined start fn");
446 (rust_main
, vec
![arg_argc
, arg_argv
])
449 let result
= bx
.call(start_fn
, &args
, None
);
450 let cast
= bx
.intcast(result
, cx
.type_int(), true);
457 /// Obtain the `argc` and `argv` values to pass to the rust start function.
458 fn get_argc_argv
<'a
, 'tcx
, Bx
: BuilderMethods
<'a
, 'tcx
>>(
459 cx
: &'a Bx
::CodegenCx
,
461 ) -> (Bx
::Value
, Bx
::Value
) {
462 if cx
.sess().target
.main_needs_argc_argv
{
463 // Params from native `main()` used as args for rust start function
464 let param_argc
= bx
.get_param(0);
465 let param_argv
= bx
.get_param(1);
466 let arg_argc
= bx
.intcast(param_argc
, cx
.type_isize(), true);
467 let arg_argv
= param_argv
;
470 // The Rust start function doesn't need `argc` and `argv`, so just pass zeros.
471 let arg_argc
= bx
.const_int(cx
.type_int(), 0);
472 let arg_argv
= bx
.const_null(cx
.type_ptr_to(cx
.type_i8p()));
477 pub fn codegen_crate
<B
: ExtraBackendMethods
>(
480 metadata
: EncodedMetadata
,
481 need_metadata_module
: bool
,
482 ) -> OngoingCodegen
<B
> {
483 // Skip crate items and just output metadata in -Z no-codegen mode.
484 if tcx
.sess
.opts
.debugging_opts
.no_codegen
|| !tcx
.sess
.opts
.output_types
.should_codegen() {
485 let ongoing_codegen
= start_async_codegen(backend
, tcx
, metadata
, 1);
487 ongoing_codegen
.codegen_finished(tcx
);
491 ongoing_codegen
.check_for_errors(tcx
.sess
);
493 return ongoing_codegen
;
496 let cgu_name_builder
= &mut CodegenUnitNameBuilder
::new(tcx
);
498 // Run the monomorphization collector and partition the collected items into
500 let codegen_units
= tcx
.collect_and_partition_mono_items(LOCAL_CRATE
).1;
502 // Force all codegen_unit queries so they are already either red or green
503 // when compile_codegen_unit accesses them. We are not able to re-execute
504 // the codegen_unit query from just the DepNode, so an unknown color would
505 // lead to having to re-execute compile_codegen_unit, possibly
507 if tcx
.dep_graph
.is_fully_enabled() {
508 for cgu
in codegen_units
{
509 tcx
.ensure().codegen_unit(cgu
.name());
513 let ongoing_codegen
= start_async_codegen(backend
.clone(), tcx
, metadata
, codegen_units
.len());
514 let ongoing_codegen
= AbortCodegenOnDrop
::<B
>(Some(ongoing_codegen
));
516 // Codegen an allocator shim, if necessary.
518 // If the crate doesn't have an `allocator_kind` set then there's definitely
519 // no shim to generate. Otherwise we also check our dependency graph for all
520 // our output crate types. If anything there looks like its a `Dynamic`
521 // linkage, then it's already got an allocator shim and we'll be using that
522 // one instead. If nothing exists then it's our job to generate the
524 let any_dynamic_crate
= tcx
.dependency_formats(LOCAL_CRATE
).iter().any(|(_
, list
)| {
525 use rustc_middle
::middle
::dependency_format
::Linkage
;
526 list
.iter().any(|&linkage
| linkage
== Linkage
::Dynamic
)
528 let allocator_module
= if any_dynamic_crate
{
530 } else if let Some(kind
) = tcx
.allocator_kind() {
532 cgu_name_builder
.build_cgu_name(LOCAL_CRATE
, &["crate"], Some("allocator")).to_string();
533 let mut modules
= backend
.new_metadata(tcx
, &llmod_id
);
534 tcx
.sess
.time("write_allocator_module", || {
535 backend
.codegen_allocator(tcx
, &mut modules
, kind
, tcx
.lang_items().oom().is_some())
538 Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator }
)
543 if let Some(allocator_module
) = allocator_module
{
544 ongoing_codegen
.submit_pre_codegened_module_to_llvm(tcx
, allocator_module
);
547 if need_metadata_module
{
548 // Codegen the encoded metadata.
549 let metadata_cgu_name
=
550 cgu_name_builder
.build_cgu_name(LOCAL_CRATE
, &["crate"], Some("metadata")).to_string();
551 let mut metadata_llvm_module
= backend
.new_metadata(tcx
, &metadata_cgu_name
);
552 tcx
.sess
.time("write_compressed_metadata", || {
553 backend
.write_compressed_metadata(
555 &ongoing_codegen
.metadata
,
556 &mut metadata_llvm_module
,
560 let metadata_module
= ModuleCodegen
{
561 name
: metadata_cgu_name
,
562 module_llvm
: metadata_llvm_module
,
563 kind
: ModuleKind
::Metadata
,
565 ongoing_codegen
.submit_pre_codegened_module_to_llvm(tcx
, metadata_module
);
568 // We sort the codegen units by size. This way we can schedule work for LLVM
569 // a bit more efficiently.
570 let codegen_units
= {
571 let mut codegen_units
= codegen_units
.iter().collect
::<Vec
<_
>>();
572 codegen_units
.sort_by_cached_key(|cgu
| cmp
::Reverse(cgu
.size_estimate()));
576 let total_codegen_time
= Lock
::new(Duration
::new(0, 0));
578 // The non-parallel compiler can only translate codegen units to LLVM IR
579 // on a single thread, leading to a staircase effect where the N LLVM
580 // threads have to wait on the single codegen threads to generate work
581 // for them. The parallel compiler does not have this restriction, so
582 // we can pre-load the LLVM queue in parallel before handing off
583 // coordination to the OnGoingCodegen scheduler.
585 // This likely is a temporary measure. Once we don't have to support the
586 // non-parallel compiler anymore, we can compile CGUs end-to-end in
587 // parallel and get rid of the complicated scheduling logic.
588 let pre_compile_cgus
= |cgu_reuse
: &[CguReuse
]| {
589 if cfg
!(parallel_compiler
) {
590 tcx
.sess
.time("compile_first_CGU_batch", || {
591 // Try to find one CGU to compile per thread.
592 let cgus
: Vec
<_
> = cgu_reuse
595 .filter(|&(_
, reuse
)| reuse
== &CguReuse
::No
)
596 .take(tcx
.sess
.threads())
599 // Compile the found CGUs in parallel.
602 let start_time
= Instant
::now();
603 let module
= backend
.compile_codegen_unit(tcx
, codegen_units
[i
].name());
604 let mut time
= total_codegen_time
.lock();
605 *time
+= start_time
.elapsed();
615 let mut cgu_reuse
= Vec
::new();
616 let mut pre_compiled_cgus
: Option
<FxHashMap
<usize, _
>> = None
;
618 for (i
, cgu
) in codegen_units
.iter().enumerate() {
619 ongoing_codegen
.wait_for_signal_to_codegen_item();
620 ongoing_codegen
.check_for_errors(tcx
.sess
);
622 // Do some setup work in the first iteration
623 if pre_compiled_cgus
.is_none() {
624 // Calculate the CGU reuse
625 cgu_reuse
= tcx
.sess
.time("find_cgu_reuse", || {
626 codegen_units
.iter().map(|cgu
| determine_cgu_reuse(tcx
, &cgu
)).collect()
628 // Pre compile some CGUs
629 pre_compiled_cgus
= Some(pre_compile_cgus(&cgu_reuse
));
632 let cgu_reuse
= cgu_reuse
[i
];
633 tcx
.sess
.cgu_reuse_tracker
.set_actual_reuse(&cgu
.name().as_str(), cgu_reuse
);
638 if let Some(cgu
) = pre_compiled_cgus
.as_mut().unwrap().remove(&i
) {
641 let start_time
= Instant
::now();
642 let module
= backend
.compile_codegen_unit(tcx
, cgu
.name());
643 let mut time
= total_codegen_time
.lock();
644 *time
+= start_time
.elapsed();
647 submit_codegened_module_to_llvm(
649 &ongoing_codegen
.coordinator_send
,
655 CguReuse
::PreLto
=> {
656 submit_pre_lto_module_to_llvm(
659 &ongoing_codegen
.coordinator_send
,
660 CachedModuleCodegen
{
661 name
: cgu
.name().to_string(),
662 source
: cgu
.work_product(tcx
),
667 CguReuse
::PostLto
=> {
668 submit_post_lto_module_to_llvm(
670 &ongoing_codegen
.coordinator_send
,
671 CachedModuleCodegen
{
672 name
: cgu
.name().to_string(),
673 source
: cgu
.work_product(tcx
),
681 ongoing_codegen
.codegen_finished(tcx
);
683 // Since the main thread is sometimes blocked during codegen, we keep track
684 // -Ztime-passes output manually.
685 print_time_passes_entry(
686 tcx
.sess
.time_passes(),
687 "codegen_to_LLVM_IR",
688 total_codegen_time
.into_inner(),
691 rustc_incremental
::assert_module_sources
::assert_module_sources(tcx
);
693 symbol_names_test
::report_symbol_names(tcx
);
695 ongoing_codegen
.check_for_errors(tcx
.sess
);
699 ongoing_codegen
.into_inner()
702 /// A curious wrapper structure whose only purpose is to call `codegen_aborted`
703 /// when it's dropped abnormally.
705 /// In the process of working on rust-lang/rust#55238 a mysterious segfault was
706 /// stumbled upon. The segfault was never reproduced locally, but it was
707 /// suspected to be related to the fact that codegen worker threads were
708 /// sticking around by the time the main thread was exiting, causing issues.
710 /// This structure is an attempt to fix that issue where the `codegen_aborted`
711 /// message will block until all workers have finished. This should ensure that
712 /// even if the main codegen thread panics we'll wait for pending work to
713 /// complete before returning from the main thread, hopefully avoiding
716 /// If you see this comment in the code, then it means that this workaround
717 /// worked! We may yet one day track down the mysterious cause of that
719 struct AbortCodegenOnDrop
<B
: ExtraBackendMethods
>(Option
<OngoingCodegen
<B
>>);
721 impl<B
: ExtraBackendMethods
> AbortCodegenOnDrop
<B
> {
722 fn into_inner(mut self) -> OngoingCodegen
<B
> {
723 self.0.take().unwrap()
727 impl<B
: ExtraBackendMethods
> Deref
for AbortCodegenOnDrop
<B
> {
728 type Target
= OngoingCodegen
<B
>;
730 fn deref(&self) -> &OngoingCodegen
<B
> {
731 self.0.as_ref().unwrap()
735 impl<B
: ExtraBackendMethods
> DerefMut
for AbortCodegenOnDrop
<B
> {
736 fn deref_mut(&mut self) -> &mut OngoingCodegen
<B
> {
737 self.0.as_mut().unwrap()
741 impl<B
: ExtraBackendMethods
> Drop
for AbortCodegenOnDrop
<B
> {
743 if let Some(codegen
) = self.0.take() {
744 codegen
.codegen_aborted();
749 fn finalize_tcx(tcx
: TyCtxt
<'_
>) {
750 tcx
.sess
.time("assert_dep_graph", || rustc_incremental
::assert_dep_graph(tcx
));
751 tcx
.sess
.time("serialize_dep_graph", || rustc_incremental
::save_dep_graph(tcx
));
753 // We assume that no queries are run past here. If there are new queries
754 // after this point, they'll show up as "<unknown>" in self-profiling data.
756 let _prof_timer
= tcx
.prof
.generic_activity("self_profile_alloc_query_strings");
757 tcx
.alloc_self_profile_query_strings();
762 pub fn new(tcx
: TyCtxt
<'_
>) -> CrateInfo
{
763 let mut info
= CrateInfo
{
765 compiler_builtins
: None
,
766 profiler_runtime
: None
,
767 is_no_builtins
: Default
::default(),
768 native_libraries
: Default
::default(),
769 used_libraries
: tcx
.native_libraries(LOCAL_CRATE
),
770 link_args
: tcx
.link_args(LOCAL_CRATE
),
771 crate_name
: Default
::default(),
772 used_crates_dynamic
: cstore
::used_crates(tcx
, LinkagePreference
::RequireDynamic
),
773 used_crates_static
: cstore
::used_crates(tcx
, LinkagePreference
::RequireStatic
),
774 used_crate_source
: Default
::default(),
775 lang_item_to_crate
: Default
::default(),
776 missing_lang_items
: Default
::default(),
777 dependency_formats
: tcx
.dependency_formats(LOCAL_CRATE
),
779 let lang_items
= tcx
.lang_items();
781 let crates
= tcx
.crates();
783 let n_crates
= crates
.len();
784 info
.native_libraries
.reserve(n_crates
);
785 info
.crate_name
.reserve(n_crates
);
786 info
.used_crate_source
.reserve(n_crates
);
787 info
.missing_lang_items
.reserve(n_crates
);
789 for &cnum
in crates
.iter() {
790 info
.native_libraries
.insert(cnum
, tcx
.native_libraries(cnum
));
791 info
.crate_name
.insert(cnum
, tcx
.crate_name(cnum
).to_string());
792 info
.used_crate_source
.insert(cnum
, tcx
.used_crate_source(cnum
));
793 if tcx
.is_panic_runtime(cnum
) {
794 info
.panic_runtime
= Some(cnum
);
796 if tcx
.is_compiler_builtins(cnum
) {
797 info
.compiler_builtins
= Some(cnum
);
799 if tcx
.is_profiler_runtime(cnum
) {
800 info
.profiler_runtime
= Some(cnum
);
802 if tcx
.is_no_builtins(cnum
) {
803 info
.is_no_builtins
.insert(cnum
);
805 let missing
= tcx
.missing_lang_items(cnum
);
806 for &item
in missing
.iter() {
807 if let Ok(id
) = lang_items
.require(item
) {
808 info
.lang_item_to_crate
.insert(item
, id
.krate
);
812 // No need to look for lang items that don't actually need to exist.
814 missing
.iter().cloned().filter(|&l
| lang_items
::required(tcx
, l
)).collect();
815 info
.missing_lang_items
.insert(cnum
, missing
);
822 pub fn provide_both(providers
: &mut Providers
) {
823 providers
.backend_optimization_level
= |tcx
, cratenum
| {
824 let for_speed
= match tcx
.sess
.opts
.optimize
{
825 // If globally no optimisation is done, #[optimize] has no effect.
827 // This is done because if we ended up "upgrading" to `-O2` here, we’d populate the
828 // pass manager and it is likely that some module-wide passes (such as inliner or
829 // cross-function constant propagation) would ignore the `optnone` annotation we put
830 // on the functions, thus necessarily involving these functions into optimisations.
831 config
::OptLevel
::No
=> return config
::OptLevel
::No
,
832 // If globally optimise-speed is already specified, just use that level.
833 config
::OptLevel
::Less
=> return config
::OptLevel
::Less
,
834 config
::OptLevel
::Default
=> return config
::OptLevel
::Default
,
835 config
::OptLevel
::Aggressive
=> return config
::OptLevel
::Aggressive
,
836 // If globally optimize-for-size has been requested, use -O2 instead (if optimize(size)
838 config
::OptLevel
::Size
=> config
::OptLevel
::Default
,
839 config
::OptLevel
::SizeMin
=> config
::OptLevel
::Default
,
842 let (defids
, _
) = tcx
.collect_and_partition_mono_items(cratenum
);
844 let CodegenFnAttrs { optimize, .. }
= tcx
.codegen_fn_attrs(*id
);
846 attr
::OptimizeAttr
::None
=> continue,
847 attr
::OptimizeAttr
::Size
=> continue,
848 attr
::OptimizeAttr
::Speed
=> {
853 tcx
.sess
.opts
.optimize
856 providers
.dllimport_foreign_items
= |tcx
, krate
| {
857 let module_map
= tcx
.foreign_modules(krate
);
860 .native_libraries(krate
)
863 if !matches
!(lib
.kind
, NativeLibKind
::Dylib
| NativeLibKind
::Unspecified
) {
866 let cfg
= match lib
.cfg
{
867 Some(ref cfg
) => cfg
,
870 attr
::cfg_matches(cfg
, &tcx
.sess
.parse_sess
, None
)
872 .filter_map(|lib
| lib
.foreign_module
)
873 .map(|id
| &module_map
[&id
])
874 .flat_map(|module
| module
.foreign_items
.iter().cloned())
879 providers
.is_dllimport_foreign_item
=
880 |tcx
, def_id
| tcx
.dllimport_foreign_items(def_id
.krate
).contains(&def_id
);
883 fn determine_cgu_reuse
<'tcx
>(tcx
: TyCtxt
<'tcx
>, cgu
: &CodegenUnit
<'tcx
>) -> CguReuse
{
884 if !tcx
.dep_graph
.is_fully_enabled() {
888 let work_product_id
= &cgu
.work_product_id();
889 if tcx
.dep_graph
.previous_work_product(work_product_id
).is_none() {
890 // We don't have anything cached for this CGU. This can happen
891 // if the CGU did not exist in the previous session.
895 // Try to mark the CGU as green. If it we can do so, it means that nothing
896 // affecting the LLVM module has changed and we can re-use a cached version.
897 // If we compile with any kind of LTO, this means we can re-use the bitcode
898 // of the Pre-LTO stage (possibly also the Post-LTO version but we'll only
899 // know that later). If we are not doing LTO, there is only one optimized
900 // version of each module, so we re-use that.
901 let dep_node
= cgu
.codegen_dep_node(tcx
);
903 !tcx
.dep_graph
.dep_node_exists(&dep_node
),
904 "CompileCodegenUnit dep-node for CGU `{}` already exists before marking.",
908 if tcx
.dep_graph
.try_mark_green(tcx
, &dep_node
).is_some() {
909 // We can re-use either the pre- or the post-thinlto state. If no LTO is
910 // being performed then we can use post-LTO artifacts, otherwise we must
911 // reuse pre-LTO artifacts
912 match compute_per_cgu_lto_type(
915 &tcx
.sess
.crate_types(),
918 ComputedLtoType
::No
=> CguReuse
::PostLto
,
919 _
=> CguReuse
::PreLto
,