From 8d530db2c5e63da2fed3ec1ac3bba2fa0fb4363c Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Tue, 25 Sep 2018 17:52:03 +0200 Subject: [PATCH] Generalized base:codegen_crate --- src/librustc_codegen_llvm/back/lto.rs | 15 ++-- src/librustc_codegen_llvm/back/write.rs | 22 ++--- src/librustc_codegen_llvm/base.rs | 80 +++++++++---------- .../interfaces/backend.rs | 40 ++++++++++ src/librustc_codegen_llvm/interfaces/mod.rs | 2 +- src/librustc_codegen_llvm/lib.rs | 67 ++++++++++++++-- 6 files changed, 160 insertions(+), 66 deletions(-) diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 60b06c579cb40..5eb2e28a2a86f 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -13,8 +13,7 @@ use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; use back::write::{self, DiagnosticHandlers, pre_lto_bitcode_filename}; use errors::{FatalError, Handler}; use llvm::archive_ro::ArchiveRO; -use llvm::{True, False}; -use llvm; +use llvm::{self, True, False}; use memmap; use rustc::dep_graph::WorkProduct; use rustc::dep_graph::cgu_reuse_tracker::CguReuse; @@ -49,7 +48,7 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool { pub(crate) enum LtoModuleCodegen { Fat { - module: Option, + module: Option>, _serialized_bitcode: Vec, }, @@ -73,7 +72,7 @@ impl LtoModuleCodegen { pub(crate) unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline) - -> Result + -> Result, FatalError> { match *self { LtoModuleCodegen::Fat { ref mut module, .. } => { @@ -108,7 +107,7 @@ impl LtoModuleCodegen { /// the need optimization and another for modules that can simply be copied over /// from the incr. comp. cache. pub(crate) fn run(cgcx: &CodegenContext, - modules: Vec, + modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, timeline: &mut Timeline) -> Result<(Vec, Vec), FatalError> @@ -232,7 +231,7 @@ pub(crate) fn run(cgcx: &CodegenContext, fn fat_lto(cgcx: &CodegenContext, diag_handler: &Handler, - mut modules: Vec, + mut modules: Vec>, mut serialized_modules: Vec<(SerializedModule, CString)>, symbol_white_list: &[*const libc::c_char], timeline: &mut Timeline) @@ -388,7 +387,7 @@ impl Drop for Linker<'a> { /// they all go out of scope. fn thin_lto(cgcx: &CodegenContext, diag_handler: &Handler, - modules: Vec, + modules: Vec>, serialized_modules: Vec<(SerializedModule, CString)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, symbol_white_list: &[*const libc::c_char], @@ -740,7 +739,7 @@ impl ThinModule { } unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline) - -> Result + -> Result, FatalError> { let diag_handler = cgcx.create_diag_handler(); let tm = (cgcx.tm_factory)().map_err(|e| { diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index bb490c582858c..72820f967afa3 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -26,7 +26,7 @@ use rustc::util::nodemap::FxHashMap; use time_graph::{self, TimeGraph, Timeline}; use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic}; use llvm_util; -use {CodegenResults, ModuleCodegen, CompiledModule, ModuleKind, // ModuleLlvm, +use {CodegenResults, ModuleCodegen, CompiledModule, ModuleKind, ModuleLlvm, CachedModuleCodegen}; use CrateInfo; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -408,7 +408,7 @@ impl CodegenContext { } } - pub(crate) fn save_temp_bitcode(&self, module: &ModuleCodegen, name: &str) { + pub(crate) fn save_temp_bitcode(&self, module: &ModuleCodegen, name: &str) { if !self.save_temps { return } @@ -515,7 +515,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void // Unsafe due to LLVM calls. unsafe fn optimize(cgcx: &CodegenContext, diag_handler: &Handler, - module: &ModuleCodegen, + module: &ModuleCodegen, config: &ModuleConfig, timeline: &mut Timeline) -> Result<(), FatalError> @@ -646,7 +646,7 @@ unsafe fn optimize(cgcx: &CodegenContext, } fn generate_lto_work(cgcx: &CodegenContext, - modules: Vec, + modules: Vec>, import_only_modules: Vec<(SerializedModule, WorkProduct)>) -> Vec<(WorkItem, u64)> { @@ -675,7 +675,7 @@ fn generate_lto_work(cgcx: &CodegenContext, unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &Handler, - module: ModuleCodegen, + module: ModuleCodegen, config: &ModuleConfig, timeline: &mut Timeline) -> Result @@ -1284,7 +1284,7 @@ pub(crate) fn dump_incremental_data(_codegen_results: &CodegenResults) { enum WorkItem { /// Optimize a newly codegened, totally unoptimized module. - Optimize(ModuleCodegen), + Optimize(ModuleCodegen), /// Copy the post-LTO artifacts from the incremental cache to the output /// directory. CopyPostLtoArtifacts(CachedModuleCodegen), @@ -1312,7 +1312,7 @@ impl WorkItem { enum WorkItemResult { Compiled(CompiledModule), - NeedsLTO(ModuleCodegen), + NeedsLTO(ModuleCodegen), } fn execute_work_item(cgcx: &CodegenContext, @@ -1336,7 +1336,7 @@ fn execute_work_item(cgcx: &CodegenContext, } fn execute_optimize_work_item(cgcx: &CodegenContext, - module: ModuleCodegen, + module: ModuleCodegen, module_config: &ModuleConfig, timeline: &mut Timeline) -> Result @@ -1480,7 +1480,7 @@ fn execute_lto_work_item(cgcx: &CodegenContext, enum Message { Token(io::Result), NeedsLTO { - result: ModuleCodegen, + result: ModuleCodegen, worker_id: usize, }, Done { @@ -2445,7 +2445,7 @@ impl OngoingCodegen { pub(crate) fn submit_pre_codegened_module_to_llvm(&self, tcx: TyCtxt, - module: ModuleCodegen) { + module: ModuleCodegen) { self.wait_for_signal_to_codegen_item(); self.check_for_errors(tcx.sess); @@ -2497,7 +2497,7 @@ impl OngoingCodegen { // } pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt, - module: ModuleCodegen, + module: ModuleCodegen, cost: u64) { let llvm_work_item = WorkItem::Optimize(module); drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::CodegenDone { diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 333264cf1c3d7..5fd413b4c7bab 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -29,7 +29,7 @@ use super::ModuleKind; use super::CachedModuleCodegen; use abi; -use back::write::{self, OngoingCodegen}; +use back::write; use llvm; use metadata; use rustc::dep_graph::cgu_reuse_tracker::CguReuse; @@ -48,7 +48,6 @@ use rustc::util::profiling::ProfileCategory; use rustc::session::config::{self, DebugInfo, EntryFnType, Lto}; use rustc::session::Session; use rustc_incremental; -use allocator; use mir::place::PlaceRef; use builder::{Builder, MemFlags}; use callee; @@ -584,9 +583,10 @@ fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( } } -fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, - llvm_module: &ModuleLlvm) - -> EncodedMetadata { +pub(crate) fn write_metadata<'a, 'gcx>( + tcx: TyCtxt<'a, 'gcx, 'gcx>, + llvm_module: &ModuleLlvm +) -> EncodedMetadata { use std::io::Write; use flate2::Compression; use flate2::write::DeflateEncoder; @@ -713,10 +713,12 @@ fn determine_cgu_reuse<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - rx: mpsc::Receiver>) - -> OngoingCodegen -{ +pub fn codegen_crate<'a, 'tcx, B: BackendMethods>( + backend: B, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + rx: mpsc::Receiver> +) -> B::OngoingCodegen { + check_for_rustc_errors_attr(tcx); let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); @@ -728,9 +730,9 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, &["crate"], Some("metadata")).as_str() .to_string(); - let metadata_llvm_module = ModuleLlvm::new(tcx.sess, &metadata_cgu_name); + let metadata_llvm_module = backend.new_metadata(tcx.sess, &metadata_cgu_name); let metadata = time(tcx.sess, "write metadata", || { - write_metadata(tcx, &metadata_llvm_module) + backend.write_metadata(tcx, &metadata_llvm_module) }); tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen)); @@ -749,19 +751,19 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // 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() { - let ongoing_codegen = write::start_async_codegen( + let ongoing_codegen = backend.start_async_codegen( tcx, time_graph, metadata, rx, 1); - ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module); - ongoing_codegen.codegen_finished(tcx); + backend.submit_pre_codegened_module_to_llvm(&ongoing_codegen, tcx, metadata_module); + backend.codegen_finished(&ongoing_codegen, tcx); assert_and_save_dep_graph(tcx); - ongoing_codegen.check_for_errors(tcx.sess); + backend.check_for_errors(&ongoing_codegen, tcx.sess); return ongoing_codegen; } @@ -782,13 +784,13 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - let ongoing_codegen = write::start_async_codegen( + let ongoing_codegen = backend.start_async_codegen( tcx, time_graph.clone(), metadata, rx, codegen_units.len()); - let ongoing_codegen = AbortCodegenOnDrop(Some(ongoing_codegen)); + let ongoing_codegen = AbortCodegenOnDrop::(Some(ongoing_codegen)); // Codegen an allocator shim, if necessary. // @@ -811,11 +813,9 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, &["crate"], Some("allocator")).as_str() .to_string(); - let modules = ModuleLlvm::new(tcx.sess, &llmod_id); + let modules = backend.new_metadata(tcx.sess, &llmod_id); time(tcx.sess, "write allocator module", || { - unsafe { - allocator::codegen(tcx, &modules, kind) - } + backend.codegen_allocator(tcx, &modules, kind) }); Some(ModuleCodegen { @@ -828,10 +828,10 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; if let Some(allocator_module) = allocator_module { - ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module); + backend.submit_pre_codegened_module_to_llvm(&ongoing_codegen, tcx, allocator_module); } - ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module); + backend.submit_pre_codegened_module_to_llvm(&ongoing_codegen, tcx, metadata_module); // We sort the codegen units by size. This way we can schedule work for LLVM // a bit more efficiently. @@ -845,8 +845,8 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut all_stats = Stats::default(); for cgu in codegen_units.into_iter() { - ongoing_codegen.wait_for_signal_to_codegen_item(); - ongoing_codegen.check_for_errors(tcx.sess); + backend.wait_for_signal_to_codegen_item(&ongoing_codegen); + backend.check_for_errors(&ongoing_codegen, tcx.sess); let cgu_reuse = determine_cgu_reuse(tcx, &cgu); tcx.sess.cgu_reuse_tracker.set_actual_reuse(&cgu.name().as_str(), cgu_reuse); @@ -881,7 +881,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; } - ongoing_codegen.codegen_finished(tcx); + backend.codegen_finished(&ongoing_codegen, tcx); // Since the main thread is sometimes blocked during codegen, we keep track // -Ztime-passes output manually. @@ -915,7 +915,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - ongoing_codegen.check_for_errors(tcx.sess); + backend.check_for_errors(&ongoing_codegen, tcx.sess); assert_and_save_dep_graph(tcx); ongoing_codegen.into_inner() @@ -938,32 +938,32 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// If you see this comment in the code, then it means that this workaround /// worked! We may yet one day track down the mysterious cause of that /// segfault... -struct AbortCodegenOnDrop(Option); +struct AbortCodegenOnDrop(Option); -impl AbortCodegenOnDrop { - fn into_inner(mut self) -> OngoingCodegen { +impl AbortCodegenOnDrop { + fn into_inner(mut self) -> B::OngoingCodegen { self.0.take().unwrap() } } -impl Deref for AbortCodegenOnDrop { - type Target = OngoingCodegen; +impl Deref for AbortCodegenOnDrop { + type Target = B::OngoingCodegen; - fn deref(&self) -> &OngoingCodegen { + fn deref(&self) -> &B::OngoingCodegen { self.0.as_ref().unwrap() } } -impl DerefMut for AbortCodegenOnDrop { - fn deref_mut(&mut self) -> &mut OngoingCodegen { +impl DerefMut for AbortCodegenOnDrop { + fn deref_mut(&mut self) -> &mut B::OngoingCodegen { self.0.as_mut().unwrap() } } -impl Drop for AbortCodegenOnDrop { +impl Drop for AbortCodegenOnDrop { fn drop(&mut self) { if let Some(codegen) = self.0.take() { - codegen.codegen_aborted(); + B::codegen_aborted(codegen); } } } @@ -1092,7 +1092,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn module_codegen<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, cgu_name: InternedString) - -> (Stats, ModuleCodegen) + -> (Stats, ModuleCodegen) { let cgu = tcx.codegen_unit(cgu_name); @@ -1226,9 +1226,9 @@ pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { mod temp_stable_hash_impls { use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher, HashStable}; - use ModuleCodegen; + use {ModuleCodegen, ModuleLlvm}; - impl HashStable for ModuleCodegen { + impl HashStable for ModuleCodegen { fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) { diff --git a/src/librustc_codegen_llvm/interfaces/backend.rs b/src/librustc_codegen_llvm/interfaces/backend.rs index 7e95cb248045a..a5df7e5af6ff5 100644 --- a/src/librustc_codegen_llvm/interfaces/backend.rs +++ b/src/librustc_codegen_llvm/interfaces/backend.rs @@ -12,6 +12,14 @@ use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout}; use rustc::ty::Ty; use super::CodegenObject; +use rustc::middle::allocator::AllocatorKind; +use rustc::middle::cstore::EncodedMetadata; +use rustc::session::Session; +use rustc::ty::TyCtxt; +use std::any::Any; +use std::sync::mpsc::Receiver; +use time_graph::TimeGraph; +use ModuleCodegen; pub trait BackendTypes { type Value: CodegenObject; @@ -30,3 +38,35 @@ pub trait Backend<'tcx>: impl<'tcx, T> Backend<'tcx> for T where Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf, TyLayout = TyLayout<'tcx>> {} + +pub trait BackendMethods { + type Metadata; + type OngoingCodegen; + + fn new_metadata(&self, sess: &Session, mod_name: &str) -> Self::Metadata; + fn write_metadata<'a, 'gcx>( + &self, + tcx: TyCtxt<'a, 'gcx, 'gcx>, + metadata: &Self::Metadata, + ) -> EncodedMetadata; + fn codegen_allocator(&self, tcx: TyCtxt, mods: &Self::Metadata, kind: AllocatorKind); + + fn start_async_codegen( + &self, + tcx: TyCtxt, + time_graph: Option, + metadata: EncodedMetadata, + coordinator_receive: Receiver>, + total_cgus: usize, + ) -> Self::OngoingCodegen; + fn submit_pre_codegened_module_to_llvm( + &self, + codegen: &Self::OngoingCodegen, + tcx: TyCtxt, + module: ModuleCodegen, + ); + fn codegen_aborted(codegen: Self::OngoingCodegen); + fn codegen_finished(&self, codegen: &Self::OngoingCodegen, tcx: TyCtxt); + fn check_for_errors(&self, codegen: &Self::OngoingCodegen, sess: &Session); + fn wait_for_signal_to_codegen_item(&self, codegen: &Self::OngoingCodegen); +} diff --git a/src/librustc_codegen_llvm/interfaces/mod.rs b/src/librustc_codegen_llvm/interfaces/mod.rs index 6ff662614167e..e0ce05d0a8479 100644 --- a/src/librustc_codegen_llvm/interfaces/mod.rs +++ b/src/librustc_codegen_llvm/interfaces/mod.rs @@ -22,7 +22,7 @@ mod type_; pub use self::abi::{AbiBuilderMethods, AbiMethods}; pub use self::asm::{AsmBuilderMethods, AsmMethods}; -pub use self::backend::{Backend, BackendTypes}; +pub use self::backend::{Backend, BackendMethods, BackendTypes}; pub use self::builder::BuilderMethods; pub use self::consts::ConstMethods; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods}; diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 43942b0db85c3..d1be81f122484 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -68,6 +68,10 @@ extern crate tempfile; extern crate memmap; use back::bytecode::RLIB_BYTECODE_EXTENSION; +use interfaces::*; +use time_graph::TimeGraph; +use std::sync::mpsc::Receiver; +use back::write::{self, OngoingCodegen}; pub use llvm_util::target_features; use std::any::Any; @@ -76,7 +80,8 @@ use rustc_data_structures::sync::Lrc; use rustc::dep_graph::DepGraph; use rustc::hir::def_id::CrateNum; -use rustc::middle::cstore::MetadataLoader; +use rustc::middle::allocator::AllocatorKind; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource}; use rustc::middle::lang_items::LangItem; use rustc::session::{Session, CompileIncomplete}; @@ -133,6 +138,56 @@ mod value; pub struct LlvmCodegenBackend(()); +impl BackendMethods for LlvmCodegenBackend { + type Metadata = ModuleLlvm; + type OngoingCodegen = OngoingCodegen; + + fn new_metadata(&self, sess: &Session, mod_name: &str) -> ModuleLlvm { + ModuleLlvm::new(sess, mod_name) + } + fn write_metadata<'a, 'gcx>( + &self, + tcx: TyCtxt<'a, 'gcx, 'gcx>, + metadata: &ModuleLlvm + ) -> EncodedMetadata { + base::write_metadata(tcx, metadata) + } + fn start_async_codegen( + &self, + tcx: TyCtxt, + time_graph: Option, + metadata: EncodedMetadata, + coordinator_receive: Receiver>, + total_cgus: usize + ) -> OngoingCodegen { + write::start_async_codegen(tcx, time_graph, metadata, coordinator_receive, total_cgus) + } + fn submit_pre_codegened_module_to_llvm( + &self, + codegen: &OngoingCodegen, + tcx: TyCtxt, + module: ModuleCodegen + ) { + codegen.submit_pre_codegened_module_to_llvm(tcx, module) + } + fn codegen_aborted(codegen: OngoingCodegen) { + codegen.codegen_aborted(); + } + fn codegen_finished(&self, codegen: &OngoingCodegen, tcx: TyCtxt) { + codegen.codegen_finished(tcx) + } + fn check_for_errors(&self, codegen: &OngoingCodegen, sess: &Session) { + codegen.check_for_errors(sess) + } + fn codegen_allocator(&self, tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) { + unsafe { allocator::codegen(tcx, mods, kind) } + } + fn wait_for_signal_to_codegen_item(&self, codegen: &OngoingCodegen) { + codegen.wait_for_signal_to_codegen_item() + } +} + + impl !Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis impl !Sync for LlvmCodegenBackend {} @@ -212,7 +267,7 @@ impl CodegenBackend for LlvmCodegenBackend { tcx: TyCtxt<'a, 'tcx, 'tcx>, rx: mpsc::Receiver> ) -> Box { - box base::codegen_crate(tcx, rx) + box base::codegen_crate(LlvmCodegenBackend(()), tcx, rx) } fn join_codegen_and_link( @@ -265,7 +320,7 @@ pub fn __rustc_codegen_backend() -> Box { LlvmCodegenBackend::new() } -struct ModuleCodegen { +pub struct ModuleCodegen { /// The name of the module. When the crate may be saved between /// compilations, incremental compilation requires that name be /// unique amongst **all** crates. Therefore, it should contain @@ -273,7 +328,7 @@ struct ModuleCodegen { /// as the crate name and disambiguator. /// We currently generate these names via CodegenUnit::build_cgu_name(). name: String, - module_llvm: ModuleLlvm, + module_llvm: M, kind: ModuleKind, } @@ -282,7 +337,7 @@ struct CachedModuleCodegen { source: WorkProduct, } -impl ModuleCodegen { +impl ModuleCodegen { fn into_compiled_module(self, emit_obj: bool, emit_bc: bool, @@ -315,7 +370,7 @@ impl ModuleCodegen { } } -struct ModuleLlvm { +pub struct ModuleLlvm { llcx: &'static mut llvm::Context, llmod_raw: *const llvm::Module, tm: &'static mut llvm::TargetMachine,