diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index c416a9810eb0e..9ab96b66d2736 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -389,7 +389,9 @@ pub fn link_binary(sess: &Session, outputs: &OutputFilenames, crate_name: &str) -> Vec { let mut out_filenames = Vec::new(); + let mut dylib = false; 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)); @@ -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 diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 5352c61d8c0ad..e8f2e293f6c0b 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -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()); @@ -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")); } } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index c3f614c8cc06a..3fede97a7149f 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -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}; @@ -2513,14 +2513,14 @@ pub fn crate_ctxt_to_encode_parms<'a, 'tcx>(cx: &'a SharedCrateContext<'tcx>, } } -pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { +pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> (Vec, Option) { 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 = @@ -2528,25 +2528,44 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { 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); } - return metadata; } /// Find any symbols that are defined in one compilation unit, but not declared @@ -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(); @@ -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"); diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 51db0adf5b775..1fd802b3a8ca9 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -60,9 +60,6 @@ pub struct Stats { pub struct SharedCrateContext<'tcx> { local_ccxs: Vec>, - metadata_llmod: ModuleRef, - metadata_llcx: ContextRef, - export_map: ExportMap, reachable: NodeSet, item_symbols: RefCell>, @@ -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); @@ -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 @@ -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()), @@ -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 } diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index 7d568ff90ea43..5efc1fdb7da80 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -70,7 +70,7 @@ unsafe impl Sync for ModuleTranslation { } pub struct CrateTranslation { pub modules: Vec, - pub metadata_module: ModuleTranslation, + pub metadata_module: Option, pub link: LinkMeta, pub metadata: Vec, pub reachable: Vec,