diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 7ea5e91230905..9077e89a4020e 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -28,7 +28,7 @@ use rustc::mir::mono::{Linkage, Visibility, Stats}; use rustc::middle::cstore::{EncodedMetadata}; use rustc::ty::TyCtxt; use rustc::middle::exported_symbols; -use rustc::session::config::{self, DebugInfo}; +use rustc::session::config::DebugInfo; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_data_structures::small_c_str::SmallCStr; @@ -42,47 +42,16 @@ use rustc::hir::CodegenFnAttrs; use crate::value::Value; - -pub fn write_metadata<'a, 'gcx>( +pub fn write_compressed_metadata<'a, 'gcx>( tcx: TyCtxt<'a, 'gcx, 'gcx>, + metadata: &EncodedMetadata, llvm_module: &mut ModuleLlvm -) -> EncodedMetadata { +) { use std::io::Write; use flate2::Compression; use flate2::write::DeflateEncoder; let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); - - #[derive(PartialEq, Eq, PartialOrd, Ord)] - enum MetadataKind { - None, - Uncompressed, - Compressed - } - - let kind = tcx.sess.crate_types.borrow().iter().map(|ty| { - match *ty { - config::CrateType::Executable | - config::CrateType::Staticlib | - config::CrateType::Cdylib => MetadataKind::None, - - config::CrateType::Rlib => MetadataKind::Uncompressed, - - config::CrateType::Dylib | - config::CrateType::ProcMacro => MetadataKind::Compressed, - } - }).max().unwrap_or(MetadataKind::None); - - if kind == MetadataKind::None { - return EncodedMetadata::new(); - } - - let metadata = tcx.encode_metadata(); - if kind == MetadataKind::Uncompressed { - return metadata; - } - - assert!(kind == MetadataKind::Compressed); let mut compressed = tcx.metadata_encoding_version(); DeflateEncoder::new(&mut compressed, Compression::fast()) .write_all(&metadata.raw_data).unwrap(); @@ -107,7 +76,6 @@ pub fn write_metadata<'a, 'gcx>( let directive = CString::new(directive).unwrap(); llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr()) } - return metadata; } pub struct ValueIter<'ll> { diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 08424e7c3229a..09b284052b3c4 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -110,12 +110,13 @@ impl ExtraBackendMethods for LlvmCodegenBackend { ModuleLlvm::new_metadata(tcx, mod_name) } - fn write_metadata<'b, 'gcx>( + fn write_compressed_metadata<'b, 'gcx>( &self, tcx: TyCtxt<'b, 'gcx, 'gcx>, - metadata: &mut ModuleLlvm - ) -> EncodedMetadata { - base::write_metadata(tcx, metadata) + metadata: &EncodedMetadata, + llvm_module: &mut ModuleLlvm + ) { + base::write_compressed_metadata(tcx, metadata, llvm_module) } fn codegen_allocator<'b, 'gcx>( &self, @@ -289,9 +290,12 @@ impl CodegenBackend for LlvmCodegenBackend { fn codegen_crate<'b, 'tcx>( &self, tcx: TyCtxt<'b, 'tcx, 'tcx>, + metadata: EncodedMetadata, + need_metadata_module: bool, rx: mpsc::Receiver> ) -> Box { - box rustc_codegen_ssa::base::codegen_crate(LlvmCodegenBackend(()), tcx, rx) + box rustc_codegen_ssa::base::codegen_crate( + LlvmCodegenBackend(()), tcx, metadata, need_metadata_module, rx) } fn join_codegen_and_link( diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 3046c069981cb..3cd47dfbb29fb 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -17,6 +17,7 @@ use crate::{ModuleCodegen, ModuleKind, CachedModuleCodegen}; use rustc::dep_graph::cgu_reuse_tracker::CguReuse; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::middle::cstore::EncodedMetadata; use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::weak_lang_items; use rustc::mir::mono::{Stats, CodegenUnitNameBuilder}; @@ -25,7 +26,7 @@ use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::ty::query::Providers; use rustc::middle::cstore::{self, LinkagePreference}; use rustc::util::common::{time, print_time_passes_entry}; -use rustc::session::config::{self, CrateType, EntryFnType, Lto}; +use rustc::session::config::{self, EntryFnType, Lto}; use rustc::session::Session; use rustc_mir::monomorphize::item::DefPathBasedNames; use rustc_mir::monomorphize::Instance; @@ -530,26 +531,13 @@ pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX; pub fn codegen_crate( backend: B, tcx: TyCtxt<'a, 'tcx, 'tcx>, + metadata: EncodedMetadata, + need_metadata_module: bool, rx: mpsc::Receiver> ) -> OngoingCodegen { check_for_rustc_errors_attr(tcx); - let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); - - // Codegen the metadata. - tcx.sess.profiler(|p| p.start_activity("codegen crate metadata")); - - let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE, - &["crate"], - Some("metadata")).as_str() - .to_string(); - let mut metadata_llvm_module = backend.new_metadata(tcx, &metadata_cgu_name); - let metadata = time(tcx.sess, "write metadata", || { - backend.write_metadata(tcx, &mut metadata_llvm_module) - }); - tcx.sess.profiler(|p| p.end_activity("codegen crate metadata")); - // Skip crate items and just output metadata in -Z no-codegen mode. if tcx.sess.opts.debugging_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() { @@ -569,6 +557,8 @@ pub fn codegen_crate( return ongoing_codegen; } + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); + // Run the monomorphization collector and partition the collected items into // codegen units. let codegen_units = tcx.collect_and_partition_mono_items(LOCAL_CRATE).1; @@ -632,17 +622,21 @@ pub fn codegen_crate( ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module); } - let needs_metadata_module = tcx.sess.crate_types.borrow().iter().any(|ct| { - match *ct { - CrateType::Dylib | - CrateType::ProcMacro => true, - CrateType::Executable | - CrateType::Rlib | - CrateType::Staticlib | - CrateType::Cdylib => false, - } - }); - if needs_metadata_module { + if need_metadata_module { + // Codegen the encoded metadata. + tcx.sess.profiler(|p| p.start_activity("codegen crate metadata")); + + let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE, + &["crate"], + Some("metadata")).as_str() + .to_string(); + let mut metadata_llvm_module = backend.new_metadata(tcx, &metadata_cgu_name); + time(tcx.sess, "write compressed metadata", || { + backend.write_compressed_metadata(tcx, &ongoing_codegen.metadata, + &mut metadata_llvm_module); + }); + tcx.sess.profiler(|p| p.end_activity("codegen crate metadata")); + let metadata_module = ModuleCodegen { name: metadata_cgu_name, module_llvm: metadata_llvm_module, diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index a9e0eadb198a8..530eba516a6c0 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -33,11 +33,12 @@ impl<'tcx, T> Backend<'tcx> for T where pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send { fn new_metadata(&self, sess: TyCtxt<'_, '_, '_>, mod_name: &str) -> Self::Module; - fn write_metadata<'b, 'gcx>( + fn write_compressed_metadata<'b, 'gcx>( &self, tcx: TyCtxt<'b, 'gcx, 'gcx>, - metadata: &mut Self::Module, - ) -> EncodedMetadata; + metadata: &EncodedMetadata, + llvm_module: &mut Self::Module, + ); fn codegen_allocator<'b, 'gcx>( &self, tcx: TyCtxt<'b, 'gcx, 'gcx>, diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 56eaffb1ca31d..191c6605b43ff 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -18,7 +18,7 @@ use rustc::util::common::ErrorReported; use rustc::session::config::{OutputFilenames, PrintRequest}; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; -use rustc::middle::cstore::MetadataLoader; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; use rustc::dep_graph::DepGraph; pub use rustc_data_structures::sync::MetadataRef; @@ -37,6 +37,8 @@ pub trait CodegenBackend { fn codegen_crate<'a, 'tcx>( &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + metadata: EncodedMetadata, + need_metadata_module: bool, rx: mpsc::Receiver> ) -> Box; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index f8b1271b8b5c6..38d641d2f6076 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -16,7 +16,7 @@ use rustc::traits; use rustc::util::common::{time, ErrorReported}; use rustc::util::profiling::ProfileCategory; use rustc::session::{CompileResult, CrateDisambiguator, Session}; -use rustc::session::config::{self, Input, OutputFilenames, OutputType}; +use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType}; use rustc::session::search_paths::PathKind; use rustc_allocator as allocator; use rustc_borrowck as borrowck; @@ -999,6 +999,38 @@ fn analysis<'tcx>( Ok(()) } +fn encode_metadata<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> (middle::cstore::EncodedMetadata, bool) { + #[derive(PartialEq, Eq, PartialOrd, Ord)] + enum MetadataKind { + None, + Uncompressed, + Compressed + } + + let metadata_kind = tcx.sess.crate_types.borrow().iter().map(|ty| { + match *ty { + CrateType::Executable | + CrateType::Staticlib | + CrateType::Cdylib => MetadataKind::None, + + CrateType::Rlib => MetadataKind::Uncompressed, + + CrateType::Dylib | + CrateType::ProcMacro => MetadataKind::Compressed, + } + }).max().unwrap_or(MetadataKind::None); + + let need_metadata_module = metadata_kind == MetadataKind::Compressed; + + let metadata = match metadata_kind { + MetadataKind::None => middle::cstore::EncodedMetadata::new(), + MetadataKind::Uncompressed | + MetadataKind::Compressed => tcx.encode_metadata(), + }; + + (metadata, need_metadata_module) +} + /// Runs the codegen backend, after which the AST and analysis can /// be discarded. pub fn start_codegen<'tcx>( @@ -1013,11 +1045,17 @@ pub fn start_codegen<'tcx>( } time(tcx.sess, "resolving dependency formats", || { - ::rustc::middle::dependency_format::calculate(tcx) + middle::dependency_format::calculate(tcx) + }); + + let (metadata, need_metadata_module) = time(tcx.sess, "metadata encoding", || { + encode_metadata(tcx) }); tcx.sess.profiler(|p| p.start_activity("codegen crate")); - let codegen = time(tcx.sess, "codegen", move || codegen_backend.codegen_crate(tcx, rx)); + let codegen = time(tcx.sess, "codegen", move || { + codegen_backend.codegen_crate(tcx, metadata, need_metadata_module, rx) + }); tcx.sess.profiler(|p| p.end_activity("codegen crate")); if log_enabled!(::log::Level::Info) { diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 5330470da16b0..4e43aa96e1d85 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -15,7 +15,7 @@ use rustc::session::Session; use rustc::session::config::OutputFilenames; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; -use rustc::middle::cstore::MetadataLoader; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; use rustc::dep_graph::DepGraph; use rustc::util::common::ErrorReported; use rustc_codegen_utils::codegen_backend::CodegenBackend; @@ -61,6 +61,8 @@ impl CodegenBackend for TheBackend { fn codegen_crate<'a, 'tcx>( &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + _metadata: EncodedMetadata, + _need_metadata_module: bool, _rx: mpsc::Receiver> ) -> Box { use rustc::hir::def_id::LOCAL_CRATE;