rustc_interface/
queries.rs1use std::any::Any;
2use std::sync::Arc;
3
4use rustc_codegen_ssa::CodegenResults;
5use rustc_codegen_ssa::traits::CodegenBackend;
6use rustc_data_structures::svh::Svh;
7use rustc_errors::timings::TimingSection;
8use rustc_hir::def_id::LOCAL_CRATE;
9use rustc_metadata::EncodedMetadata;
10use rustc_middle::dep_graph::DepGraph;
11use rustc_middle::ty::TyCtxt;
12use rustc_session::Session;
13use rustc_session::config::{self, OutputFilenames, OutputType};
14
15use crate::errors::FailedWritingFile;
16use crate::passes;
17
18pub struct Linker {
19 dep_graph: DepGraph,
20 output_filenames: Arc<OutputFilenames>,
21 crate_hash: Option<Svh>,
23 metadata: EncodedMetadata,
24 ongoing_codegen: Box<dyn Any>,
25}
26
27impl Linker {
28 pub fn codegen_and_build_linker(
29 tcx: TyCtxt<'_>,
30 codegen_backend: &dyn CodegenBackend,
31 ) -> Linker {
32 let (ongoing_codegen, metadata) = passes::start_codegen(codegen_backend, tcx);
33
34 Linker {
35 dep_graph: tcx.dep_graph.clone(),
36 output_filenames: Arc::clone(tcx.output_filenames(())),
37 crate_hash: if tcx.needs_crate_hash() {
38 Some(tcx.crate_hash(LOCAL_CRATE))
39 } else {
40 None
41 },
42 metadata,
43 ongoing_codegen,
44 }
45 }
46
47 pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) {
48 let (codegen_results, work_products) = sess.time("finish_ongoing_codegen", || {
49 codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames)
50 });
51
52 sess.dcx().abort_if_errors();
53
54 let _timer = sess.timer("link");
55
56 sess.time("serialize_work_products", || {
57 rustc_incremental::save_work_product_index(sess, &self.dep_graph, work_products)
58 });
59
60 let prof = sess.prof.clone();
61 prof.generic_activity("drop_dep_graph").run(move || drop(self.dep_graph));
62
63 rustc_incremental::finalize_session_directory(sess, self.crate_hash);
66
67 if !sess
68 .opts
69 .output_types
70 .keys()
71 .any(|&i| i == OutputType::Exe || i == OutputType::Metadata)
72 {
73 return;
74 }
75
76 if sess.opts.unstable_opts.no_link {
77 let rlink_file = self.output_filenames.with_extension(config::RLINK_EXT);
78 CodegenResults::serialize_rlink(
79 sess,
80 &rlink_file,
81 &codegen_results,
82 &self.metadata,
83 &*self.output_filenames,
84 )
85 .unwrap_or_else(|error| {
86 sess.dcx().emit_fatal(FailedWritingFile { path: &rlink_file, error })
87 });
88 return;
89 }
90
91 let _timer = sess.prof.verbose_generic_activity("link_crate");
92 let _timing = sess.timings.start_section(sess.dcx(), TimingSection::Linking);
93 codegen_backend.link(sess, codegen_results, self.metadata, &self.output_filenames)
94 }
95}