rustc_codegen_ssa/back/
lto.rs

1use std::ffi::CString;
2use std::sync::Arc;
3
4use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
5use rustc_data_structures::memmap::Mmap;
6use rustc_errors::FatalError;
7
8use super::write::CodegenContext;
9use crate::ModuleCodegen;
10use crate::back::write::ModuleConfig;
11use crate::traits::*;
12
13pub struct ThinModule<B: WriteBackendMethods> {
14    pub shared: Arc<ThinShared<B>>,
15    pub idx: usize,
16}
17
18impl<B: WriteBackendMethods> ThinModule<B> {
19    pub fn name(&self) -> &str {
20        self.shared.module_names[self.idx].to_str().unwrap()
21    }
22
23    pub fn cost(&self) -> u64 {
24        // Yes, that's correct, we're using the size of the bytecode as an
25        // indicator for how costly this codegen unit is.
26        self.data().len() as u64
27    }
28
29    pub fn data(&self) -> &[u8] {
30        let a = self.shared.thin_buffers.get(self.idx).map(|b| b.data());
31        a.unwrap_or_else(|| {
32            let len = self.shared.thin_buffers.len();
33            self.shared.serialized_modules[self.idx - len].data()
34        })
35    }
36}
37
38pub struct ThinShared<B: WriteBackendMethods> {
39    pub data: B::ThinData,
40    pub thin_buffers: Vec<B::ThinBuffer>,
41    pub serialized_modules: Vec<SerializedModule<B::ModuleBuffer>>,
42    pub module_names: Vec<CString>,
43}
44
45pub enum LtoModuleCodegen<B: WriteBackendMethods> {
46    Fat(ModuleCodegen<B::Module>),
47    Thin(ThinModule<B>),
48}
49
50impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
51    pub fn name(&self) -> &str {
52        match *self {
53            LtoModuleCodegen::Fat(_) => "everything",
54            LtoModuleCodegen::Thin(ref m) => m.name(),
55        }
56    }
57
58    /// Optimize this module within the given codegen context.
59    pub fn optimize(
60        self,
61        cgcx: &CodegenContext<B>,
62    ) -> Result<ModuleCodegen<B::Module>, FatalError> {
63        match self {
64            LtoModuleCodegen::Fat(mut module) => {
65                B::optimize_fat(cgcx, &mut module)?;
66                Ok(module)
67            }
68            LtoModuleCodegen::Thin(thin) => B::optimize_thin(cgcx, thin),
69        }
70    }
71
72    /// A "gauge" of how costly it is to optimize this module, used to sort
73    /// biggest modules first.
74    pub fn cost(&self) -> u64 {
75        match *self {
76            // Only one module with fat LTO, so the cost doesn't matter.
77            LtoModuleCodegen::Fat(_) => 0,
78            LtoModuleCodegen::Thin(ref m) => m.cost(),
79        }
80    }
81
82    /// Run autodiff on Fat LTO module
83    pub fn autodiff(
84        self,
85        cgcx: &CodegenContext<B>,
86        diff_fncs: Vec<AutoDiffItem>,
87        config: &ModuleConfig,
88    ) -> Result<LtoModuleCodegen<B>, FatalError> {
89        match &self {
90            LtoModuleCodegen::Fat(module) => {
91                B::autodiff(cgcx, &module, diff_fncs, config)?;
92            }
93            _ => panic!("autodiff called with non-fat LTO module"),
94        }
95
96        Ok(self)
97    }
98}
99
100pub enum SerializedModule<M: ModuleBufferMethods> {
101    Local(M),
102    FromRlib(Vec<u8>),
103    FromUncompressedFile(Mmap),
104}
105
106impl<M: ModuleBufferMethods> SerializedModule<M> {
107    pub fn data(&self) -> &[u8] {
108        match *self {
109            SerializedModule::Local(ref m) => m.data(),
110            SerializedModule::FromRlib(ref m) => m,
111            SerializedModule::FromUncompressedFile(ref m) => m,
112        }
113    }
114}