]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_ssa/back/lto.rs
Suggest defining type parameter when appropriate
[rust.git] / src / librustc_codegen_ssa / back / lto.rs
1 use super::write::CodegenContext;
2 use crate::traits::*;
3 use crate::ModuleCodegen;
4
5 use rustc_errors::FatalError;
6
7 use std::ffi::CString;
8 use std::sync::Arc;
9
10 pub struct ThinModule<B: WriteBackendMethods> {
11     pub shared: Arc<ThinShared<B>>,
12     pub idx: usize,
13 }
14
15 impl<B: WriteBackendMethods> ThinModule<B> {
16     pub fn name(&self) -> &str {
17         self.shared.module_names[self.idx].to_str().unwrap()
18     }
19
20     pub fn cost(&self) -> u64 {
21         // Yes, that's correct, we're using the size of the bytecode as an
22         // indicator for how costly this codegen unit is.
23         self.data().len() as u64
24     }
25
26     pub fn data(&self) -> &[u8] {
27         let a = self.shared.thin_buffers.get(self.idx).map(|b| b.data());
28         a.unwrap_or_else(|| {
29             let len = self.shared.thin_buffers.len();
30             self.shared.serialized_modules[self.idx - len].data()
31         })
32     }
33 }
34
35 pub struct ThinShared<B: WriteBackendMethods> {
36     pub data: B::ThinData,
37     pub thin_buffers: Vec<B::ThinBuffer>,
38     pub serialized_modules: Vec<SerializedModule<B::ModuleBuffer>>,
39     pub module_names: Vec<CString>,
40 }
41
42 pub enum LtoModuleCodegen<B: WriteBackendMethods> {
43     Fat {
44         module: Option<ModuleCodegen<B::Module>>,
45         _serialized_bitcode: Vec<SerializedModule<B::ModuleBuffer>>,
46     },
47
48     Thin(ThinModule<B>),
49 }
50
51 impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
52     pub fn name(&self) -> &str {
53         match *self {
54             LtoModuleCodegen::Fat { .. } => "everything",
55             LtoModuleCodegen::Thin(ref m) => m.name(),
56         }
57     }
58
59     /// Optimize this module within the given codegen context.
60     ///
61     /// This function is unsafe as it'll return a `ModuleCodegen` still
62     /// points to LLVM data structures owned by this `LtoModuleCodegen`.
63     /// It's intended that the module returned is immediately code generated and
64     /// dropped, and then this LTO module is dropped.
65     pub unsafe fn optimize(
66         &mut self,
67         cgcx: &CodegenContext<B>,
68     ) -> Result<ModuleCodegen<B::Module>, FatalError> {
69         match *self {
70             LtoModuleCodegen::Fat { ref mut module, .. } => {
71                 let module = module.take().unwrap();
72                 {
73                     let config = cgcx.config(module.kind);
74                     B::run_lto_pass_manager(cgcx, &module, config, false);
75                 }
76                 Ok(module)
77             }
78             LtoModuleCodegen::Thin(ref mut thin) => B::optimize_thin(cgcx, thin),
79         }
80     }
81
82     /// A "gauge" of how costly it is to optimize this module, used to sort
83     /// biggest modules first.
84     pub fn cost(&self) -> u64 {
85         match *self {
86             // Only one module with fat LTO, so the cost doesn't matter.
87             LtoModuleCodegen::Fat { .. } => 0,
88             LtoModuleCodegen::Thin(ref m) => m.cost(),
89         }
90     }
91 }
92
93 pub enum SerializedModule<M: ModuleBufferMethods> {
94     Local(M),
95     FromRlib(Vec<u8>),
96     FromUncompressedFile(memmap::Mmap),
97 }
98
99 impl<M: ModuleBufferMethods> SerializedModule<M> {
100     pub fn data(&self) -> &[u8] {
101         match *self {
102             SerializedModule::Local(ref m) => m.data(),
103             SerializedModule::FromRlib(ref m) => m,
104             SerializedModule::FromUncompressedFile(ref m) => m,
105         }
106     }
107 }