]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/back/lto.rs
Rollup merge of #68914 - nnethercote:speed-up-SipHasher128, r=michaelwoerister
[rust.git] / src / librustc_codegen_llvm / back / lto.rs
1 use crate::back::bytecode::DecodedBytecode;
2 use crate::back::write::{
3     self, save_temp_bitcode, to_llvm_opt_settings, with_llvm_pmb, DiagnosticHandlers,
4 };
5 use crate::llvm::archive_ro::ArchiveRO;
6 use crate::llvm::{self, False, True};
7 use crate::{LlvmCodegenBackend, ModuleLlvm};
8 use log::{debug, info};
9 use rustc::bug;
10 use rustc::dep_graph::WorkProduct;
11 use rustc::middle::exported_symbols::SymbolExportLevel;
12 use rustc::session::config::{self, Lto};
13 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
14 use rustc_codegen_ssa::back::symbol_export;
15 use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
16 use rustc_codegen_ssa::traits::*;
17 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, RLIB_BYTECODE_EXTENSION};
18 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
19 use rustc_errors::{FatalError, Handler};
20 use rustc_hir::def_id::LOCAL_CRATE;
21 use rustc_session::cgu_reuse_tracker::CguReuse;
22
23 use std::ffi::{CStr, CString};
24 use std::fs::File;
25 use std::io;
26 use std::mem;
27 use std::path::Path;
28 use std::ptr;
29 use std::slice;
30 use std::sync::Arc;
31
32 /// We keep track of past LTO imports that were used to produce the current set
33 /// of compiled object files that we might choose to reuse during this
34 /// compilation session.
35 pub const THIN_LTO_IMPORTS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-imports.bin";
36
37 pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
38     match crate_type {
39         config::CrateType::Executable
40         | config::CrateType::Staticlib
41         | config::CrateType::Cdylib => true,
42
43         config::CrateType::Dylib | config::CrateType::Rlib | config::CrateType::ProcMacro => false,
44     }
45 }
46
47 fn prepare_lto(
48     cgcx: &CodegenContext<LlvmCodegenBackend>,
49     diag_handler: &Handler,
50 ) -> Result<(Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>), FatalError> {
51     let export_threshold = match cgcx.lto {
52         // We're just doing LTO for our one crate
53         Lto::ThinLocal => SymbolExportLevel::Rust,
54
55         // We're doing LTO for the entire crate graph
56         Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&cgcx.crate_types),
57
58         Lto::No => panic!("didn't request LTO but we're doing LTO"),
59     };
60
61     let symbol_filter = &|&(ref name, level): &(String, SymbolExportLevel)| {
62         if level.is_below_threshold(export_threshold) {
63             Some(CString::new(name.as_str()).unwrap())
64         } else {
65             None
66         }
67     };
68     let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
69     let mut symbol_white_list = {
70         let _timer = cgcx.prof.generic_activity("LLVM_lto_generate_symbol_white_list");
71         exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<CString>>()
72     };
73     info!("{} symbols to preserve in this crate", symbol_white_list.len());
74
75     // If we're performing LTO for the entire crate graph, then for each of our
76     // upstream dependencies, find the corresponding rlib and load the bitcode
77     // from the archive.
78     //
79     // We save off all the bytecode and LLVM module ids for later processing
80     // with either fat or thin LTO
81     let mut upstream_modules = Vec::new();
82     if cgcx.lto != Lto::ThinLocal {
83         if cgcx.opts.cg.prefer_dynamic {
84             diag_handler
85                 .struct_err("cannot prefer dynamic linking when performing LTO")
86                 .note(
87                     "only 'staticlib', 'bin', and 'cdylib' outputs are \
88                                supported with LTO",
89                 )
90                 .emit();
91             return Err(FatalError);
92         }
93
94         // Make sure we actually can run LTO
95         for crate_type in cgcx.crate_types.iter() {
96             if !crate_type_allows_lto(*crate_type) {
97                 let e = diag_handler.fatal(
98                     "lto can only be run for executables, cdylibs and \
99                                             static library outputs",
100                 );
101                 return Err(e);
102             }
103         }
104
105         for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
106             let exported_symbols =
107                 cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
108             {
109                 let _timer = cgcx.prof.generic_activity("LLVM_lto_generate_symbol_white_list");
110                 symbol_white_list.extend(exported_symbols[&cnum].iter().filter_map(symbol_filter));
111             }
112
113             let archive = ArchiveRO::open(&path).expect("wanted an rlib");
114             let bytecodes = archive
115                 .iter()
116                 .filter_map(|child| child.ok().and_then(|c| c.name().map(|name| (name, c))))
117                 .filter(|&(name, _)| name.ends_with(RLIB_BYTECODE_EXTENSION));
118             for (name, data) in bytecodes {
119                 let _timer =
120                     cgcx.prof.generic_activity_with_arg("LLVM_lto_load_upstream_bitcode", name);
121                 info!("adding bytecode {}", name);
122                 let bc_encoded = data.data();
123
124                 let (bc, id) = match DecodedBytecode::new(bc_encoded) {
125                     Ok(b) => Ok((b.bytecode(), b.identifier().to_string())),
126                     Err(e) => Err(diag_handler.fatal(&e)),
127                 }?;
128                 let bc = SerializedModule::FromRlib(bc);
129                 upstream_modules.push((bc, CString::new(id).unwrap()));
130             }
131         }
132     }
133
134     Ok((symbol_white_list, upstream_modules))
135 }
136
137 /// Performs fat LTO by merging all modules into a single one and returning it
138 /// for further optimization.
139 pub(crate) fn run_fat(
140     cgcx: &CodegenContext<LlvmCodegenBackend>,
141     modules: Vec<FatLTOInput<LlvmCodegenBackend>>,
142     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
143 ) -> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError> {
144     let diag_handler = cgcx.create_diag_handler();
145     let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, &diag_handler)?;
146     let symbol_white_list = symbol_white_list.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
147     fat_lto(cgcx, &diag_handler, modules, cached_modules, upstream_modules, &symbol_white_list)
148 }
149
150 /// Performs thin LTO by performing necessary global analysis and returning two
151 /// lists, one of the modules that need optimization and another for modules that
152 /// can simply be copied over from the incr. comp. cache.
153 pub(crate) fn run_thin(
154     cgcx: &CodegenContext<LlvmCodegenBackend>,
155     modules: Vec<(String, ThinBuffer)>,
156     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
157 ) -> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
158     let diag_handler = cgcx.create_diag_handler();
159     let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, &diag_handler)?;
160     let symbol_white_list = symbol_white_list.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
161     if cgcx.opts.cg.linker_plugin_lto.enabled() {
162         unreachable!(
163             "We should never reach this case if the LTO step \
164                       is deferred to the linker"
165         );
166     }
167     thin_lto(cgcx, &diag_handler, modules, upstream_modules, cached_modules, &symbol_white_list)
168 }
169
170 pub(crate) fn prepare_thin(module: ModuleCodegen<ModuleLlvm>) -> (String, ThinBuffer) {
171     let name = module.name.clone();
172     let buffer = ThinBuffer::new(module.module_llvm.llmod());
173     (name, buffer)
174 }
175
176 fn fat_lto(
177     cgcx: &CodegenContext<LlvmCodegenBackend>,
178     diag_handler: &Handler,
179     modules: Vec<FatLTOInput<LlvmCodegenBackend>>,
180     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
181     mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
182     symbol_white_list: &[*const libc::c_char],
183 ) -> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError> {
184     let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_build_monolithic_module");
185     info!("going for a fat lto");
186
187     // Sort out all our lists of incoming modules into two lists.
188     //
189     // * `serialized_modules` (also and argument to this function) contains all
190     //   modules that are serialized in-memory.
191     // * `in_memory` contains modules which are already parsed and in-memory,
192     //   such as from multi-CGU builds.
193     //
194     // All of `cached_modules` (cached from previous incremental builds) can
195     // immediately go onto the `serialized_modules` modules list and then we can
196     // split the `modules` array into these two lists.
197     let mut in_memory = Vec::new();
198     serialized_modules.extend(cached_modules.into_iter().map(|(buffer, wp)| {
199         info!("pushing cached module {:?}", wp.cgu_name);
200         (buffer, CString::new(wp.cgu_name).unwrap())
201     }));
202     for module in modules {
203         match module {
204             FatLTOInput::InMemory(m) => in_memory.push(m),
205             FatLTOInput::Serialized { name, buffer } => {
206                 info!("pushing serialized module {:?}", name);
207                 let buffer = SerializedModule::Local(buffer);
208                 serialized_modules.push((buffer, CString::new(name).unwrap()));
209             }
210         }
211     }
212
213     // Find the "costliest" module and merge everything into that codegen unit.
214     // All the other modules will be serialized and reparsed into the new
215     // context, so this hopefully avoids serializing and parsing the largest
216     // codegen unit.
217     //
218     // Additionally use a regular module as the base here to ensure that various
219     // file copy operations in the backend work correctly. The only other kind
220     // of module here should be an allocator one, and if your crate is smaller
221     // than the allocator module then the size doesn't really matter anyway.
222     let costliest_module = in_memory
223         .iter()
224         .enumerate()
225         .filter(|&(_, module)| module.kind == ModuleKind::Regular)
226         .map(|(i, module)| {
227             let cost = unsafe { llvm::LLVMRustModuleCost(module.module_llvm.llmod()) };
228             (cost, i)
229         })
230         .max();
231
232     // If we found a costliest module, we're good to go. Otherwise all our
233     // inputs were serialized which could happen in the case, for example, that
234     // all our inputs were incrementally reread from the cache and we're just
235     // re-executing the LTO passes. If that's the case deserialize the first
236     // module and create a linker with it.
237     let module: ModuleCodegen<ModuleLlvm> = match costliest_module {
238         Some((_cost, i)) => in_memory.remove(i),
239         None => {
240             assert!(serialized_modules.len() > 0, "must have at least one serialized module");
241             let (buffer, name) = serialized_modules.remove(0);
242             info!("no in-memory regular modules to choose from, parsing {:?}", name);
243             ModuleCodegen {
244                 module_llvm: ModuleLlvm::parse(cgcx, &name, buffer.data(), diag_handler)?,
245                 name: name.into_string().unwrap(),
246                 kind: ModuleKind::Regular,
247             }
248         }
249     };
250     let mut serialized_bitcode = Vec::new();
251     {
252         let (llcx, llmod) = {
253             let llvm = &module.module_llvm;
254             (&llvm.llcx, llvm.llmod())
255         };
256         info!("using {:?} as a base module", module.name);
257
258         // The linking steps below may produce errors and diagnostics within LLVM
259         // which we'd like to handle and print, so set up our diagnostic handlers
260         // (which get unregistered when they go out of scope below).
261         let _handler = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
262
263         // For all other modules we codegened we'll need to link them into our own
264         // bitcode. All modules were codegened in their own LLVM context, however,
265         // and we want to move everything to the same LLVM context. Currently the
266         // way we know of to do that is to serialize them to a string and them parse
267         // them later. Not great but hey, that's why it's "fat" LTO, right?
268         for module in in_memory {
269             let buffer = ModuleBuffer::new(module.module_llvm.llmod());
270             let llmod_id = CString::new(&module.name[..]).unwrap();
271             serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
272         }
273         // Sort the modules to ensure we produce deterministic results.
274         serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1));
275
276         // For all serialized bitcode files we parse them and link them in as we did
277         // above, this is all mostly handled in C++. Like above, though, we don't
278         // know much about the memory management here so we err on the side of being
279         // save and persist everything with the original module.
280         let mut linker = Linker::new(llmod);
281         for (bc_decoded, name) in serialized_modules {
282             let _timer = cgcx
283                 .prof
284                 .generic_activity_with_arg("LLVM_fat_lto_link_module", format!("{:?}", name));
285             info!("linking {:?}", name);
286             let data = bc_decoded.data();
287             linker.add(&data).map_err(|()| {
288                 let msg = format!("failed to load bc of {:?}", name);
289                 write::llvm_err(&diag_handler, &msg)
290             })?;
291             serialized_bitcode.push(bc_decoded);
292         }
293         drop(linker);
294         save_temp_bitcode(&cgcx, &module, "lto.input");
295
296         // Internalize everything that *isn't* in our whitelist to help strip out
297         // more modules and such
298         unsafe {
299             let ptr = symbol_white_list.as_ptr();
300             llvm::LLVMRustRunRestrictionPass(
301                 llmod,
302                 ptr as *const *const libc::c_char,
303                 symbol_white_list.len() as libc::size_t,
304             );
305             save_temp_bitcode(&cgcx, &module, "lto.after-restriction");
306         }
307
308         if cgcx.no_landing_pads {
309             unsafe {
310                 llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
311             }
312             save_temp_bitcode(&cgcx, &module, "lto.after-nounwind");
313         }
314     }
315
316     Ok(LtoModuleCodegen::Fat { module: Some(module), _serialized_bitcode: serialized_bitcode })
317 }
318
319 struct Linker<'a>(&'a mut llvm::Linker<'a>);
320
321 impl Linker<'a> {
322     fn new(llmod: &'a llvm::Module) -> Self {
323         unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) }
324     }
325
326     fn add(&mut self, bytecode: &[u8]) -> Result<(), ()> {
327         unsafe {
328             if llvm::LLVMRustLinkerAdd(
329                 self.0,
330                 bytecode.as_ptr() as *const libc::c_char,
331                 bytecode.len(),
332             ) {
333                 Ok(())
334             } else {
335                 Err(())
336             }
337         }
338     }
339 }
340
341 impl Drop for Linker<'a> {
342     fn drop(&mut self) {
343         unsafe {
344             llvm::LLVMRustLinkerFree(&mut *(self.0 as *mut _));
345         }
346     }
347 }
348
349 /// Prepare "thin" LTO to get run on these modules.
350 ///
351 /// The general structure of ThinLTO is quite different from the structure of
352 /// "fat" LTO above. With "fat" LTO all LLVM modules in question are merged into
353 /// one giant LLVM module, and then we run more optimization passes over this
354 /// big module after internalizing most symbols. Thin LTO, on the other hand,
355 /// avoid this large bottleneck through more targeted optimization.
356 ///
357 /// At a high level Thin LTO looks like:
358 ///
359 ///     1. Prepare a "summary" of each LLVM module in question which describes
360 ///        the values inside, cost of the values, etc.
361 ///     2. Merge the summaries of all modules in question into one "index"
362 ///     3. Perform some global analysis on this index
363 ///     4. For each module, use the index and analysis calculated previously to
364 ///        perform local transformations on the module, for example inlining
365 ///        small functions from other modules.
366 ///     5. Run thin-specific optimization passes over each module, and then code
367 ///        generate everything at the end.
368 ///
369 /// The summary for each module is intended to be quite cheap, and the global
370 /// index is relatively quite cheap to create as well. As a result, the goal of
371 /// ThinLTO is to reduce the bottleneck on LTO and enable LTO to be used in more
372 /// situations. For example one cheap optimization is that we can parallelize
373 /// all codegen modules, easily making use of all the cores on a machine.
374 ///
375 /// With all that in mind, the function here is designed at specifically just
376 /// calculating the *index* for ThinLTO. This index will then be shared amongst
377 /// all of the `LtoModuleCodegen` units returned below and destroyed once
378 /// they all go out of scope.
379 fn thin_lto(
380     cgcx: &CodegenContext<LlvmCodegenBackend>,
381     diag_handler: &Handler,
382     modules: Vec<(String, ThinBuffer)>,
383     serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
384     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
385     symbol_white_list: &[*const libc::c_char],
386 ) -> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
387     let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
388     unsafe {
389         info!("going for that thin, thin LTO");
390
391         let green_modules: FxHashMap<_, _> =
392             cached_modules.iter().map(|&(_, ref wp)| (wp.cgu_name.clone(), wp.clone())).collect();
393
394         let full_scope_len = modules.len() + serialized_modules.len() + cached_modules.len();
395         let mut thin_buffers = Vec::with_capacity(modules.len());
396         let mut module_names = Vec::with_capacity(full_scope_len);
397         let mut thin_modules = Vec::with_capacity(full_scope_len);
398
399         for (i, (name, buffer)) in modules.into_iter().enumerate() {
400             info!("local module: {} - {}", i, name);
401             let cname = CString::new(name.clone()).unwrap();
402             thin_modules.push(llvm::ThinLTOModule {
403                 identifier: cname.as_ptr(),
404                 data: buffer.data().as_ptr(),
405                 len: buffer.data().len(),
406             });
407             thin_buffers.push(buffer);
408             module_names.push(cname);
409         }
410
411         // FIXME: All upstream crates are deserialized internally in the
412         //        function below to extract their summary and modules. Note that
413         //        unlike the loop above we *must* decode and/or read something
414         //        here as these are all just serialized files on disk. An
415         //        improvement, however, to make here would be to store the
416         //        module summary separately from the actual module itself. Right
417         //        now this is store in one large bitcode file, and the entire
418         //        file is deflate-compressed. We could try to bypass some of the
419         //        decompression by storing the index uncompressed and only
420         //        lazily decompressing the bytecode if necessary.
421         //
422         //        Note that truly taking advantage of this optimization will
423         //        likely be further down the road. We'd have to implement
424         //        incremental ThinLTO first where we could actually avoid
425         //        looking at upstream modules entirely sometimes (the contents,
426         //        we must always unconditionally look at the index).
427         let mut serialized = Vec::with_capacity(serialized_modules.len() + cached_modules.len());
428
429         let cached_modules =
430             cached_modules.into_iter().map(|(sm, wp)| (sm, CString::new(wp.cgu_name).unwrap()));
431
432         for (module, name) in serialized_modules.into_iter().chain(cached_modules) {
433             info!("upstream or cached module {:?}", name);
434             thin_modules.push(llvm::ThinLTOModule {
435                 identifier: name.as_ptr(),
436                 data: module.data().as_ptr(),
437                 len: module.data().len(),
438             });
439             serialized.push(module);
440             module_names.push(name);
441         }
442
443         // Sanity check
444         assert_eq!(thin_modules.len(), module_names.len());
445
446         // Delegate to the C++ bindings to create some data here. Once this is a
447         // tried-and-true interface we may wish to try to upstream some of this
448         // to LLVM itself, right now we reimplement a lot of what they do
449         // upstream...
450         let data = llvm::LLVMRustCreateThinLTOData(
451             thin_modules.as_ptr(),
452             thin_modules.len() as u32,
453             symbol_white_list.as_ptr(),
454             symbol_white_list.len() as u32,
455         )
456         .ok_or_else(|| write::llvm_err(&diag_handler, "failed to prepare thin LTO context"))?;
457
458         info!("thin LTO data created");
459
460         let (import_map_path, prev_import_map, curr_import_map) =
461             if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir {
462                 let path = incr_comp_session_dir.join(THIN_LTO_IMPORTS_INCR_COMP_FILE_NAME);
463                 // If previous imports have been deleted, or we get an IO error
464                 // reading the file storing them, then we'll just use `None` as the
465                 // prev_import_map, which will force the code to be recompiled.
466                 let prev =
467                     if path.exists() { ThinLTOImports::load_from_file(&path).ok() } else { None };
468                 let curr = ThinLTOImports::from_thin_lto_data(data);
469                 (Some(path), prev, curr)
470             } else {
471                 // If we don't compile incrementally, we don't need to load the
472                 // import data from LLVM.
473                 assert!(green_modules.is_empty());
474                 let curr = ThinLTOImports::default();
475                 (None, None, curr)
476             };
477         info!("thin LTO import map loaded");
478
479         let data = ThinData(data);
480
481         // Throw our data in an `Arc` as we'll be sharing it across threads. We
482         // also put all memory referenced by the C++ data (buffers, ids, etc)
483         // into the arc as well. After this we'll create a thin module
484         // codegen per module in this data.
485         let shared = Arc::new(ThinShared {
486             data,
487             thin_buffers,
488             serialized_modules: serialized,
489             module_names,
490         });
491
492         let mut copy_jobs = vec![];
493         let mut opt_jobs = vec![];
494
495         info!("checking which modules can be-reused and which have to be re-optimized.");
496         for (module_index, module_name) in shared.module_names.iter().enumerate() {
497             let module_name = module_name_to_str(module_name);
498
499             // If (1.) the module hasn't changed, and (2.) none of the modules
500             // it imports from has changed, *and* (3.) the import-set itself has
501             // not changed from the previous compile when it was last
502             // ThinLTO'ed, then we can re-use the post-ThinLTO version of the
503             // module. Otherwise, freshly perform LTO optimization.
504             //
505             // This strategy means we can always save the computed imports as
506             // canon: when we reuse the post-ThinLTO version, condition (3.)
507             // ensures that the curent import set is the same as the previous
508             // one. (And of course, when we don't reuse the post-ThinLTO
509             // version, the current import set *is* the correct one, since we
510             // are doing the ThinLTO in this current compilation cycle.)
511             //
512             // See rust-lang/rust#59535.
513             if let (Some(prev_import_map), true) =
514                 (prev_import_map.as_ref(), green_modules.contains_key(module_name))
515             {
516                 assert!(cgcx.incr_comp_session_dir.is_some());
517
518                 let prev_imports = prev_import_map.modules_imported_by(module_name);
519                 let curr_imports = curr_import_map.modules_imported_by(module_name);
520                 let imports_all_green = curr_imports
521                     .iter()
522                     .all(|imported_module| green_modules.contains_key(imported_module));
523
524                 if imports_all_green && equivalent_as_sets(prev_imports, curr_imports) {
525                     let work_product = green_modules[module_name].clone();
526                     copy_jobs.push(work_product);
527                     info!(" - {}: re-used", module_name);
528                     assert!(cgcx.incr_comp_session_dir.is_some());
529                     cgcx.cgu_reuse_tracker.set_actual_reuse(module_name, CguReuse::PostLto);
530                     continue;
531                 }
532             }
533
534             info!(" - {}: re-compiled", module_name);
535             opt_jobs.push(LtoModuleCodegen::Thin(ThinModule {
536                 shared: shared.clone(),
537                 idx: module_index,
538             }));
539         }
540
541         // Save the curent ThinLTO import information for the next compilation
542         // session, overwriting the previous serialized imports (if any).
543         if let Some(path) = import_map_path {
544             if let Err(err) = curr_import_map.save_to_file(&path) {
545                 let msg = format!("Error while writing ThinLTO import data: {}", err);
546                 return Err(write::llvm_err(&diag_handler, &msg));
547             }
548         }
549
550         Ok((opt_jobs, copy_jobs))
551     }
552 }
553
554 /// Given two slices, each with no repeat elements. returns true if and only if
555 /// the two slices have the same contents when considered as sets (i.e. when
556 /// element order is disregarded).
557 fn equivalent_as_sets(a: &[String], b: &[String]) -> bool {
558     // cheap path: unequal lengths means cannot possibly be set equivalent.
559     if a.len() != b.len() {
560         return false;
561     }
562     // fast path: before building new things, check if inputs are equivalent as is.
563     if a == b {
564         return true;
565     }
566     // slow path: general set comparison.
567     let a: FxHashSet<&str> = a.iter().map(|s| s.as_str()).collect();
568     let b: FxHashSet<&str> = b.iter().map(|s| s.as_str()).collect();
569     a == b
570 }
571
572 pub(crate) fn run_pass_manager(
573     cgcx: &CodegenContext<LlvmCodegenBackend>,
574     module: &ModuleCodegen<ModuleLlvm>,
575     config: &ModuleConfig,
576     thin: bool,
577 ) {
578     let _timer = cgcx.prof.extra_verbose_generic_activity("LLVM_lto_optimize", &module.name[..]);
579
580     // Now we have one massive module inside of llmod. Time to run the
581     // LTO-specific optimization passes that LLVM provides.
582     //
583     // This code is based off the code found in llvm's LTO code generator:
584     //      tools/lto/LTOCodeGenerator.cpp
585     debug!("running the pass manager");
586     unsafe {
587         let pm = llvm::LLVMCreatePassManager();
588         llvm::LLVMAddAnalysisPasses(module.module_llvm.tm, pm);
589
590         if config.verify_llvm_ir {
591             let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
592             llvm::LLVMRustAddPass(pm, pass.unwrap());
593         }
594
595         // When optimizing for LTO we don't actually pass in `-O0`, but we force
596         // it to always happen at least with `-O1`.
597         //
598         // With ThinLTO we mess around a lot with symbol visibility in a way
599         // that will actually cause linking failures if we optimize at O0 which
600         // notable is lacking in dead code elimination. To ensure we at least
601         // get some optimizations and correctly link we forcibly switch to `-O1`
602         // to get dead code elimination.
603         //
604         // Note that in general this shouldn't matter too much as you typically
605         // only turn on ThinLTO when you're compiling with optimizations
606         // otherwise.
607         let opt_level = config
608             .opt_level
609             .map(|x| to_llvm_opt_settings(x).0)
610             .unwrap_or(llvm::CodeGenOptLevel::None);
611         let opt_level = match opt_level {
612             llvm::CodeGenOptLevel::None => llvm::CodeGenOptLevel::Less,
613             level => level,
614         };
615         with_llvm_pmb(module.module_llvm.llmod(), config, opt_level, false, &mut |b| {
616             if thin {
617                 llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm);
618             } else {
619                 llvm::LLVMPassManagerBuilderPopulateLTOPassManager(
620                     b, pm, /* Internalize = */ False, /* RunInliner = */ True,
621                 );
622             }
623         });
624
625         // We always generate bitcode through ThinLTOBuffers,
626         // which do not support anonymous globals
627         if config.bitcode_needed() {
628             let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr().cast());
629             llvm::LLVMRustAddPass(pm, pass.unwrap());
630         }
631
632         if config.verify_llvm_ir {
633             let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
634             llvm::LLVMRustAddPass(pm, pass.unwrap());
635         }
636
637         llvm::LLVMRunPassManager(pm, module.module_llvm.llmod());
638
639         llvm::LLVMDisposePassManager(pm);
640     }
641     debug!("lto done");
642 }
643
644 pub struct ModuleBuffer(&'static mut llvm::ModuleBuffer);
645
646 unsafe impl Send for ModuleBuffer {}
647 unsafe impl Sync for ModuleBuffer {}
648
649 impl ModuleBuffer {
650     pub fn new(m: &llvm::Module) -> ModuleBuffer {
651         ModuleBuffer(unsafe { llvm::LLVMRustModuleBufferCreate(m) })
652     }
653 }
654
655 impl ModuleBufferMethods for ModuleBuffer {
656     fn data(&self) -> &[u8] {
657         unsafe {
658             let ptr = llvm::LLVMRustModuleBufferPtr(self.0);
659             let len = llvm::LLVMRustModuleBufferLen(self.0);
660             slice::from_raw_parts(ptr, len)
661         }
662     }
663 }
664
665 impl Drop for ModuleBuffer {
666     fn drop(&mut self) {
667         unsafe {
668             llvm::LLVMRustModuleBufferFree(&mut *(self.0 as *mut _));
669         }
670     }
671 }
672
673 pub struct ThinData(&'static mut llvm::ThinLTOData);
674
675 unsafe impl Send for ThinData {}
676 unsafe impl Sync for ThinData {}
677
678 impl Drop for ThinData {
679     fn drop(&mut self) {
680         unsafe {
681             llvm::LLVMRustFreeThinLTOData(&mut *(self.0 as *mut _));
682         }
683     }
684 }
685
686 pub struct ThinBuffer(&'static mut llvm::ThinLTOBuffer);
687
688 unsafe impl Send for ThinBuffer {}
689 unsafe impl Sync for ThinBuffer {}
690
691 impl ThinBuffer {
692     pub fn new(m: &llvm::Module) -> ThinBuffer {
693         unsafe {
694             let buffer = llvm::LLVMRustThinLTOBufferCreate(m);
695             ThinBuffer(buffer)
696         }
697     }
698 }
699
700 impl ThinBufferMethods for ThinBuffer {
701     fn data(&self) -> &[u8] {
702         unsafe {
703             let ptr = llvm::LLVMRustThinLTOBufferPtr(self.0) as *const _;
704             let len = llvm::LLVMRustThinLTOBufferLen(self.0);
705             slice::from_raw_parts(ptr, len)
706         }
707     }
708 }
709
710 impl Drop for ThinBuffer {
711     fn drop(&mut self) {
712         unsafe {
713             llvm::LLVMRustThinLTOBufferFree(&mut *(self.0 as *mut _));
714         }
715     }
716 }
717
718 pub unsafe fn optimize_thin_module(
719     thin_module: &mut ThinModule<LlvmCodegenBackend>,
720     cgcx: &CodegenContext<LlvmCodegenBackend>,
721 ) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
722     let diag_handler = cgcx.create_diag_handler();
723     let tm = (cgcx.tm_factory.0)().map_err(|e| write::llvm_err(&diag_handler, &e))?;
724
725     // Right now the implementation we've got only works over serialized
726     // modules, so we create a fresh new LLVM context and parse the module
727     // into that context. One day, however, we may do this for upstream
728     // crates but for locally codegened modules we may be able to reuse
729     // that LLVM Context and Module.
730     let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
731     let llmod_raw = parse_module(
732         llcx,
733         &thin_module.shared.module_names[thin_module.idx],
734         thin_module.data(),
735         &diag_handler,
736     )? as *const _;
737     let module = ModuleCodegen {
738         module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
739         name: thin_module.name().to_string(),
740         kind: ModuleKind::Regular,
741     };
742     {
743         let llmod = module.module_llvm.llmod();
744         save_temp_bitcode(&cgcx, &module, "thin-lto-input");
745
746         // Before we do much else find the "main" `DICompileUnit` that we'll be
747         // using below. If we find more than one though then rustc has changed
748         // in a way we're not ready for, so generate an ICE by returning
749         // an error.
750         let mut cu1 = ptr::null_mut();
751         let mut cu2 = ptr::null_mut();
752         llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
753         if !cu2.is_null() {
754             let msg = "multiple source DICompileUnits found";
755             return Err(write::llvm_err(&diag_handler, msg));
756         }
757
758         // Like with "fat" LTO, get some better optimizations if landing pads
759         // are disabled by removing all landing pads.
760         if cgcx.no_landing_pads {
761             let _timer = cgcx
762                 .prof
763                 .generic_activity_with_arg("LLVM_thin_lto_remove_landing_pads", thin_module.name());
764             llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
765             save_temp_bitcode(&cgcx, &module, "thin-lto-after-nounwind");
766         }
767
768         // Up next comes the per-module local analyses that we do for Thin LTO.
769         // Each of these functions is basically copied from the LLVM
770         // implementation and then tailored to suit this implementation. Ideally
771         // each of these would be supported by upstream LLVM but that's perhaps
772         // a patch for another day!
773         //
774         // You can find some more comments about these functions in the LLVM
775         // bindings we've got (currently `PassWrapper.cpp`)
776         {
777             let _timer =
778                 cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name());
779             if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod) {
780                 let msg = "failed to prepare thin LTO module";
781                 return Err(write::llvm_err(&diag_handler, msg));
782             }
783             save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
784         }
785
786         {
787             let _timer = cgcx
788                 .prof
789                 .generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
790             if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
791                 let msg = "failed to prepare thin LTO module";
792                 return Err(write::llvm_err(&diag_handler, msg));
793             }
794             save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
795         }
796
797         {
798             let _timer = cgcx
799                 .prof
800                 .generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
801             if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
802                 let msg = "failed to prepare thin LTO module";
803                 return Err(write::llvm_err(&diag_handler, msg));
804             }
805             save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
806         }
807
808         {
809             let _timer =
810                 cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name());
811             if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod) {
812                 let msg = "failed to prepare thin LTO module";
813                 return Err(write::llvm_err(&diag_handler, msg));
814             }
815             save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
816         }
817
818         // Ok now this is a bit unfortunate. This is also something you won't
819         // find upstream in LLVM's ThinLTO passes! This is a hack for now to
820         // work around bugs in LLVM.
821         //
822         // First discovered in #45511 it was found that as part of ThinLTO
823         // importing passes LLVM will import `DICompileUnit` metadata
824         // information across modules. This means that we'll be working with one
825         // LLVM module that has multiple `DICompileUnit` instances in it (a
826         // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
827         // bugs in LLVM's backend which generates invalid DWARF in a situation
828         // like this:
829         //
830         //  https://bugs.llvm.org/show_bug.cgi?id=35212
831         //  https://bugs.llvm.org/show_bug.cgi?id=35562
832         //
833         // While the first bug there is fixed the second ended up causing #46346
834         // which was basically a resurgence of #45511 after LLVM's bug 35212 was
835         // fixed.
836         //
837         // This function below is a huge hack around this problem. The function
838         // below is defined in `PassWrapper.cpp` and will basically "merge"
839         // all `DICompileUnit` instances in a module. Basically it'll take all
840         // the objects, rewrite all pointers of `DISubprogram` to point to the
841         // first `DICompileUnit`, and then delete all the other units.
842         //
843         // This is probably mangling to the debug info slightly (but hopefully
844         // not too much) but for now at least gets LLVM to emit valid DWARF (or
845         // so it appears). Hopefully we can remove this once upstream bugs are
846         // fixed in LLVM.
847         {
848             let _timer = cgcx
849                 .prof
850                 .generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name());
851             llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
852             save_temp_bitcode(cgcx, &module, "thin-lto-after-patch");
853         }
854
855         // Alright now that we've done everything related to the ThinLTO
856         // analysis it's time to run some optimizations! Here we use the same
857         // `run_pass_manager` as the "fat" LTO above except that we tell it to
858         // populate a thin-specific pass manager, which presumably LLVM treats a
859         // little differently.
860         {
861             info!("running thin lto passes over {}", module.name);
862             let config = cgcx.config(module.kind);
863             run_pass_manager(cgcx, &module, config, true);
864             save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
865         }
866     }
867     Ok(module)
868 }
869
870 #[derive(Debug, Default)]
871 pub struct ThinLTOImports {
872     // key = llvm name of importing module, value = list of modules it imports from
873     imports: FxHashMap<String, Vec<String>>,
874 }
875
876 impl ThinLTOImports {
877     fn modules_imported_by(&self, llvm_module_name: &str) -> &[String] {
878         self.imports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[])
879     }
880
881     fn save_to_file(&self, path: &Path) -> io::Result<()> {
882         use std::io::Write;
883         let file = File::create(path)?;
884         let mut writer = io::BufWriter::new(file);
885         for (importing_module_name, imported_modules) in &self.imports {
886             writeln!(writer, "{}", importing_module_name)?;
887             for imported_module in imported_modules {
888                 writeln!(writer, " {}", imported_module)?;
889             }
890             writeln!(writer)?;
891         }
892         Ok(())
893     }
894
895     fn load_from_file(path: &Path) -> io::Result<ThinLTOImports> {
896         use std::io::BufRead;
897         let mut imports = FxHashMap::default();
898         let mut current_module = None;
899         let mut current_imports = vec![];
900         let file = File::open(path)?;
901         for line in io::BufReader::new(file).lines() {
902             let line = line?;
903             if line.is_empty() {
904                 let importing_module = current_module.take().expect("Importing module not set");
905                 imports.insert(importing_module, mem::replace(&mut current_imports, vec![]));
906             } else if line.starts_with(" ") {
907                 // Space marks an imported module
908                 assert_ne!(current_module, None);
909                 current_imports.push(line.trim().to_string());
910             } else {
911                 // Otherwise, beginning of a new module (must be start or follow empty line)
912                 assert_eq!(current_module, None);
913                 current_module = Some(line.trim().to_string());
914             }
915         }
916         Ok(ThinLTOImports { imports })
917     }
918
919     /// Loads the ThinLTO import map from ThinLTOData.
920     unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports {
921         unsafe extern "C" fn imported_module_callback(
922             payload: *mut libc::c_void,
923             importing_module_name: *const libc::c_char,
924             imported_module_name: *const libc::c_char,
925         ) {
926             let map = &mut *(payload as *mut ThinLTOImports);
927             let importing_module_name = CStr::from_ptr(importing_module_name);
928             let importing_module_name = module_name_to_str(&importing_module_name);
929             let imported_module_name = CStr::from_ptr(imported_module_name);
930             let imported_module_name = module_name_to_str(&imported_module_name);
931
932             if !map.imports.contains_key(importing_module_name) {
933                 map.imports.insert(importing_module_name.to_owned(), vec![]);
934             }
935
936             map.imports
937                 .get_mut(importing_module_name)
938                 .unwrap()
939                 .push(imported_module_name.to_owned());
940         }
941         let mut map = ThinLTOImports::default();
942         llvm::LLVMRustGetThinLTOModuleImports(
943             data,
944             imported_module_callback,
945             &mut map as *mut _ as *mut libc::c_void,
946         );
947         map
948     }
949 }
950
951 fn module_name_to_str(c_str: &CStr) -> &str {
952     c_str.to_str().unwrap_or_else(|e| {
953         bug!("Encountered non-utf8 LLVM module name `{}`: {}", c_str.to_string_lossy(), e)
954     })
955 }
956
957 pub fn parse_module<'a>(
958     cx: &'a llvm::Context,
959     name: &CStr,
960     data: &[u8],
961     diag_handler: &Handler,
962 ) -> Result<&'a llvm::Module, FatalError> {
963     unsafe {
964         llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr()).ok_or_else(
965             || {
966                 let msg = "failed to parse bitcode for LTO module";
967                 write::llvm_err(&diag_handler, msg)
968             },
969         )
970     }
971 }