From f6c306d6468509fc27bfcbe2dc3540da90a47fb0 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 12 Jun 2015 04:19:14 +0300 Subject: [PATCH 1/2] rustc_trans: remove unused duplicate definition of OutputType. --- src/librustc_trans/back/write.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 5352c61d8c0ad..1ae0b36cb0e3b 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -36,15 +36,6 @@ use std::sync::mpsc::channel; use std::thread; use libc::{self, c_uint, c_int, c_void}; -#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)] -pub enum OutputType { - OutputTypeBitcode, - OutputTypeAssembly, - OutputTypeLlvmAssembly, - OutputTypeObject, - OutputTypeExe, -} - pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! { unsafe { let cstr = llvm::LLVMRustGetLastError(); From 381267bff92207e73f52ff7be1d74d0f6edff76b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 12 Jun 2015 05:49:42 +0300 Subject: [PATCH 2/2] rustc: --emit=rlibmeta outputs an rlib with only metadata, works with -Z no-trans. --- src/librustc/metadata/encoder.rs | 6 +- src/librustc/session/config.rs | 48 +++++----- src/librustc_driver/driver.rs | 23 +++-- src/librustc_driver/lib.rs | 16 +++- src/librustc_trans/back/link.rs | 75 +++++++++++----- src/librustc_trans/back/write.rs | 6 +- src/librustc_trans/trans/base.rs | 134 ++++++++++++++++------------ src/librustc_trans/trans/context.rs | 49 +++------- src/librustc_trans/trans/mod.rs | 2 +- 9 files changed, 214 insertions(+), 145 deletions(-) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index b217eabec6e6a..caf5d7a5c6d4b 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -251,8 +251,10 @@ fn encode_symbol(ecx: &EncodeContext, rbml_w.wr_tagged_str(tag_items_data_item_symbol, x); } None => { - ecx.diag.handler().bug( - &format!("encode_symbol: id not found {}", id)); + if !ecx.tcx.sess.opts.no_trans { + ecx.diag.handler().bug( + &format!("encode_symbol: id not found {}", id)); + } } } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 48fe574e71f48..9fd616f33d741 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -70,6 +70,7 @@ pub enum OutputType { OutputTypeObject, OutputTypeExe, OutputTypeDepInfo, + OutputTypeRlibMeta, } #[derive(Clone)] @@ -183,6 +184,7 @@ impl OutputFilenames { OutputTypeLlvmAssembly => base.with_extension("ll"), OutputTypeObject => base.with_extension("o"), OutputTypeDepInfo => base.with_extension("d"), + OutputTypeRlibMeta => base.with_extension("rmeta"), OutputTypeExe => base, } } @@ -785,7 +787,7 @@ pub fn rustc_short_optgroups() -> Vec { "NAME"), opt::multi("", "emit", "Comma separated list of types of output for \ the compiler to emit", - "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"), + "[asm|llvm-bc|llvm-ir|obj|link|dep-info|rlibmeta]"), opt::multi("", "print", "Comma separated list of compiler information to \ print on stdout", "[crate-name|file-names|sysroot]"), @@ -886,29 +888,33 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } let mut output_types = Vec::new(); - if !debugging_opts.parse_only && !no_trans { - let unparsed_output_types = matches.opt_strs("emit"); - for unparsed_output_type in &unparsed_output_types { - for part in unparsed_output_type.split(',') { - let output_type = match part { - "asm" => OutputTypeAssembly, - "llvm-ir" => OutputTypeLlvmAssembly, - "llvm-bc" => OutputTypeBitcode, - "obj" => OutputTypeObject, - "link" => OutputTypeExe, - "dep-info" => OutputTypeDepInfo, - _ => { - early_error(&format!("unknown emission type: `{}`", - part)) - } - }; - output_types.push(output_type) - } + let unparsed_output_types = matches.opt_strs("emit"); + for unparsed_output_type in &unparsed_output_types { + for part in unparsed_output_type.split(',') { + let output_type = match part { + "asm" => OutputTypeAssembly, + "llvm-ir" => OutputTypeLlvmAssembly, + "llvm-bc" => OutputTypeBitcode, + "obj" => OutputTypeObject, + "link" => OutputTypeExe, + "dep-info" => OutputTypeDepInfo, + "rlibmeta" => OutputTypeRlibMeta, + _ => { + early_error(&format!("unknown emission type: `{}`", + part)) + } + }; + output_types.push(output_type) } - }; + } output_types.sort(); output_types.dedup(); - if output_types.is_empty() { + + if debugging_opts.parse_only { + output_types = vec![]; + } else if no_trans { + output_types.retain(|&x| x == OutputTypeRlibMeta); + } else if output_types.is_empty() { output_types.push(OutputTypeExe); } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index eaac1eb6f2cb0..b58a69a27d543 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -101,6 +101,7 @@ pub fn compile_input(sess: Session, CompileState::state_after_expand(input, &sess, outdir, + &outputs, &expanded_crate, &id[..])); @@ -115,6 +116,7 @@ pub fn compile_input(sess: Session, CompileState::state_after_write_deps(input, &sess, outdir, + &outputs, &ast_map, &ast_map.krate(), &id[..])); @@ -130,6 +132,7 @@ pub fn compile_input(sess: Session, CompileState::state_after_analysis(input, &analysis.ty_cx.sess, outdir, + &outputs, analysis.ty_cx.map.krate(), &analysis, &analysis.ty_cx)); @@ -157,6 +160,7 @@ pub fn compile_input(sess: Session, CompileState::state_after_llvm(input, &sess, outdir, + &outputs, &trans)); phase_6_link_output(&sess, &trans, &outputs); @@ -280,12 +284,14 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn state_after_expand(input: &'a Input, session: &'a Session, out_dir: &'a Option, + outputs: &'a OutputFilenames, expanded_crate: &'a ast::Crate, crate_name: &'a str) -> CompileState<'a, 'ast, 'tcx> { CompileState { crate_name: Some(crate_name), expanded_crate: Some(expanded_crate), + output_filenames: Some(outputs), .. CompileState::empty(input, session, out_dir) } } @@ -293,6 +299,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn state_after_write_deps(input: &'a Input, session: &'a Session, out_dir: &'a Option, + outputs: &'a OutputFilenames, ast_map: &'a ast_map::Map<'ast>, expanded_crate: &'a ast::Crate, crate_name: &'a str) @@ -301,6 +308,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { crate_name: Some(crate_name), ast_map: Some(ast_map), expanded_crate: Some(expanded_crate), + output_filenames: Some(outputs), .. CompileState::empty(input, session, out_dir) } } @@ -308,6 +316,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn state_after_analysis(input: &'a Input, session: &'a Session, out_dir: &'a Option, + outputs: &'a OutputFilenames, expanded_crate: &'a ast::Crate, analysis: &'a ty::CrateAnalysis<'tcx>, tcx: &'a ty::ctxt<'tcx>) @@ -316,6 +325,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { analysis: Some(analysis), tcx: Some(tcx), expanded_crate: Some(expanded_crate), + output_filenames: Some(outputs), .. CompileState::empty(input, session, out_dir) } } @@ -324,10 +334,12 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn state_after_llvm(input: &'a Input, session: &'a Session, out_dir: &'a Option, + outputs: &'a OutputFilenames, trans: &'a trans::CrateTranslation) -> CompileState<'a, 'ast, 'tcx> { CompileState { trans: Some(trans), + output_filenames: Some(outputs), .. CompileState::empty(input, session, out_dir) } } @@ -788,12 +800,13 @@ fn write_out_deps(sess: &Session, id: &str) { let mut out_filenames = Vec::new(); - for output_type in &sess.opts.output_types { - let file = outputs.path(*output_type); - match *output_type { + for &output_type in &sess.opts.output_types { + let file = outputs.path(output_type); + match output_type { config::OutputTypeExe => { - for output in sess.crate_types.borrow().iter() { - let p = link::filename_for_input(sess, *output, + for &output in sess.crate_types.borrow().iter() { + let p = link::filename_for_input(sess, output, + output_type, id, &file); out_filenames.push(p); } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6ae0ea81c3dda..64306fa0ca693 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -368,9 +368,22 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { if sess.opts.no_trans { control.after_analysis.stop = Compilation::Stop; + if sess.opts.output_types.contains(&config::OutputTypeRlibMeta) { + control.after_analysis.callback = box |state| { + use rustc_trans::trans; + + let tcx = state.tcx.unwrap(); + let name = state.analysis.unwrap().name.clone(); + let trans = trans::trans_only_metadata(tcx, name); + let outputs = state.output_filenames.unwrap(); + driver::phase_6_link_output(&tcx.sess, &trans, outputs); + }; + } } - if !sess.opts.output_types.iter().any(|&i| i == config::OutputTypeExe) { + if !sess.opts.output_types.iter().any(|&i| + i == config::OutputTypeExe || + i == config::OutputTypeRlibMeta) { control.after_llvm.stop = Compilation::Stop; } @@ -456,6 +469,7 @@ impl RustcDefaultCalls { for &style in &crate_types { let fname = link::filename_for_input(sess, style, + config::OutputTypeExe, &id, &t_outputs.with_extension("")); println!("{}", fname.file_name().unwrap() diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index e2c816bb84df6..3e99f132a3e0e 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -389,25 +389,39 @@ pub fn link_binary(sess: &Session, outputs: &OutputFilenames, crate_name: &str) -> Vec { let mut out_filenames = Vec::new(); - for &crate_type in sess.crate_types.borrow().iter() { + if sess.opts.output_types.contains(&config::OutputTypeExe) { + for &crate_type in sess.crate_types.borrow().iter() { + if invalid_output_for_target(sess, crate_type) { + sess.bug(&format!("invalid output type `{:?}` for target os `{}`", + crate_type, sess.opts.target_triple)); + } + let out_file = link_binary_output(sess, trans, crate_type, outputs, + crate_name, None); + out_filenames.push(out_file); + } + + // Remove the temporary object file and metadata if we aren't saving temps + if !sess.opts.cg.save_temps { + let obj_filename = outputs.temp_path(OutputTypeObject); + if !sess.opts.output_types.contains(&OutputTypeObject) { + remove(sess, &obj_filename); + } + remove(sess, &obj_filename.with_extension("metadata.o")); + } + } + + // Attempt to output an rlib with just metadata, if that was requested. + if sess.opts.output_types.contains(&config::OutputTypeRlibMeta) { + let crate_type = config::CrateTypeRlib; if invalid_output_for_target(sess, crate_type) { sess.bug(&format!("invalid output type `{:?}` for target os `{}`", - crate_type, sess.opts.target_triple)); + crate_type, sess.opts.target_triple)); } let out_file = link_binary_output(sess, trans, crate_type, outputs, - crate_name); + crate_name, Some(config::OutputTypeRlibMeta)); out_filenames.push(out_file); } - // Remove the temporary object file and metadata if we aren't saving temps - if !sess.opts.cg.save_temps { - let obj_filename = outputs.temp_path(OutputTypeObject); - if !sess.opts.output_types.contains(&OutputTypeObject) { - remove(sess, &obj_filename); - } - remove(sess, &obj_filename.with_extension("metadata.o")); - } - out_filenames } @@ -449,12 +463,18 @@ fn is_writeable(p: &Path) -> bool { pub fn filename_for_input(sess: &Session, crate_type: config::CrateType, + output_type: config::OutputType, name: &str, out_filename: &Path) -> PathBuf { let libname = format!("{}{}", name, sess.opts.cg.extra_filename); match crate_type { config::CrateTypeRlib => { - out_filename.with_file_name(&format!("lib{}.rlib", libname)) + let suffix = if output_type == config::OutputTypeRlibMeta { + ".rmeta" + } else { + "" + }; + out_filename.with_file_name(&format!("lib{}{}.rlib", libname, suffix)) } config::CrateTypeDylib => { let (prefix, suffix) = (&sess.target.target.options.dll_prefix, @@ -482,13 +502,16 @@ fn link_binary_output(sess: &Session, trans: &CrateTranslation, crate_type: config::CrateType, outputs: &OutputFilenames, - crate_name: &str) -> PathBuf { + crate_name: &str, + custom_rlib_emission: Option) + -> PathBuf { let obj_filename = outputs.temp_path(OutputTypeObject); let out_filename = match outputs.single_output_file { Some(ref file) => file.clone(), None => { - let out_filename = outputs.path(OutputTypeExe); - filename_for_input(sess, crate_type, crate_name, &out_filename) + let output_type = custom_rlib_emission.unwrap_or(OutputTypeExe); + let out_filename = outputs.path(output_type); + filename_for_input(sess, crate_type, output_type, crate_name, &out_filename) } }; @@ -511,7 +534,12 @@ fn link_binary_output(sess: &Session, match crate_type { config::CrateTypeRlib => { - link_rlib(sess, Some(trans), &obj_filename, &out_filename).build(); + let obj_filename = if custom_rlib_emission.is_some() { + None + } else { + Some(&*obj_filename) + }; + link_rlib(sess, Some(trans), obj_filename, &out_filename).build(); } config::CrateTypeStaticlib => { link_staticlib(sess, &obj_filename, &out_filename); @@ -544,7 +572,7 @@ fn archive_search_paths(sess: &Session) -> Vec { // native libraries and inserting all of the contents into this archive. fn link_rlib<'a>(sess: &'a Session, trans: Option<&CrateTranslation>, // None == no metadata/bytecode - obj_filename: &Path, + obj_filename: Option<&Path>, out_filename: &Path) -> ArchiveBuilder<'a> { info!("preparing rlib from {:?} to {:?}", obj_filename, out_filename); let handler = &sess.diagnostic().handler; @@ -557,7 +585,7 @@ fn link_rlib<'a>(sess: &'a Session, ar_prog: get_ar_prog(sess), }; let mut ab = ArchiveBuilder::create(config); - ab.add_file(obj_filename).unwrap(); + obj_filename.map(|file| ab.add_file(file).unwrap()); for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() { match kind { @@ -619,6 +647,13 @@ fn link_rlib<'a>(sess: &'a Session, ab.add_file(&metadata).unwrap(); remove(sess, &metadata); + // Nothing else to add if we have no code. + let obj_filename = if let Some(file) = obj_filename { + file + } else { + return ab; + }; + // For LTO purposes, the bytecode of this library is also inserted // into the archive. If codegen_units > 1, we insert each of the // bitcode files. @@ -734,7 +769,7 @@ fn write_rlib_bytecode_object_v1(writer: &mut Write, // link in the metadata object file (and also don't prepare the archive with a // metadata file). fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) { - let ab = link_rlib(sess, None, obj_filename, out_filename); + let ab = link_rlib(sess, None, Some(obj_filename), out_filename); let mut ab = match sess.target.target.options.is_like_osx { true => ab.build().extend(), false => ab, diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 1ae0b36cb0e3b..75bef1f5bb99a 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -620,7 +620,8 @@ pub fn run_passes(sess: &Session, modules_config.emit_obj = true; metadata_config.emit_obj = true; }, - config::OutputTypeDepInfo => {} + config::OutputTypeDepInfo | + config::OutputTypeRlibMeta => {} } } @@ -793,7 +794,8 @@ pub fn run_passes(sess: &Session, link_obj(&crate_output.temp_path(config::OutputTypeObject)); } } - config::OutputTypeDepInfo => {} + config::OutputTypeDepInfo | + config::OutputTypeRlibMeta => {} } } let user_wants_bitcode = user_wants_bitcode; diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index aad986cd34a3b..61e2b5bb4c790 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -35,6 +35,7 @@ use lint; use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param}; use llvm; use metadata::{csearch, encoder, loader}; +use metadata::common::LinkMeta; use middle::astencode; use middle::cfg; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; @@ -61,7 +62,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::{self, SharedCrateContext}; use trans::controlflow; use trans::datum; use trans::debuginfo::{self, DebugLoc, ToDebugLoc}; @@ -82,7 +83,7 @@ use trans::value::Value; use util::common::indenter; use util::ppaux::{Repr, ty_to_string}; use util::sha2::Sha256; -use util::nodemap::NodeMap; +use util::nodemap::{NodeMap, NodeSet, FnvHashMap}; use arena::TypedArena; use libc::c_uint; @@ -2477,55 +2478,57 @@ fn register_method(ccx: &CrateContext, id: ast::NodeId, } } -pub fn crate_ctxt_to_encode_parms<'a, 'tcx>(cx: &'a SharedCrateContext<'tcx>, - ie: encoder::EncodeInlinedItem<'a>) - -> encoder::EncodeParams<'a, 'tcx> { - encoder::EncodeParams { - diag: cx.sess().diagnostic(), - tcx: cx.tcx(), - reexports: cx.export_map(), - item_symbols: cx.item_symbols(), - link_meta: cx.link_meta(), - cstore: &cx.sess().cstore, - encode_inlined_item: ie, - reachable: cx.reachable(), - } -} - -pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { +pub fn write_metadata(tcx: &ty::ctxt, link_meta: &LinkMeta, + ccx: Option<&SharedCrateContext>) + -> (Vec, ModuleTranslation) { use flate; - let any_library = cx.sess().crate_types.borrow().iter().any(|ty| { + let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { *ty != config::CrateTypeExecutable }); - if !any_library { - return Vec::new() - } - - 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 (llcx, llmod) = context::create_context_and_module(&tcx.sess, "metadata"); + let module = ModuleTranslation { + llcx: llcx, + llmod: llmod + }; + if !any_library { + return (vec![], module); + } + + let empty_reexports = FnvHashMap(); + let empty_item_symbols = RefCell::new(NodeMap()); + let empty_reachable = NodeSet(); + let encode_parms = encoder::EncodeParams { + diag: tcx.sess.diagnostic(), + tcx: tcx, + reexports: ccx.map_or(&empty_reexports, |cx| cx.export_map()), + item_symbols: ccx.map_or(&empty_item_symbols, |cx| cx.item_symbols()), + link_meta: link_meta, + cstore: &tcx.sess.cstore, + encode_inlined_item: box astencode::encode_inlined_item, + reachable: ccx.map_or(&empty_reachable, |cx| cx.reachable()), + }; + let metadata = encoder::encode_metadata(encode_parms, tcx.map.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 llmeta = C_bytes_in_context(llcx, &compressed[..]); + let llconst = C_struct_in_context(llcx, &[llmeta], false); let name = format!("rust_metadata_{}_{}", - cx.link_meta().crate_name, - cx.link_meta().crate_hash); + link_meta.crate_name, + 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()) + llvm::LLVMAddGlobal(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 = loader::meta_section_name(&tcx.sess.target.target); let name = CString::new(name).unwrap(); llvm::LLVMSetSection(llglobal, name.as_ptr()) } - return metadata; + (metadata, module) } /// Find any symbols that are defined in one compilation unit, but not declared @@ -2613,23 +2616,7 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet) { } } -pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) - -> (ty::ctxt<'tcx>, CrateTranslation) { - let ty::CrateAnalysis { ty_cx: tcx, export_map, reachable, name, .. } = analysis; - let krate = tcx.map.krate(); - - let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks { - v - } else { - tcx.sess.opts.debug_assertions - }; - - let check_dropflag = if let Some(v) = tcx.sess.opts.debugging_opts.force_dropflag_checks { - v - } else { - tcx.sess.opts.debug_assertions - }; - +fn initialize_llvm(sess: &Session) { // Before we touch LLVM, make sure that multithreading is enabled. unsafe { use std::sync::Once; @@ -2644,10 +2631,29 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) }); if POISONED { - tcx.sess.bug("couldn't enable multi-threaded LLVM"); + sess.bug("couldn't enable multi-threaded LLVM"); } } +} + +pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) + -> (ty::ctxt<'tcx>, CrateTranslation) { + let ty::CrateAnalysis { ty_cx: tcx, export_map, reachable, name, .. } = analysis; + let krate = tcx.map.krate(); + + let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks { + v + } else { + tcx.sess.opts.debug_assertions + }; + let check_dropflag = if let Some(v) = tcx.sess.opts.debugging_opts.force_dropflag_checks { + v + } else { + tcx.sess.opts.debug_assertions + }; + + initialize_llvm(&tcx.sess); let link_meta = link::build_link_meta(&tcx.sess, krate, name); let codegen_units = tcx.sess.opts.cg.codegen_units; @@ -2681,7 +2687,8 @@ 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.tcx(), &link_meta, + Some(&shared_ccx)); if shared_ccx.sess().trans_stats() { let stats = shared_ccx.stats(); @@ -2748,10 +2755,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"); @@ -2767,3 +2770,18 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) (shared_ccx.take_tcx(), translation) } + +pub fn trans_only_metadata(tcx: &ty::ctxt, name: String) -> CrateTranslation { + initialize_llvm(&tcx.sess); + let link_meta = link::build_link_meta(&tcx.sess, tcx.map.krate(), name); + let (metadata, metadata_module) = write_metadata(tcx, &link_meta, None); + CrateTranslation { + modules: vec![], + metadata_module: metadata_module, + link: link_meta, + metadata: metadata, + reachable: vec![], + crate_formats: tcx.dependency_formats.borrow().clone(), + no_builtins: true + } +} diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 663a01e19f342..e21120b65946b 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>, @@ -221,20 +218,21 @@ impl<'a, 'tcx> Iterator for CrateContextMaybeIterator<'a, 'tcx> { } } +pub fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) { + unsafe { + let llcx = llvm::LLVMContextCreate(); + let mod_name = CString::new(mod_name).unwrap(); + let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); -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); - - let data_layout = sess.target.target.data_layout.as_bytes(); - let data_layout = CString::new(data_layout).unwrap(); - llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); + let data_layout = sess.target.target.data_layout.as_bytes(); + let data_layout = CString::new(data_layout).unwrap(); + llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); - let llvm_target = sess.target.target.llvm_target.as_bytes(); - let llvm_target = CString::new(llvm_target).unwrap(); - llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); - (llcx, llmod) + let llvm_target = sess.target.target.llvm_target.as_bytes(); + let llvm_target = CString::new(llvm_target).unwrap(); + llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); + (llcx, llmod) + } } impl<'tcx> SharedCrateContext<'tcx> { @@ -248,10 +246,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 +293,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,14 +364,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 } @@ -392,10 +376,6 @@ impl<'tcx> SharedCrateContext<'tcx> { &self.item_symbols } - pub fn link_meta<'a>(&'a self) -> &'a LinkMeta { - &self.link_meta - } - pub fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { &self.tcx } @@ -421,9 +401,8 @@ impl<'tcx> LocalCrateContext<'tcx> { fn new(shared: &SharedCrateContext<'tcx>, name: &str) -> LocalCrateContext<'tcx> { + let (llcx, llmod) = create_context_and_module(&shared.tcx.sess, name); unsafe { - let (llcx, llmod) = create_context_and_module(&shared.tcx.sess, name); - let td = mk_target_data(&shared.tcx .sess .target diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index 7d568ff90ea43..ae40a0c340de1 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -12,7 +12,7 @@ use llvm::{ContextRef, ModuleRef}; use metadata::common::LinkMeta; use middle::dependency_format; -pub use self::base::trans_crate; +pub use self::base::{trans_crate, trans_only_metadata}; pub use self::context::CrateContext; pub use self::common::gensym_name;