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