From c4adeceb37e4bdf9be3b70ff2454b121531466ce Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 21 Jul 2017 15:14:21 +0200 Subject: [PATCH] async-llvm(1): Run LLVM already in trans_crate(). --- src/librustc_driver/driver.rs | 57 +++++---------------------- src/librustc_trans/back/write.rs | 12 ++---- src/librustc_trans/base.rs | 66 ++++++++++++++++++++++++-------- src/librustc_trans/lib.rs | 66 +++++++++++++++++++++++++++++++- 4 files changed, 129 insertions(+), 72 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c592882a1e43..1bc3f59ed047 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -15,8 +15,7 @@ use rustc_data_structures::stable_hasher::StableHasher; use rustc_mir as mir; use rustc::session::{Session, CompileResult}; use rustc::session::CompileIncomplete; -use rustc::session::config::{self, Input, OutputFilenames, OutputType, - OutputTypes}; +use rustc::session::config::{self, Input, OutputFilenames, OutputType}; use rustc::session::search_paths::PathKind; use rustc::lint; use rustc::middle::{self, dependency_format, stability, reachable}; @@ -26,7 +25,6 @@ use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas}; use rustc::traits; use rustc::util::common::{ErrorReported, time}; use rustc::util::nodemap::NodeSet; -use rustc::util::fs::rename_or_copy_remove; use rustc_allocator as allocator; use rustc_borrowck as borrowck; use rustc_incremental::{self, IncrementalHashesMap}; @@ -231,7 +229,7 @@ pub fn compile_input(sess: &Session, sess.code_stats.borrow().print_type_sizes(); } - let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs); + let (phase5_result, trans) = phase_5_run_llvm_passes(sess, trans, &outputs); controller_entry_point!(after_llvm, sess, @@ -1057,7 +1055,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, analysis: ty::CrateAnalysis, incremental_hashes_map: &IncrementalHashesMap, output_filenames: &OutputFilenames) - -> trans::CrateTranslation { + -> trans::OngoingCrateTranslation { let time_passes = tcx.sess.time_passes(); time(time_passes, @@ -1069,61 +1067,26 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "translation", move || trans::trans_crate(tcx, analysis, &incremental_hashes_map, output_filenames)); - time(time_passes, - "assert dep graph", - || rustc_incremental::assert_dep_graph(tcx)); - - time(time_passes, - "serialize dep graph", - || rustc_incremental::save_dep_graph(tcx, - &incremental_hashes_map, - &translation.metadata.hashes, - translation.link.crate_hash)); translation } /// Run LLVM itself, producing a bitcode file, assembly file or object file /// as a side effect. pub fn phase_5_run_llvm_passes(sess: &Session, - trans: &trans::CrateTranslation, - outputs: &OutputFilenames) -> CompileResult { - if sess.opts.cg.no_integrated_as || - (sess.target.target.options.no_integrated_as && - (outputs.outputs.contains_key(&OutputType::Object) || - outputs.outputs.contains_key(&OutputType::Exe))) - { - let output_types = OutputTypes::new(&[(OutputType::Assembly, None)]); - time(sess.time_passes(), - "LLVM passes", - || write::run_passes(sess, trans, &output_types, outputs)); + trans: trans::OngoingCrateTranslation, + outputs: &OutputFilenames) + -> (CompileResult, trans::CrateTranslation) { + let trans = trans.join(sess, outputs); - write::run_assembler(sess, outputs); - - // HACK the linker expects the object file to be named foo.0.o but - // `run_assembler` produces an object named just foo.o. Rename it if we - // are going to build an executable - if sess.opts.output_types.contains_key(&OutputType::Exe) { - let f = outputs.path(OutputType::Object); - rename_or_copy_remove(&f, - f.with_file_name(format!("{}.0.o", - f.file_stem().unwrap().to_string_lossy()))).unwrap(); - } - - // Remove assembly source, unless --save-temps was specified - if !sess.opts.cg.save_temps { - fs::remove_file(&outputs.temp_path(OutputType::Assembly, None)).unwrap(); - } - } else { - time(sess.time_passes(), - "LLVM passes", - || write::run_passes(sess, trans, &sess.opts.output_types, outputs)); + if sess.opts.debugging_opts.incremental_info { + write::dump_incremental_data(&trans); } time(sess.time_passes(), "serialize work products", move || rustc_incremental::save_work_products(sess)); - sess.compile_status() + (sess.compile_status(), trans) } /// Run the linker on any artifacts that resulted from the LLVM run. diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 26553c85023b..4af4ee664a25 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -18,7 +18,7 @@ use rustc::session::Session; use llvm; use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef}; use llvm::SMDiagnosticRef; -use {CrateTranslation, ModuleLlvm, ModuleSource, ModuleTranslation}; +use {CrateTranslation, OngoingCrateTranslation, ModuleLlvm, ModuleSource, ModuleTranslation}; use rustc::hir::def_id::CrateNum; use rustc::util::common::{time, time_depth, set_time_depth, path2cstr}; use rustc::util::fs::link_or_copy; @@ -255,7 +255,7 @@ impl ModuleConfig { } } - fn set_flags(&mut self, sess: &Session, trans: &CrateTranslation) { + fn set_flags(&mut self, sess: &Session, trans: &OngoingCrateTranslation) { self.no_verify = sess.no_verify(); self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes; self.no_builtins = trans.no_builtins; @@ -614,7 +614,7 @@ pub fn cleanup_llvm(trans: &CrateTranslation) { } pub fn run_passes(sess: &Session, - trans: &CrateTranslation, + trans: &OngoingCrateTranslation, output_types: &OutputTypes, crate_output: &OutputFilenames) { // It's possible that we have `codegen_units > 1` but only one item in @@ -748,10 +748,6 @@ pub fn run_passes(sess: &Session, work_items.push(work); } - if sess.opts.debugging_opts.incremental_info { - dump_incremental_data(&trans); - } - let client = sess.jobserver_from_env.clone().unwrap_or_else(|| { // Pick a "reasonable maximum" if we don't otherwise have a jobserver in // our environment, capping out at 32 so we don't take everything down @@ -938,7 +934,7 @@ pub fn run_passes(sess: &Session, } } -fn dump_incremental_data(trans: &CrateTranslation) { +pub fn dump_incremental_data(trans: &CrateTranslation) { let mut reuse = 0; for mtrans in trans.modules.iter() { match mtrans.source { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 7b836399f9cb..1fd871d31b59 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -23,7 +23,7 @@ //! but one TypeRef corresponds to many `Ty`s; for instance, tup(int, int, //! int) and rec(x=int, y=int, z=int) will have the same TypeRef. -use super::CrateTranslation; +use super::OngoingCrateTranslation; use super::ModuleLlvm; use super::ModuleSource; use super::ModuleTranslation; @@ -43,9 +43,9 @@ use rustc::dep_graph::AssertDepGraphSafe; use rustc::middle::cstore::LinkMeta; use rustc::hir::map as hir_map; use rustc::util::common::time; -use rustc::session::config::{self, NoDebugInfo, OutputFilenames}; +use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, OutputTypes}; use rustc::session::Session; -use rustc_incremental::IncrementalHashesMap; +use rustc_incremental::{self, IncrementalHashesMap}; use abi; use allocator; use mir::lvalue::LvalueRef; @@ -922,7 +922,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, analysis: ty::CrateAnalysis, incremental_hashes_map: &IncrementalHashesMap, output_filenames: &OutputFilenames) - -> CrateTranslation { + -> OngoingCrateTranslation { // Be careful with this krate: obviously it gives access to the // entire contents of the krate. So if you push any subtasks of // `TransCrate`, you need to be careful to register "reads" of the @@ -961,17 +961,18 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, !tcx.sess.opts.output_types.should_trans() { let empty_exported_symbols = ExportedSymbols::empty(); let linker_info = LinkerInfo::new(&shared_ccx, &empty_exported_symbols); - return CrateTranslation { + return OngoingCrateTranslation { crate_name: tcx.crate_name(LOCAL_CRATE), modules: vec![], metadata_module: metadata_module, allocator_module: None, link: link_meta, metadata: metadata, - exported_symbols: empty_exported_symbols, + exported_symbols: Arc::new(empty_exported_symbols), no_builtins: no_builtins, linker_info: linker_info, windows_subsystem: None, + no_integrated_as: false, }; } @@ -1210,19 +1211,52 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, subsystem.to_string() }); - CrateTranslation { + let outputs = output_filenames; + + let no_integrated_as = sess.opts.cg.no_integrated_as || + (sess.target.target.options.no_integrated_as && + (outputs.outputs.contains_key(&OutputType::Object) || + outputs.outputs.contains_key(&OutputType::Exe))); + + let crate_translation = OngoingCrateTranslation { crate_name: tcx.crate_name(LOCAL_CRATE), - modules: modules, - metadata_module: metadata_module, - allocator_module: allocator_module, link: link_meta, metadata: metadata, - exported_symbols: Arc::try_unwrap(exported_symbols) - .expect("There's still a reference to exported_symbols?"), - no_builtins: no_builtins, - linker_info: linker_info, - windows_subsystem: windows_subsystem, - } + exported_symbols, + no_builtins, + linker_info, + windows_subsystem, + no_integrated_as, + + modules, + metadata_module, + allocator_module, + }; + + time(sess.time_passes(), + "assert dep graph", + || rustc_incremental::assert_dep_graph(tcx)); + + time(sess.time_passes(), + "serialize dep graph", + || rustc_incremental::save_dep_graph(tcx, + incremental_hashes_map, + &crate_translation.metadata.hashes, + crate_translation.link.crate_hash)); + // --- + + if no_integrated_as { + let output_types = OutputTypes::new(&[(OutputType::Assembly, None)]); + time(sess.time_passes(), + "LLVM passes", + || ::back::write::run_passes(sess, &crate_translation, &output_types, outputs)) + } else { + time(sess.time_passes(), + "LLVM passes", + || ::back::write::run_passes(sess, &crate_translation, &sess.opts.output_types, outputs)) + }; + + crate_translation } #[inline(never)] // give this a place in the profiler diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 70337a91731d..c386d11fa84c 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -35,7 +35,12 @@ #![feature(conservative_impl_trait)] use rustc::dep_graph::WorkProduct; +use rustc::session::Session; +use rustc::session::config::{OutputType, OutputFilenames}; +use rustc::util::fs::rename_or_copy_remove; use syntax_pos::symbol::Symbol; +use std::fs; +use std::sync::Arc; extern crate flate2; extern crate crossbeam; @@ -167,10 +172,69 @@ pub struct CrateTranslation { pub allocator_module: Option, pub link: rustc::middle::cstore::LinkMeta, pub metadata: rustc::middle::cstore::EncodedMetadata, - pub exported_symbols: back::symbol_export::ExportedSymbols, + pub exported_symbols: Arc, pub no_builtins: bool, pub windows_subsystem: Option, pub linker_info: back::linker::LinkerInfo } +pub struct OngoingCrateTranslation { + pub crate_name: Symbol, + pub link: rustc::middle::cstore::LinkMeta, + pub metadata: rustc::middle::cstore::EncodedMetadata, + pub exported_symbols: Arc, + pub no_builtins: bool, + pub windows_subsystem: Option, + pub linker_info: back::linker::LinkerInfo, + pub no_integrated_as: bool, + + // These will be replaced by a Future. + pub modules: Vec, + pub metadata_module: ModuleTranslation, + pub allocator_module: Option, +} + +impl OngoingCrateTranslation { + pub fn join(self, + sess: &Session, + outputs: &OutputFilenames) + -> CrateTranslation { + + let trans = CrateTranslation { + crate_name: self.crate_name, + link: self.link, + metadata: self.metadata, + exported_symbols: self.exported_symbols, + no_builtins: self.no_builtins, + windows_subsystem: self.windows_subsystem, + linker_info: self.linker_info, + + modules: self.modules, + metadata_module: self.metadata_module, + allocator_module: self.allocator_module, + }; + + if self.no_integrated_as { + back::write::run_assembler(sess, outputs); + + // HACK the linker expects the object file to be named foo.0.o but + // `run_assembler` produces an object named just foo.o. Rename it if we + // are going to build an executable + if sess.opts.output_types.contains_key(&OutputType::Exe) { + let f = outputs.path(OutputType::Object); + rename_or_copy_remove(&f, + f.with_file_name(format!("{}.0.o", + f.file_stem().unwrap().to_string_lossy()))).unwrap(); + } + + // Remove assembly source, unless --save-temps was specified + if !sess.opts.cg.save_temps { + fs::remove_file(&outputs.temp_path(OutputType::Assembly, None)).unwrap(); + } + } + + trans + } +} + __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }