about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2020-04-14 09:47:03 -0400
committerFelix S. Klock II <pnkfelix@pnkfx.org>2020-04-14 09:47:03 -0400
commite542f4fa59a2d1ae33bebcd1e11149f7644db5da (patch)
tree3b5b072be37c51aa705237979044109ea26a0116
parent5179ebe2064e15196c5be1f8df950736140b8fdd (diff)
downloadrust-e542f4fa59a2d1ae33bebcd1e11149f7644db5da.tar.gz
rust-e542f4fa59a2d1ae33bebcd1e11149f7644db5da.zip
If an LLVM module's exports change, cannot reuse its post-LTO object file in
incremental compilation.

This is symmetric to PR #67020, which handled the case where the LLVM module's
*imports* changed. This commit builds upon the infrastructure added there; the
export map is just the inverse of the import map, so we can build the export map
at the same time that we load the serialized import map.

Fix #69798
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs37
1 files changed, 33 insertions, 4 deletions
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 816329e06c7..c97e108b0f5 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -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 @@ impl ThinLTOImports {
         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 @@ impl ThinLTOImports {
     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 @@ impl 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 @@ impl 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,