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