Skip to content

Don't compress metadata when not producing dylibs #26081

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,9 @@ pub fn link_binary(sess: &Session,
outputs: &OutputFilenames,
crate_name: &str) -> Vec<PathBuf> {
let mut out_filenames = Vec::new();
let mut dylib = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also be fine with just a if sess.crate_types.borrow().contains(&config::CrateTypeDylib) check below (this isn't perf-sensitive or anything).

for &crate_type in &*sess.crate_types.borrow() {
dylib = dylib || crate_type == config::CrateTypeDylib;
if invalid_output_for_target(sess, crate_type) {
sess.bug(&format!("invalid output type `{:?}` for target os `{}`",
crate_type, sess.opts.target_triple));
Expand All @@ -405,7 +407,10 @@ pub fn link_binary(sess: &Session,
if !sess.opts.output_types.contains(&OutputTypeObject) {
remove(sess, &obj_filename);
}
remove(sess, &obj_filename.with_extension("metadata.o"));
if dylib {
// metadata.o is only produced for dylibs
remove(sess, &obj_filename.with_extension("metadata.o"));
}
}

out_filenames
Expand Down
7 changes: 4 additions & 3 deletions src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,9 +642,9 @@ pub fn run_passes(sess: &Session,
// doesn't actually matter.)
let mut work_items = Vec::with_capacity(1 + trans.modules.len());

{
if let Some(m) = trans.metadata_module {
let work = build_work_item(sess,
trans.metadata_module,
m,
metadata_config.clone(),
crate_output.clone(),
"metadata".to_string());
Expand Down Expand Up @@ -850,7 +850,8 @@ pub fn run_passes(sess: &Session,
}
}

if metadata_config.emit_bc && !user_wants_bitcode {
if metadata_config.emit_bc &&
trans.metadata_module.is_some() && !user_wants_bitcode {
remove(sess, &crate_output.with_extension("metadata.bc"));
}
}
Expand Down
71 changes: 43 additions & 28 deletions src/librustc_trans/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ use trans::common::{node_id_type, return_type_is_void};
use trans::common::{type_is_immediate, type_is_zero_size, val_ty};
use trans::common;
use trans::consts;
use trans::context::SharedCrateContext;
use trans::context::{SharedCrateContext, create_context_and_module};
use trans::controlflow;
use trans::datum;
use trans::debuginfo::{self, DebugLoc, ToDebugLoc};
Expand Down Expand Up @@ -2513,40 +2513,59 @@ pub fn crate_ctxt_to_encode_parms<'a, 'tcx>(cx: &'a SharedCrateContext<'tcx>,
}
}

pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> (Vec<u8>, Option<ModuleTranslation>) {
use flate;

let any_library = cx.sess().crate_types.borrow().iter().any(|ty| {
let need_metadata = cx.sess().crate_types.borrow().iter().any(|ty| {
*ty != config::CrateTypeExecutable
});
if !any_library {
return Vec::new()
if !need_metadata {
return (Vec::new(), None);
}

let encode_inlined_item: encoder::EncodeInlinedItem =
Box::new(|ecx, rbml_w, ii| astencode::encode_inlined_item(ecx, rbml_w, ii));

let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
let metadata = encoder::encode_metadata(encode_parms, krate);
let mut compressed = encoder::metadata_encoding_version.to_vec();
compressed.push_all(&flate::deflate_bytes(&metadata));
let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]);
let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
let name = format!("rust_metadata_{}_{}",
cx.link_meta().crate_name,
cx.link_meta().crate_hash);
let buf = CString::new(name).unwrap();
let llglobal = unsafe {
llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(),
buf.as_ptr())
};
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
let name = loader::meta_section_name(&cx.sess().target.target);
let name = CString::new(name).unwrap();
llvm::LLVMSetSection(llglobal, name.as_ptr())

let need_metadata_module = cx.sess().crate_types.borrow().iter().any(|ty| {
*ty == config::CrateTypeDylib
});

if !need_metadata_module {
return (metadata, None);
} else {
let (metadata_llcx, metadata_llmod) = unsafe {
create_context_and_module(cx.sess(), "metadata")
};

let mut compressed = encoder::metadata_encoding_version.to_vec();
compressed.push_all(&flate::deflate_bytes(&metadata));
let llmeta = C_bytes_in_context(metadata_llcx, &compressed[..]);
let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
let name = format!("rust_metadata_{}_{}",
cx.link_meta().crate_name,
cx.link_meta().crate_hash);
let buf = CString::new(name).unwrap();
let llglobal = unsafe {
llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst).to_ref(),
buf.as_ptr())
};
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
let name = loader::meta_section_name(&cx.sess().target.target);
let name = CString::new(name).unwrap();
llvm::LLVMSetSection(llglobal, name.as_ptr())
}

let metadata_module = Some(ModuleTranslation {
llcx: metadata_llcx,
llmod: metadata_llmod,
});

return (metadata, metadata_module);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this all be tabbed left by one after the return (metadata, None) case above? Helps rightward drift a bit.

}
return metadata;
}

/// Find any symbols that are defined in one compilation unit, but not declared
Expand Down Expand Up @@ -2702,7 +2721,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
}

// Translate the metadata.
let metadata = write_metadata(&shared_ccx, krate);
let (metadata, metadata_module) = write_metadata(&shared_ccx, krate);

if shared_ccx.sess().trans_stats() {
let stats = shared_ccx.stats();
Expand Down Expand Up @@ -2769,10 +2788,6 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
internalize_symbols(&shared_ccx, &reachable.iter().cloned().collect());
}

let metadata_module = ModuleTranslation {
llcx: shared_ccx.metadata_llcx(),
llmod: shared_ccx.metadata_llmod(),
};
let formats = shared_ccx.tcx().dependency_formats.borrow().clone();
let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");

Expand Down
20 changes: 1 addition & 19 deletions src/librustc_trans/trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ pub struct Stats {
pub struct SharedCrateContext<'tcx> {
local_ccxs: Vec<LocalCrateContext<'tcx>>,

metadata_llmod: ModuleRef,
metadata_llcx: ContextRef,

export_map: ExportMap,
reachable: NodeSet,
item_symbols: RefCell<NodeMap<String>>,
Expand Down Expand Up @@ -222,7 +219,7 @@ impl<'a, 'tcx> Iterator for CrateContextMaybeIterator<'a, 'tcx> {
}


unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
let llcx = llvm::LLVMContextCreate();
let mod_name = CString::new(mod_name).unwrap();
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
Expand All @@ -248,10 +245,6 @@ impl<'tcx> SharedCrateContext<'tcx> {
check_overflow: bool,
check_drop_flag_for_sanity: bool)
-> SharedCrateContext<'tcx> {
let (metadata_llcx, metadata_llmod) = unsafe {
create_context_and_module(&tcx.sess, "metadata")
};

// An interesting part of Windows which MSVC forces our hand on (and
// apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
// attributes in LLVM IR as well as native dependencies (in C these
Expand Down Expand Up @@ -299,8 +292,6 @@ impl<'tcx> SharedCrateContext<'tcx> {

let mut shared_ccx = SharedCrateContext {
local_ccxs: Vec::with_capacity(local_count),
metadata_llmod: metadata_llmod,
metadata_llcx: metadata_llcx,
export_map: export_map,
reachable: reachable,
item_symbols: RefCell::new(NodeMap()),
Expand Down Expand Up @@ -372,15 +363,6 @@ impl<'tcx> SharedCrateContext<'tcx> {
}
}


pub fn metadata_llmod(&self) -> ModuleRef {
self.metadata_llmod
}

pub fn metadata_llcx(&self) -> ContextRef {
self.metadata_llcx
}

pub fn export_map<'a>(&'a self) -> &'a ExportMap {
&self.export_map
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ unsafe impl Sync for ModuleTranslation { }

pub struct CrateTranslation {
pub modules: Vec<ModuleTranslation>,
pub metadata_module: ModuleTranslation,
pub metadata_module: Option<ModuleTranslation>,
pub link: LinkMeta,
pub metadata: Vec<u8>,
pub reachable: Vec<String>,
Expand Down