]>
Commit | Line | Data |
---|---|---|
a1dfa0c6 | 1 | use super::write::CodegenContext; |
9fa01778 XL |
2 | use crate::traits::*; |
3 | use crate::ModuleCodegen; | |
a1dfa0c6 | 4 | |
cdc7bbd5 | 5 | use rustc_data_structures::memmap::Mmap; |
a1dfa0c6 XL |
6 | use rustc_errors::FatalError; |
7 | ||
a1dfa0c6 | 8 | use std::ffi::CString; |
dfeec247 | 9 | use std::sync::Arc; |
a1dfa0c6 XL |
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 | ||
a1dfa0c6 XL |
43 | pub enum LtoModuleCodegen<B: WriteBackendMethods> { |
44 | Fat { | |
45 | module: Option<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 | &mut self, | |
68 | cgcx: &CodegenContext<B>, | |
a1dfa0c6 XL |
69 | ) -> Result<ModuleCodegen<B::Module>, FatalError> { |
70 | match *self { | |
71 | LtoModuleCodegen::Fat { ref mut module, .. } => { | |
72 | let module = module.take().unwrap(); | |
73 | { | |
74 | let config = cgcx.config(module.kind); | |
75 | B::run_lto_pass_manager(cgcx, &module, config, false); | |
a1dfa0c6 XL |
76 | } |
77 | Ok(module) | |
78 | } | |
532ac7d7 | 79 | LtoModuleCodegen::Thin(ref mut thin) => B::optimize_thin(cgcx, thin), |
a1dfa0c6 XL |
80 | } |
81 | } | |
82 | ||
83 | /// A "gauge" of how costly it is to optimize this module, used to sort | |
84 | /// biggest modules first. | |
85 | pub fn cost(&self) -> u64 { | |
86 | match *self { | |
87 | // Only one module with fat LTO, so the cost doesn't matter. | |
88 | LtoModuleCodegen::Fat { .. } => 0, | |
89 | LtoModuleCodegen::Thin(ref m) => m.cost(), | |
90 | } | |
91 | } | |
92 | } | |
93 | ||
a1dfa0c6 XL |
94 | pub enum SerializedModule<M: ModuleBufferMethods> { |
95 | Local(M), | |
96 | FromRlib(Vec<u8>), | |
cdc7bbd5 | 97 | FromUncompressedFile(Mmap), |
a1dfa0c6 XL |
98 | } |
99 | ||
100 | impl<M: ModuleBufferMethods> SerializedModule<M> { | |
101 | pub fn data(&self) -> &[u8] { | |
102 | match *self { | |
103 | SerializedModule::Local(ref m) => m.data(), | |
104 | SerializedModule::FromRlib(ref m) => m, | |
105 | SerializedModule::FromUncompressedFile(ref m) => m, | |
106 | } | |
107 | } | |
108 | } |