]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_codegen_llvm/back/lto.rs
If an LLVM module's exports change, cannot reuse its post-LTO object file in
[rust.git] / src / librustc_codegen_llvm / back / lto.rs
index 1b64750f51febd12f10cb21c8abb0525524951b5..c97e108b0f53cd1ee445a92b35ac03a0989fccb9 100644 (file)
@@ -6,9 +6,6 @@
 use crate::llvm::{self, False, True};
 use crate::{LlvmCodegenBackend, ModuleLlvm};
 use log::{debug, info};
-use rustc::bug;
-use rustc::dep_graph::WorkProduct;
-use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
 use rustc_codegen_ssa::back::symbol_export;
 use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
@@ -17,6 +14,9 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{FatalError, Handler};
 use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_middle::bug;
+use rustc_middle::dep_graph::WorkProduct;
+use rustc_middle::middle::exported_symbols::SymbolExportLevel;
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{self, Lto};
 
@@ -517,11 +517,20 @@ fn thin_lto(
 
                 let prev_imports = prev_import_map.modules_imported_by(module_name);
                 let curr_imports = curr_import_map.modules_imported_by(module_name);
+                let prev_exports = prev_import_map.modules_exported_by(module_name);
+                let curr_exports = curr_import_map.modules_exported_by(module_name);
                 let imports_all_green = curr_imports
                     .iter()
                     .all(|imported_module| green_modules.contains_key(imported_module));
+                let exports_all_green = curr_exports
+                    .iter()
+                    .all(|exported_module| green_modules.contains_key(exported_module));
 
-                if imports_all_green && equivalent_as_sets(prev_imports, curr_imports) {
+                if imports_all_green
+                    && equivalent_as_sets(prev_imports, curr_imports)
+                    && exports_all_green
+                    && equivalent_as_sets(prev_exports, curr_exports)
+                {
                     let work_product = green_modules[module_name].clone();
                     copy_jobs.push(work_product);
                     info!(" - {}: re-used", module_name);
@@ -885,6 +894,8 @@ pub unsafe fn optimize_thin_module(
 pub struct ThinLTOImports {
     // key = llvm name of importing module, value = list of modules it imports from
     imports: FxHashMap<String, Vec<String>>,
+    // key = llvm name of exporting module, value = list of modules it exports to
+    exports: FxHashMap<String, Vec<String>>,
 }
 
 impl ThinLTOImports {
@@ -892,6 +903,10 @@ fn modules_imported_by(&self, llvm_module_name: &str) -> &[String] {
         self.imports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[])
     }
 
+    fn modules_exported_by(&self, llvm_module_name: &str) -> &[String] {
+        self.exports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[])
+    }
+
     fn save_to_file(&self, path: &Path) -> io::Result<()> {
         use std::io::Write;
         let file = File::create(path)?;
@@ -909,13 +924,17 @@ fn save_to_file(&self, path: &Path) -> io::Result<()> {
     fn load_from_file(path: &Path) -> io::Result<ThinLTOImports> {
         use std::io::BufRead;
         let mut imports = FxHashMap::default();
-        let mut current_module = None;
-        let mut current_imports = vec![];
+        let mut exports: FxHashMap<_, Vec<_>> = FxHashMap::default();
+        let mut current_module: Option<String> = None;
+        let mut current_imports: Vec<String> = vec![];
         let file = File::open(path)?;
         for line in io::BufReader::new(file).lines() {
             let line = line?;
             if line.is_empty() {
                 let importing_module = current_module.take().expect("Importing module not set");
+                for imported in &current_imports {
+                    exports.entry(imported.clone()).or_default().push(importing_module.clone());
+                }
                 imports.insert(importing_module, mem::replace(&mut current_imports, vec![]));
             } else if line.starts_with(' ') {
                 // Space marks an imported module
@@ -927,7 +946,7 @@ fn load_from_file(path: &Path) -> io::Result<ThinLTOImports> {
                 current_module = Some(line.trim().to_string());
             }
         }
-        Ok(ThinLTOImports { imports })
+        Ok(ThinLTOImports { imports, exports })
     }
 
     /// Loads the ThinLTO import map from ThinLTOData.
@@ -951,7 +970,17 @@ unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports {
                 .get_mut(importing_module_name)
                 .unwrap()
                 .push(imported_module_name.to_owned());
+
+            if !map.exports.contains_key(imported_module_name) {
+                map.exports.insert(imported_module_name.to_owned(), vec![]);
+            }
+
+            map.exports
+                .get_mut(imported_module_name)
+                .unwrap()
+                .push(importing_module_name.to_owned());
         }
+
         let mut map = ThinLTOImports::default();
         llvm::LLVMRustGetThinLTOModuleImports(
             data,