Skip to content

Commit

Permalink
Move metadata encoding earlier.
Browse files Browse the repository at this point in the history
This commit separates metadata encoding (`tcx.encode_metadata`) from the
creation of the metadata module (which is now handled by
`write_compressed_metadata`, formerly `write_metadata`).

The metadata encoding now occurs slightly earlier in the pipeline, at
the very start of code generation within `start_codegen`.

Metadata *writing* still occurs near the end of compilation; that will
be moved forward in subsequent commits.
  • Loading branch information
nnethercote committed Apr 30, 2019
1 parent 03122e1 commit faf5eac
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 76 deletions.
40 changes: 4 additions & 36 deletions src/librustc_codegen_llvm/base.rs
Expand Up @@ -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;

Expand All @@ -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();
Expand All @@ -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> {
Expand Down
14 changes: 9 additions & 5 deletions src/librustc_codegen_llvm/lib.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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<dyn Any + Send>>
) -> Box<dyn Any> {
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(
Expand Down
48 changes: 21 additions & 27 deletions src/librustc_codegen_ssa/base.rs
Expand Up @@ -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};
Expand All @@ -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;
Expand Down Expand Up @@ -530,26 +531,13 @@ pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
pub fn codegen_crate<B: ExtraBackendMethods>(
backend: B,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
metadata: EncodedMetadata,
need_metadata_module: bool,
rx: mpsc::Receiver<Box<dyn Any + Send>>
) -> OngoingCodegen<B> {

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() {
Expand All @@ -569,6 +557,8 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
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;
Expand Down Expand Up @@ -632,17 +622,21 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
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,
Expand Down
7 changes: 4 additions & 3 deletions src/librustc_codegen_ssa/traits/backend.rs
Expand Up @@ -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>,
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_codegen_utils/codegen_backend.rs
Expand Up @@ -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;
Expand All @@ -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<dyn Any + Send>>
) -> Box<dyn Any>;

Expand Down
44 changes: 41 additions & 3 deletions src/librustc_interface/passes.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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>(
Expand All @@ -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) {
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Any + Send>>
) -> Box<Any> {
use rustc::hir::def_id::LOCAL_CRATE;
Expand Down

0 comments on commit faf5eac

Please sign in to comment.