]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/back/lto.rs
Rollup merge of #70487 - Mark-Simulacrum:float-unchecked-casts, r=SimonSapin
[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_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
10 use rustc_codegen_ssa::back::symbol_export;
11 use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
12 use rustc_codegen_ssa::traits::*;
13 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, RLIB_BYTECODE_EXTENSION};
14 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
15 use rustc_errors::{FatalError, Handler};
16 use rustc_hir::def_id::LOCAL_CRATE;
17 use rustc_middle::bug;
18 use rustc_middle::dep_graph::WorkProduct;
19 use rustc_middle::middle::exported_symbols::SymbolExportLevel;
20 use rustc_session::cgu_reuse_tracker::CguReuse;
21 use rustc_session::config::{self, Lto};
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.is_empty(), "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 current 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 current 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         if write::should_use_new_llvm_pass_manager(config) {
588             let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
589             let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
590             // See comment below for why this is necessary.
591             let opt_level = if let config::OptLevel::No = opt_level {
592                 config::OptLevel::Less
593             } else {
594                 opt_level
595             };
596             write::optimize_with_new_llvm_pass_manager(cgcx, module, config, opt_level, opt_stage);
597             debug!("lto done");
598             return;
599         }
600
601         let pm = llvm::LLVMCreatePassManager();
602         llvm::LLVMAddAnalysisPasses(module.module_llvm.tm, pm);
603
604         if config.verify_llvm_ir {
605             let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
606             llvm::LLVMRustAddPass(pm, pass.unwrap());
607         }
608
609         // When optimizing for LTO we don't actually pass in `-O0`, but we force
610         // it to always happen at least with `-O1`.
611         //
612         // With ThinLTO we mess around a lot with symbol visibility in a way
613         // that will actually cause linking failures if we optimize at O0 which
614         // notable is lacking in dead code elimination. To ensure we at least
615         // get some optimizations and correctly link we forcibly switch to `-O1`
616         // to get dead code elimination.
617         //
618         // Note that in general this shouldn't matter too much as you typically
619         // only turn on ThinLTO when you're compiling with optimizations
620         // otherwise.
621         let opt_level = config
622             .opt_level
623             .map(|x| to_llvm_opt_settings(x).0)
624             .unwrap_or(llvm::CodeGenOptLevel::None);
625         let opt_level = match opt_level {
626             llvm::CodeGenOptLevel::None => llvm::CodeGenOptLevel::Less,
627             level => level,
628         };
629         with_llvm_pmb(module.module_llvm.llmod(), config, opt_level, false, &mut |b| {
630             if thin {
631                 llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm);
632             } else {
633                 llvm::LLVMPassManagerBuilderPopulateLTOPassManager(
634                     b, pm, /* Internalize = */ False, /* RunInliner = */ True,
635                 );
636             }
637         });
638
639         // We always generate bitcode through ThinLTOBuffers,
640         // which do not support anonymous globals
641         if config.bitcode_needed() {
642             let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr().cast());
643             llvm::LLVMRustAddPass(pm, pass.unwrap());
644         }
645
646         if config.verify_llvm_ir {
647             let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
648             llvm::LLVMRustAddPass(pm, pass.unwrap());
649         }
650
651         llvm::LLVMRunPassManager(pm, module.module_llvm.llmod());
652
653         llvm::LLVMDisposePassManager(pm);
654     }
655     debug!("lto done");
656 }
657
658 pub struct ModuleBuffer(&'static mut llvm::ModuleBuffer);
659
660 unsafe impl Send for ModuleBuffer {}
661 unsafe impl Sync for ModuleBuffer {}
662
663 impl ModuleBuffer {
664     pub fn new(m: &llvm::Module) -> ModuleBuffer {
665         ModuleBuffer(unsafe { llvm::LLVMRustModuleBufferCreate(m) })
666     }
667 }
668
669 impl ModuleBufferMethods for ModuleBuffer {
670     fn data(&self) -> &[u8] {
671         unsafe {
672             let ptr = llvm::LLVMRustModuleBufferPtr(self.0);
673             let len = llvm::LLVMRustModuleBufferLen(self.0);
674             slice::from_raw_parts(ptr, len)
675         }
676     }
677 }
678
679 impl Drop for ModuleBuffer {
680     fn drop(&mut self) {
681         unsafe {
682             llvm::LLVMRustModuleBufferFree(&mut *(self.0 as *mut _));
683         }
684     }
685 }
686
687 pub struct ThinData(&'static mut llvm::ThinLTOData);
688
689 unsafe impl Send for ThinData {}
690 unsafe impl Sync for ThinData {}
691
692 impl Drop for ThinData {
693     fn drop(&mut self) {
694         unsafe {
695             llvm::LLVMRustFreeThinLTOData(&mut *(self.0 as *mut _));
696         }
697     }
698 }
699
700 pub struct ThinBuffer(&'static mut llvm::ThinLTOBuffer);
701
702 unsafe impl Send for ThinBuffer {}
703 unsafe impl Sync for ThinBuffer {}
704
705 impl ThinBuffer {
706     pub fn new(m: &llvm::Module) -> ThinBuffer {
707         unsafe {
708             let buffer = llvm::LLVMRustThinLTOBufferCreate(m);
709             ThinBuffer(buffer)
710         }
711     }
712 }
713
714 impl ThinBufferMethods for ThinBuffer {
715     fn data(&self) -> &[u8] {
716         unsafe {
717             let ptr = llvm::LLVMRustThinLTOBufferPtr(self.0) as *const _;
718             let len = llvm::LLVMRustThinLTOBufferLen(self.0);
719             slice::from_raw_parts(ptr, len)
720         }
721     }
722 }
723
724 impl Drop for ThinBuffer {
725     fn drop(&mut self) {
726         unsafe {
727             llvm::LLVMRustThinLTOBufferFree(&mut *(self.0 as *mut _));
728         }
729     }
730 }
731
732 pub unsafe fn optimize_thin_module(
733     thin_module: &mut ThinModule<LlvmCodegenBackend>,
734     cgcx: &CodegenContext<LlvmCodegenBackend>,
735 ) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
736     let diag_handler = cgcx.create_diag_handler();
737     let tm = (cgcx.tm_factory.0)().map_err(|e| write::llvm_err(&diag_handler, &e))?;
738
739     // Right now the implementation we've got only works over serialized
740     // modules, so we create a fresh new LLVM context and parse the module
741     // into that context. One day, however, we may do this for upstream
742     // crates but for locally codegened modules we may be able to reuse
743     // that LLVM Context and Module.
744     let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
745     let llmod_raw = parse_module(
746         llcx,
747         &thin_module.shared.module_names[thin_module.idx],
748         thin_module.data(),
749         &diag_handler,
750     )? as *const _;
751     let module = ModuleCodegen {
752         module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
753         name: thin_module.name().to_string(),
754         kind: ModuleKind::Regular,
755     };
756     {
757         let llmod = module.module_llvm.llmod();
758         save_temp_bitcode(&cgcx, &module, "thin-lto-input");
759
760         // Before we do much else find the "main" `DICompileUnit` that we'll be
761         // using below. If we find more than one though then rustc has changed
762         // in a way we're not ready for, so generate an ICE by returning
763         // an error.
764         let mut cu1 = ptr::null_mut();
765         let mut cu2 = ptr::null_mut();
766         llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
767         if !cu2.is_null() {
768             let msg = "multiple source DICompileUnits found";
769             return Err(write::llvm_err(&diag_handler, msg));
770         }
771
772         // Like with "fat" LTO, get some better optimizations if landing pads
773         // are disabled by removing all landing pads.
774         if cgcx.no_landing_pads {
775             let _timer = cgcx
776                 .prof
777                 .generic_activity_with_arg("LLVM_thin_lto_remove_landing_pads", thin_module.name());
778             llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
779             save_temp_bitcode(&cgcx, &module, "thin-lto-after-nounwind");
780         }
781
782         // Up next comes the per-module local analyses that we do for Thin LTO.
783         // Each of these functions is basically copied from the LLVM
784         // implementation and then tailored to suit this implementation. Ideally
785         // each of these would be supported by upstream LLVM but that's perhaps
786         // a patch for another day!
787         //
788         // You can find some more comments about these functions in the LLVM
789         // bindings we've got (currently `PassWrapper.cpp`)
790         {
791             let _timer =
792                 cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name());
793             if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod) {
794                 let msg = "failed to prepare thin LTO module";
795                 return Err(write::llvm_err(&diag_handler, msg));
796             }
797             save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
798         }
799
800         {
801             let _timer = cgcx
802                 .prof
803                 .generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
804             if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
805                 let msg = "failed to prepare thin LTO module";
806                 return Err(write::llvm_err(&diag_handler, msg));
807             }
808             save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
809         }
810
811         {
812             let _timer = cgcx
813                 .prof
814                 .generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
815             if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
816                 let msg = "failed to prepare thin LTO module";
817                 return Err(write::llvm_err(&diag_handler, msg));
818             }
819             save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
820         }
821
822         {
823             let _timer =
824                 cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name());
825             if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod) {
826                 let msg = "failed to prepare thin LTO module";
827                 return Err(write::llvm_err(&diag_handler, msg));
828             }
829             save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
830         }
831
832         // Ok now this is a bit unfortunate. This is also something you won't
833         // find upstream in LLVM's ThinLTO passes! This is a hack for now to
834         // work around bugs in LLVM.
835         //
836         // First discovered in #45511 it was found that as part of ThinLTO
837         // importing passes LLVM will import `DICompileUnit` metadata
838         // information across modules. This means that we'll be working with one
839         // LLVM module that has multiple `DICompileUnit` instances in it (a
840         // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
841         // bugs in LLVM's backend which generates invalid DWARF in a situation
842         // like this:
843         //
844         //  https://bugs.llvm.org/show_bug.cgi?id=35212
845         //  https://bugs.llvm.org/show_bug.cgi?id=35562
846         //
847         // While the first bug there is fixed the second ended up causing #46346
848         // which was basically a resurgence of #45511 after LLVM's bug 35212 was
849         // fixed.
850         //
851         // This function below is a huge hack around this problem. The function
852         // below is defined in `PassWrapper.cpp` and will basically "merge"
853         // all `DICompileUnit` instances in a module. Basically it'll take all
854         // the objects, rewrite all pointers of `DISubprogram` to point to the
855         // first `DICompileUnit`, and then delete all the other units.
856         //
857         // This is probably mangling to the debug info slightly (but hopefully
858         // not too much) but for now at least gets LLVM to emit valid DWARF (or
859         // so it appears). Hopefully we can remove this once upstream bugs are
860         // fixed in LLVM.
861         {
862             let _timer = cgcx
863                 .prof
864                 .generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name());
865             llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
866             save_temp_bitcode(cgcx, &module, "thin-lto-after-patch");
867         }
868
869         // Alright now that we've done everything related to the ThinLTO
870         // analysis it's time to run some optimizations! Here we use the same
871         // `run_pass_manager` as the "fat" LTO above except that we tell it to
872         // populate a thin-specific pass manager, which presumably LLVM treats a
873         // little differently.
874         {
875             info!("running thin lto passes over {}", module.name);
876             let config = cgcx.config(module.kind);
877             run_pass_manager(cgcx, &module, config, true);
878             save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
879         }
880     }
881     Ok(module)
882 }
883
884 #[derive(Debug, Default)]
885 pub struct ThinLTOImports {
886     // key = llvm name of importing module, value = list of modules it imports from
887     imports: FxHashMap<String, Vec<String>>,
888 }
889
890 impl ThinLTOImports {
891     fn modules_imported_by(&self, llvm_module_name: &str) -> &[String] {
892         self.imports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[])
893     }
894
895     fn save_to_file(&self, path: &Path) -> io::Result<()> {
896         use std::io::Write;
897         let file = File::create(path)?;
898         let mut writer = io::BufWriter::new(file);
899         for (importing_module_name, imported_modules) in &self.imports {
900             writeln!(writer, "{}", importing_module_name)?;
901             for imported_module in imported_modules {
902                 writeln!(writer, " {}", imported_module)?;
903             }
904             writeln!(writer)?;
905         }
906         Ok(())
907     }
908
909     fn load_from_file(path: &Path) -> io::Result<ThinLTOImports> {
910         use std::io::BufRead;
911         let mut imports = FxHashMap::default();
912         let mut current_module = None;
913         let mut current_imports = vec![];
914         let file = File::open(path)?;
915         for line in io::BufReader::new(file).lines() {
916             let line = line?;
917             if line.is_empty() {
918                 let importing_module = current_module.take().expect("Importing module not set");
919                 imports.insert(importing_module, mem::replace(&mut current_imports, vec![]));
920             } else if line.starts_with(' ') {
921                 // Space marks an imported module
922                 assert_ne!(current_module, None);
923                 current_imports.push(line.trim().to_string());
924             } else {
925                 // Otherwise, beginning of a new module (must be start or follow empty line)
926                 assert_eq!(current_module, None);
927                 current_module = Some(line.trim().to_string());
928             }
929         }
930         Ok(ThinLTOImports { imports })
931     }
932
933     /// Loads the ThinLTO import map from ThinLTOData.
934     unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports {
935         unsafe extern "C" fn imported_module_callback(
936             payload: *mut libc::c_void,
937             importing_module_name: *const libc::c_char,
938             imported_module_name: *const libc::c_char,
939         ) {
940             let map = &mut *(payload as *mut ThinLTOImports);
941             let importing_module_name = CStr::from_ptr(importing_module_name);
942             let importing_module_name = module_name_to_str(&importing_module_name);
943             let imported_module_name = CStr::from_ptr(imported_module_name);
944             let imported_module_name = module_name_to_str(&imported_module_name);
945
946             if !map.imports.contains_key(importing_module_name) {
947                 map.imports.insert(importing_module_name.to_owned(), vec![]);
948             }
949
950             map.imports
951                 .get_mut(importing_module_name)
952                 .unwrap()
953                 .push(imported_module_name.to_owned());
954         }
955         let mut map = ThinLTOImports::default();
956         llvm::LLVMRustGetThinLTOModuleImports(
957             data,
958             imported_module_callback,
959             &mut map as *mut _ as *mut libc::c_void,
960         );
961         map
962     }
963 }
964
965 fn module_name_to_str(c_str: &CStr) -> &str {
966     c_str.to_str().unwrap_or_else(|e| {
967         bug!("Encountered non-utf8 LLVM module name `{}`: {}", c_str.to_string_lossy(), e)
968     })
969 }
970
971 pub fn parse_module<'a>(
972     cx: &'a llvm::Context,
973     name: &CStr,
974     data: &[u8],
975     diag_handler: &Handler,
976 ) -> Result<&'a llvm::Module, FatalError> {
977     unsafe {
978         llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr()).ok_or_else(
979             || {
980                 let msg = "failed to parse bitcode for LTO module";
981                 write::llvm_err(&diag_handler, msg)
982             },
983         )
984     }
985 }