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