]> git.proxmox.com Git - rustc.git/blob - src/librustc_codegen_ssa/back/lto.rs
New upstream version 1.47.0+dfsg1
[rustc.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 }