]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_trans/base.rs
Rollup merge of #41249 - GuillaumeGomez:rustdoc-render, r=steveklabnik,frewsxcv
[rust.git] / src / librustc_trans / base.rs
index a034974cb13edd1f4bff79a1cdf5d18dbe58f499..c770bbdb90f72569b46571cb3d18d769d4f395a9 100644 (file)
@@ -38,7 +38,8 @@
 use middle::lang_items::StartFnLangItem;
 use middle::cstore::EncodedMetadata;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::dep_graph::{AssertDepGraphSafe, DepNode, WorkProduct};
+use rustc::dep_graph::{AssertDepGraphSafe, DepNode};
+use rustc::middle::cstore::LinkMeta;
 use rustc::hir::map as hir_map;
 use rustc::util::common::time;
 use session::config::{self, NoDebugInfo};
@@ -56,7 +57,7 @@
 use common::{type_is_zero_size, val_ty};
 use common;
 use consts;
-use context::{self, SharedCrateContext, CrateContextList};
+use context::{self, LocalCrateContext, SharedCrateContext, Stats};
 use debuginfo;
 use declare;
 use machine;
@@ -724,13 +725,14 @@ fn contains_null(s: &str) -> bool {
     s.bytes().any(|b| b == 0)
 }
 
-fn write_metadata(cx: &SharedCrateContext,
-                  exported_symbols: &NodeSet)
-                  -> (ContextRef, ModuleRef, EncodedMetadata) {
+fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
+                            link_meta: &LinkMeta,
+                            exported_symbols: &NodeSet)
+                            -> (ContextRef, ModuleRef, EncodedMetadata) {
     use flate;
 
     let (metadata_llcx, metadata_llmod) = unsafe {
-        context::create_context_and_module(cx.sess(), "metadata")
+        context::create_context_and_module(tcx.sess, "metadata")
     };
 
     #[derive(PartialEq, Eq, PartialOrd, Ord)]
@@ -740,7 +742,7 @@ enum MetadataKind {
         Compressed
     }
 
-    let kind = cx.sess().crate_types.borrow().iter().map(|ty| {
+    let kind = tcx.sess.crate_types.borrow().iter().map(|ty| {
         match *ty {
             config::CrateTypeExecutable |
             config::CrateTypeStaticlib |
@@ -760,9 +762,9 @@ enum MetadataKind {
         });
     }
 
-    let cstore = &cx.tcx().sess.cstore;
-    let metadata = cstore.encode_metadata(cx.tcx(),
-                                          cx.link_meta(),
+    let cstore = &tcx.sess.cstore;
+    let metadata = cstore.encode_metadata(tcx,
+                                          &link_meta,
                                           exported_symbols);
     if kind == MetadataKind::Uncompressed {
         return (metadata_llcx, metadata_llmod, metadata);
@@ -774,7 +776,7 @@ enum MetadataKind {
 
     let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
     let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
-    let name = cx.metadata_symbol_name();
+    let name = symbol_export::metadata_symbol_name(tcx);
     let buf = CString::new(name).unwrap();
     let llglobal = unsafe {
         llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst).to_ref(), buf.as_ptr())
@@ -782,7 +784,7 @@ enum MetadataKind {
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
         let section_name =
-            cx.tcx().sess.cstore.metadata_section_name(&cx.sess().target.target);
+            tcx.sess.cstore.metadata_section_name(&tcx.sess.target.target);
         let name = CString::new(section_name).unwrap();
         llvm::LLVMSetSection(llglobal, name.as_ptr());
 
@@ -1063,21 +1065,20 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // particular items that will be processed.
     let krate = tcx.hir.krate();
 
-    let ty::CrateAnalysis { reachable, name, .. } = analysis;
+    let ty::CrateAnalysis { reachable, .. } = analysis;
     let exported_symbols = find_exported_symbols(tcx, reachable);
 
     let check_overflow = tcx.sess.overflow_checks();
 
-    let link_meta = link::build_link_meta(incremental_hashes_map, &name);
+    let link_meta = link::build_link_meta(incremental_hashes_map);
 
     let shared_ccx = SharedCrateContext::new(tcx,
-                                             link_meta.clone(),
                                              exported_symbols,
                                              check_overflow);
     // Translate the metadata.
     let (metadata_llcx, metadata_llmod, metadata) =
         time(tcx.sess.time_passes(), "write metadata", || {
-            write_metadata(&shared_ccx, shared_ccx.exported_symbols())
+            write_metadata(tcx, &link_meta, shared_ccx.exported_symbols())
         });
 
     let metadata_module = ModuleTranslation {
@@ -1096,6 +1097,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let empty_exported_symbols = ExportedSymbols::empty();
         let linker_info = LinkerInfo::new(&shared_ccx, &empty_exported_symbols);
         return CrateTranslation {
+            crate_name: tcx.crate_name(LOCAL_CRATE),
             modules: vec![],
             metadata_module: metadata_module,
             link: link_meta,
@@ -1113,41 +1115,72 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let symbol_map = Rc::new(symbol_map);
 
-    let previous_work_products = trans_reuse_previous_work_products(&shared_ccx,
-                                                                    &codegen_units,
-                                                                    &symbol_map);
-
-    let crate_context_list = CrateContextList::new(&shared_ccx,
-                                                   codegen_units,
-                                                   previous_work_products,
-                                                   symbol_map.clone());
-
-    let modules: Vec<ModuleTranslation> = crate_context_list
-        .iter_all()
-        .map(|ccx| {
-            let dep_node = ccx.codegen_unit().work_product_dep_node();
-            tcx.dep_graph.with_task(dep_node,
-                                    ccx,
-                                    AssertDepGraphSafe(symbol_map.clone()),
-                                    module_translation)
+    let mut all_stats = Stats::default();
+    let modules: Vec<ModuleTranslation> = codegen_units
+        .into_iter()
+        .map(|cgu| {
+            let dep_node = cgu.work_product_dep_node();
+            let (stats, module) =
+                tcx.dep_graph.with_task(dep_node,
+                                        AssertDepGraphSafe(&shared_ccx),
+                                        AssertDepGraphSafe((cgu, symbol_map.clone())),
+                                        module_translation);
+            all_stats.extend(stats);
+            module
         })
         .collect();
 
-    fn module_translation<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
-                                    symbol_map: AssertDepGraphSafe<Rc<SymbolMap<'tcx>>>)
-                                    -> ModuleTranslation {
-        // FIXME(#40304): Instead of this, the symbol-map should be an
-        // on-demand thing that we compute.
-        let AssertDepGraphSafe(symbol_map) = symbol_map;
+    fn module_translation<'a, 'tcx>(
+        scx: AssertDepGraphSafe<&SharedCrateContext<'a, 'tcx>>,
+        args: AssertDepGraphSafe<(CodegenUnit<'tcx>, Rc<SymbolMap<'tcx>>)>)
+        -> (Stats, ModuleTranslation)
+    {
+        // FIXME(#40304): We ought to be using the id as a key and some queries, I think.
+        let AssertDepGraphSafe(scx) = scx;
+        let AssertDepGraphSafe((cgu, symbol_map)) = args;
+
+        let cgu_name = String::from(cgu.name());
+        let cgu_id = cgu.work_product_id();
+        let symbol_name_hash = cgu.compute_symbol_name_hash(scx, &symbol_map);
+
+        // Check whether there is a previous work-product we can
+        // re-use.  Not only must the file exist, and the inputs not
+        // be dirty, but the hash of the symbols we will generate must
+        // be the same.
+        let previous_work_product =
+            scx.dep_graph().previous_work_product(&cgu_id).and_then(|work_product| {
+                if work_product.input_hash == symbol_name_hash {
+                    debug!("trans_reuse_previous_work_products: reusing {:?}", work_product);
+                    Some(work_product)
+                } else {
+                    if scx.sess().opts.debugging_opts.incremental_info {
+                        println!("incremental: CGU `{}` invalidated because of \
+                                  changed partitioning hash.",
+                                 cgu.name());
+                    }
+                    debug!("trans_reuse_previous_work_products: \
+                            not reusing {:?} because hash changed to {:?}",
+                           work_product, symbol_name_hash);
+                    None
+                }
+            });
 
-        let source = if let Some(buf) = ccx.previous_work_product() {
+        if let Some(buf) = previous_work_product {
             // Don't need to translate this module.
-            ModuleSource::Preexisting(buf.clone())
-        } else {
-            // Instantiate translation items without filling out definitions yet...
+            let module = ModuleTranslation {
+                name: cgu_name,
+                symbol_name_hash,
+                source: ModuleSource::Preexisting(buf.clone())
+            };
+            return (Stats::default(), module);
+        }
 
-            let cgu = ccx.codegen_unit();
-            let trans_items = cgu.items_in_deterministic_order(ccx.tcx(), &symbol_map);
+        // Instantiate translation items without filling out definitions yet...
+        let lcx = LocalCrateContext::new(scx, cgu, symbol_map.clone());
+        let module = {
+            let ccx = CrateContext::new(scx, &lcx);
+            let trans_items = ccx.codegen_unit()
+                                 .items_in_deterministic_order(ccx.tcx(), &symbol_map);
             for &(trans_item, linkage) in &trans_items {
                 trans_item.predefine(&ccx, linkage);
             }
@@ -1192,19 +1225,17 @@ fn module_translation<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
                 debuginfo::finalize(&ccx);
             }
 
-            ModuleSource::Translated(ModuleLlvm {
-                llcx: ccx.llcx(),
-                llmod: ccx.llmod(),
-            })
+            ModuleTranslation {
+                name: cgu_name,
+                symbol_name_hash,
+                source: ModuleSource::Translated(ModuleLlvm {
+                    llcx: ccx.llcx(),
+                    llmod: ccx.llmod(),
+                })
+            }
         };
 
-        ModuleTranslation {
-            name: String::from(ccx.codegen_unit().name()),
-            symbol_name_hash: ccx.codegen_unit()
-                                 .compute_symbol_name_hash(ccx.shared(),
-                                                           &symbol_map),
-            source: source,
-        }
+        (lcx.into_stats(), module)
     }
 
     assert_module_sources::assert_module_sources(tcx, &modules);
@@ -1212,20 +1243,19 @@ fn module_translation<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
     symbol_names_test::report_symbol_names(&shared_ccx);
 
     if shared_ccx.sess().trans_stats() {
-        let stats = shared_ccx.stats();
         println!("--- trans stats ---");
-        println!("n_glues_created: {}", stats.n_glues_created.get());
-        println!("n_null_glues: {}", stats.n_null_glues.get());
-        println!("n_real_glues: {}", stats.n_real_glues.get());
+        println!("n_glues_created: {}", all_stats.n_glues_created.get());
+        println!("n_null_glues: {}", all_stats.n_null_glues.get());
+        println!("n_real_glues: {}", all_stats.n_real_glues.get());
 
-        println!("n_fns: {}", stats.n_fns.get());
-        println!("n_inlines: {}", stats.n_inlines.get());
-        println!("n_closures: {}", stats.n_closures.get());
+        println!("n_fns: {}", all_stats.n_fns.get());
+        println!("n_inlines: {}", all_stats.n_inlines.get());
+        println!("n_closures: {}", all_stats.n_closures.get());
         println!("fn stats:");
-        stats.fn_stats.borrow_mut().sort_by(|&(_, insns_a), &(_, insns_b)| {
+        all_stats.fn_stats.borrow_mut().sort_by(|&(_, insns_a), &(_, insns_b)| {
             insns_b.cmp(&insns_a)
         });
-        for tuple in stats.fn_stats.borrow().iter() {
+        for tuple in all_stats.fn_stats.borrow().iter() {
             match *tuple {
                 (ref name, insns) => {
                     println!("{} insns, {}", insns, *name);
@@ -1235,7 +1265,7 @@ fn module_translation<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
     }
 
     if shared_ccx.sess().count_llvm_insns() {
-        for (k, v) in shared_ccx.stats().llvm_insns.borrow().iter() {
+        for (k, v) in all_stats.llvm_insns.borrow().iter() {
             println!("{:7} {}", *v, *k);
         }
     }
@@ -1289,6 +1319,7 @@ fn module_translation<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
     });
 
     CrateTranslation {
+        crate_name: tcx.crate_name(LOCAL_CRATE),
         modules: modules,
         metadata_module: metadata_module,
         link: link_meta,
@@ -1487,43 +1518,6 @@ enum Fields<'a> {
     }
 }
 
-/// For each CGU, identify if we can reuse an existing object file (or
-/// maybe other context).
-fn trans_reuse_previous_work_products(scx: &SharedCrateContext,
-                                      codegen_units: &[CodegenUnit],
-                                      symbol_map: &SymbolMap)
-                                      -> Vec<Option<WorkProduct>> {
-    debug!("trans_reuse_previous_work_products()");
-    codegen_units
-        .iter()
-        .map(|cgu| {
-            let id = cgu.work_product_id();
-
-            let hash = cgu.compute_symbol_name_hash(scx, symbol_map);
-
-            debug!("trans_reuse_previous_work_products: id={:?} hash={}", id, hash);
-
-            if let Some(work_product) = scx.dep_graph().previous_work_product(&id) {
-                if work_product.input_hash == hash {
-                    debug!("trans_reuse_previous_work_products: reusing {:?}", work_product);
-                    return Some(work_product);
-                } else {
-                    if scx.sess().opts.debugging_opts.incremental_info {
-                        println!("incremental: CGU `{}` invalidated because of \
-                                  changed partitioning hash.",
-                                  cgu.name());
-                    }
-                    debug!("trans_reuse_previous_work_products: \
-                            not reusing {:?} because hash changed to {:?}",
-                           work_product, hash);
-                }
-            }
-
-            None
-        })
-        .collect()
-}
-
 fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
                                                      -> (Vec<CodegenUnit<'tcx>>, SymbolMap<'tcx>) {
     let time_passes = scx.sess().time_passes();