]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_ssa/src/back/lto.rs
New upstream version 1.53.0+dfsg1
[rustc.git] / compiler / rustc_codegen_ssa / src / back / lto.rs
CommitLineData
a1dfa0c6 1use super::write::CodegenContext;
9fa01778
XL
2use crate::traits::*;
3use crate::ModuleCodegen;
a1dfa0c6 4
cdc7bbd5 5use rustc_data_structures::memmap::Mmap;
a1dfa0c6
XL
6use rustc_errors::FatalError;
7
a1dfa0c6 8use std::ffi::CString;
dfeec247 9use std::sync::Arc;
a1dfa0c6
XL
10
11pub struct ThinModule<B: WriteBackendMethods> {
12 pub shared: Arc<ThinShared<B>>,
13 pub idx: usize,
14}
15
16impl<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
36pub 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
43pub 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
52impl<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
94pub enum SerializedModule<M: ModuleBufferMethods> {
95 Local(M),
96 FromRlib(Vec<u8>),
cdc7bbd5 97 FromUncompressedFile(Mmap),
a1dfa0c6
XL
98}
99
100impl<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}