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