mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-29 12:36:35 +03:00
c2b15a6b64
And report an error if parsing the additional pass pipeline fails. Threading through the error accounts for most of the changes here.
109 lines
3.2 KiB
Rust
109 lines
3.2 KiB
Rust
use super::write::CodegenContext;
|
|
use crate::traits::*;
|
|
use crate::ModuleCodegen;
|
|
|
|
use rustc_data_structures::memmap::Mmap;
|
|
use rustc_errors::FatalError;
|
|
|
|
use std::ffi::CString;
|
|
use std::sync::Arc;
|
|
|
|
pub struct ThinModule<B: WriteBackendMethods> {
|
|
pub shared: Arc<ThinShared<B>>,
|
|
pub idx: usize,
|
|
}
|
|
|
|
impl<B: WriteBackendMethods> ThinModule<B> {
|
|
pub fn name(&self) -> &str {
|
|
self.shared.module_names[self.idx].to_str().unwrap()
|
|
}
|
|
|
|
pub fn cost(&self) -> u64 {
|
|
// Yes, that's correct, we're using the size of the bytecode as an
|
|
// indicator for how costly this codegen unit is.
|
|
self.data().len() as u64
|
|
}
|
|
|
|
pub fn data(&self) -> &[u8] {
|
|
let a = self.shared.thin_buffers.get(self.idx).map(|b| b.data());
|
|
a.unwrap_or_else(|| {
|
|
let len = self.shared.thin_buffers.len();
|
|
self.shared.serialized_modules[self.idx - len].data()
|
|
})
|
|
}
|
|
}
|
|
|
|
pub struct ThinShared<B: WriteBackendMethods> {
|
|
pub data: B::ThinData,
|
|
pub thin_buffers: Vec<B::ThinBuffer>,
|
|
pub serialized_modules: Vec<SerializedModule<B::ModuleBuffer>>,
|
|
pub module_names: Vec<CString>,
|
|
}
|
|
|
|
pub enum LtoModuleCodegen<B: WriteBackendMethods> {
|
|
Fat {
|
|
module: Option<ModuleCodegen<B::Module>>,
|
|
_serialized_bitcode: Vec<SerializedModule<B::ModuleBuffer>>,
|
|
},
|
|
|
|
Thin(ThinModule<B>),
|
|
}
|
|
|
|
impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
|
|
pub fn name(&self) -> &str {
|
|
match *self {
|
|
LtoModuleCodegen::Fat { .. } => "everything",
|
|
LtoModuleCodegen::Thin(ref m) => m.name(),
|
|
}
|
|
}
|
|
|
|
/// Optimize this module within the given codegen context.
|
|
///
|
|
/// This function is unsafe as it'll return a `ModuleCodegen` still
|
|
/// points to LLVM data structures owned by this `LtoModuleCodegen`.
|
|
/// It's intended that the module returned is immediately code generated and
|
|
/// dropped, and then this LTO module is dropped.
|
|
pub unsafe fn optimize(
|
|
&mut self,
|
|
cgcx: &CodegenContext<B>,
|
|
) -> Result<ModuleCodegen<B::Module>, FatalError> {
|
|
match *self {
|
|
LtoModuleCodegen::Fat { ref mut module, .. } => {
|
|
let module = module.take().unwrap();
|
|
{
|
|
let config = cgcx.config(module.kind);
|
|
B::run_lto_pass_manager(cgcx, &module, config, false)?;
|
|
}
|
|
Ok(module)
|
|
}
|
|
LtoModuleCodegen::Thin(ref mut thin) => B::optimize_thin(cgcx, thin),
|
|
}
|
|
}
|
|
|
|
/// A "gauge" of how costly it is to optimize this module, used to sort
|
|
/// biggest modules first.
|
|
pub fn cost(&self) -> u64 {
|
|
match *self {
|
|
// Only one module with fat LTO, so the cost doesn't matter.
|
|
LtoModuleCodegen::Fat { .. } => 0,
|
|
LtoModuleCodegen::Thin(ref m) => m.cost(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub enum SerializedModule<M: ModuleBufferMethods> {
|
|
Local(M),
|
|
FromRlib(Vec<u8>),
|
|
FromUncompressedFile(Mmap),
|
|
}
|
|
|
|
impl<M: ModuleBufferMethods> SerializedModule<M> {
|
|
pub fn data(&self) -> &[u8] {
|
|
match *self {
|
|
SerializedModule::Local(ref m) => m.data(),
|
|
SerializedModule::FromRlib(ref m) => m,
|
|
SerializedModule::FromUncompressedFile(ref m) => m,
|
|
}
|
|
}
|
|
}
|