From 74c92c556264c703b875645bad3f2738a37940fa Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 30 Oct 2017 18:42:21 +0100 Subject: [PATCH 01/17] Allow runtime switching between trans backends --- src/Cargo.lock | 3 +- src/librustc/session/config.rs | 2 + src/librustc_driver/driver.rs | 102 ++-------- src/librustc_driver/lib.rs | 135 ++++++------- src/librustc_driver/pretty.rs | 6 +- src/librustc_driver/target_features.rs | 31 --- src/librustc_driver/test.rs | 2 +- .../assert_module_sources.rs | 2 +- src/librustc_incremental/lib.rs | 1 + src/librustc_mir/Cargo.toml | 1 - src/librustc_mir/lib.rs | 1 - src/librustc_mir/monomorphize/item.rs | 13 ++ src/librustc_mir/monomorphize/mod.rs | 48 +++++ src/librustc_trans/back/command.rs | 6 +- src/librustc_trans/base.rs | 55 +----- src/librustc_trans/diagnostics.rs | 28 +-- src/librustc_trans/lib.rs | 116 ++++++++---- src/librustc_trans/llvm_util.rs | 19 +- src/librustc_trans/trans_item.rs | 15 +- src/librustc_trans_utils/Cargo.toml | 2 + src/librustc_trans_utils/diagnostics.rs | 38 ++++ src/librustc_trans_utils/lib.rs | 8 + .../symbol_names.rs | 6 +- .../symbol_names_test.rs | 2 +- src/librustc_trans_utils/trans_crate.rs | 178 +++++++++++------- src/librustdoc/core.rs | 12 +- src/librustdoc/lib.rs | 4 +- src/librustdoc/test.rs | 23 ++- src/test/run-make/issue-19371/foo.rs | 24 ++- src/test/run-make/llvm-phase/Makefile | 5 - src/test/run-make/llvm-phase/test.rs | 87 --------- src/test/run-pass-fulldeps/compiler-calls.rs | 3 + src/tools/compiletest/src/runtest.rs | 2 +- 33 files changed, 477 insertions(+), 503 deletions(-) delete mode 100644 src/librustc_driver/target_features.rs rename src/{librustc_trans => librustc_incremental}/assert_module_sources.rs (98%) create mode 100644 src/librustc_trans_utils/diagnostics.rs rename src/{librustc_trans/back => librustc_trans_utils}/symbol_names.rs (99%) rename src/{librustc_trans => librustc_trans_utils}/symbol_names_test.rs (98%) delete mode 100644 src/test/run-make/llvm-phase/Makefile delete mode 100644 src/test/run-make/llvm-phase/test.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 1a38a5365db..6f919fd1acd 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2010,7 +2010,6 @@ dependencies = [ "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", - "rustc_trans_utils 0.0.0", "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", @@ -2133,6 +2132,8 @@ dependencies = [ "rustc 0.0.0", "rustc_back 0.0.0", "rustc_data_structures 0.0.0", + "rustc_incremental 0.0.0", + "rustc_mir 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 69b86416afa..cd4e3cfed7a 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1045,6 +1045,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, build_debugging_options, "Z", "debugging", DB_OPTIONS, db_type_desc, dbsetters, + codegen_backend: Option = (None, parse_opt_string, [TRACKED], + "the backend to use"), verbose: bool = (false, parse_bool, [UNTRACKED], "in general, enable more debug printouts"), span_free_formats: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f7e35ba0081..468a08b1fd9 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -31,7 +31,6 @@ use rustc_incremental; use rustc_resolve::{MakeGlobMap, Resolver}; use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::{self, CStore}; -use rustc_trans as trans; use rustc_trans_utils::trans_crate::TransCrate; use rustc_typeck as typeck; use rustc_privacy; @@ -40,7 +39,6 @@ use rustc_plugin as plugin; use rustc_passes::{self, ast_validation, loops, consts, static_recursion, hir_stats}; use rustc_const_eval::{self, check_match}; use super::Compilation; -use ::DefaultTransCrate; use serialize::json; @@ -68,7 +66,8 @@ use pretty::ReplaceBodyWithLoop; use profile; -pub fn compile_input(sess: &Session, +pub fn compile_input(trans: Box, + sess: &Session, cstore: &CStore, input_path: &Option, input: &Input, @@ -76,8 +75,6 @@ pub fn compile_input(sess: &Session, output: &Option, addl_plugins: Option>, control: &CompileController) -> CompileResult { - use rustc::session::config::CrateType; - macro_rules! controller_entry_point { ($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{ let state = &mut $make_state; @@ -94,22 +91,6 @@ pub fn compile_input(sess: &Session, }} } - if cfg!(not(feature="llvm")) { - for cty in sess.opts.crate_types.iter() { - match *cty { - CrateType::CrateTypeRlib | CrateType::CrateTypeDylib | - CrateType::CrateTypeExecutable => {}, - _ => { - sess.parse_sess.span_diagnostic.warn( - &format!("LLVM unsupported, so output type {} is not supported", cty) - ); - }, - } - } - - sess.abort_if_errors(); - } - if sess.profile_queries() { profile::begin(); } @@ -117,7 +98,7 @@ pub fn compile_input(sess: &Session, // We need nested scopes here, because the intermediate results can keep // large chunks of memory alive and we want to free them as soon as // possible to keep the peak memory usage low - let (outputs, trans, dep_graph) = { + let (outputs, ongoing_trans, dep_graph) = { let krate = match phase_1_parse_input(control, sess, input) { Ok(krate) => krate, Err(mut parse_error) => { @@ -217,7 +198,8 @@ pub fn compile_input(sess: &Session, None }; - phase_3_run_analysis_passes(control, + phase_3_run_analysis_passes(&*trans, + control, sess, cstore, hir_map, @@ -254,7 +236,7 @@ pub fn compile_input(sess: &Session, tcx.print_debug_stats(); } - let trans = phase_4_translate_to_llvm::(tcx, rx); + let ongoing_trans = phase_4_translate_to_llvm(&*trans, tcx, rx); if log_enabled!(::log::Level::Info) { println!("Post-trans"); @@ -268,7 +250,7 @@ pub fn compile_input(sess: &Session, } } - Ok((outputs.clone(), trans, tcx.dep_graph.clone())) + Ok((outputs.clone(), ongoing_trans, tcx.dep_graph.clone())) })?? }; @@ -276,25 +258,7 @@ pub fn compile_input(sess: &Session, sess.code_stats.borrow().print_type_sizes(); } - let (phase5_result, trans) = - phase_5_run_llvm_passes::(sess, &dep_graph, trans); - - controller_entry_point!(after_llvm, - sess, - CompileState::state_after_llvm(input, sess, outdir, output, &trans), - phase5_result); - phase5_result?; - - // Run the linker on any artifacts that resulted from the LLVM run. - // This should produce either a finished executable or library. - time(sess.time_passes(), "linking", || { - DefaultTransCrate::link_binary(sess, &trans, &outputs) - }); - - // Now that we won't touch anything in the incremental compilation directory - // any more, we can finalize it (which involves renaming it) - #[cfg(feature="llvm")] - rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash); + trans.join_trans_and_link(ongoing_trans, sess, &dep_graph, &outputs)?; if sess.opts.debugging_opts.perf_stats { sess.print_perf_stats(); @@ -340,7 +304,6 @@ pub struct CompileController<'a> { pub after_expand: PhaseController<'a>, pub after_hir_lowering: PhaseController<'a>, pub after_analysis: PhaseController<'a>, - pub after_llvm: PhaseController<'a>, pub compilation_done: PhaseController<'a>, // FIXME we probably want to group the below options together and offer a @@ -366,7 +329,6 @@ impl<'a> CompileController<'a> { after_expand: PhaseController::basic(), after_hir_lowering: PhaseController::basic(), after_analysis: PhaseController::basic(), - after_llvm: PhaseController::basic(), compilation_done: PhaseController::basic(), make_glob_map: MakeGlobMap::No, keep_ast: false, @@ -415,7 +377,6 @@ pub struct CompileState<'a, 'tcx: 'a> { pub resolutions: Option<&'a Resolutions>, pub analysis: Option<&'a ty::CrateAnalysis>, pub tcx: Option>, - pub trans: Option<&'a trans::CrateTranslation>, } impl<'a, 'tcx> CompileState<'a, 'tcx> { @@ -440,7 +401,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { resolutions: None, analysis: None, tcx: None, - trans: None, } } @@ -528,19 +488,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { } } - fn state_after_llvm(input: &'a Input, - session: &'tcx Session, - out_dir: &'a Option, - out_file: &'a Option, - trans: &'a trans::CrateTranslation) - -> Self { - CompileState { - trans: Some(trans), - out_file: out_file.as_ref().map(|s| &**s), - ..CompileState::empty(input, session, out_dir) - } - } - fn state_when_compilation_done(input: &'a Input, session: &'tcx Session, out_dir: &'a Option, @@ -933,7 +880,6 @@ pub fn default_provide(providers: &mut ty::maps::Providers) { reachable::provide(providers); resolve_lifetime::provide(providers); rustc_privacy::provide(providers); - DefaultTransCrate::provide(providers); typeck::provide(providers); ty::provide(providers); traits::provide(providers); @@ -947,13 +893,13 @@ pub fn default_provide(providers: &mut ty::maps::Providers) { pub fn default_provide_extern(providers: &mut ty::maps::Providers) { cstore::provide_extern(providers); - DefaultTransCrate::provide_extern(providers); } /// Run the resolution, typechecking, region checking and other /// miscellaneous analysis passes on the crate. Return various /// structures carrying the results of the analysis. -pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController, +pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate, + control: &CompileController, sess: &'tcx Session, cstore: &'tcx CrateStore, hir_map: hir_map::Map<'tcx>, @@ -1006,10 +952,12 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController, let mut local_providers = ty::maps::Providers::default(); default_provide(&mut local_providers); + trans.provide(&mut local_providers); (control.provide)(&mut local_providers); let mut extern_providers = local_providers; default_provide_extern(&mut extern_providers); + trans.provide_extern(&mut extern_providers); (control.provide_extern)(&mut extern_providers); let (tx, rx) = mpsc::channel(); @@ -1101,9 +1049,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController, /// Run the translation phase to LLVM, after which the AST and analysis can /// be discarded. -pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +pub fn phase_4_translate_to_llvm<'a, 'tcx>(trans: &TransCrate, + tcx: TyCtxt<'a, 'tcx, 'tcx>, rx: mpsc::Receiver>) - -> ::OngoingCrateTranslation { + -> Box { let time_passes = tcx.sess.time_passes(); time(time_passes, @@ -1112,7 +1061,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 't let translation = time(time_passes, "translation", move || { - Trans::trans_crate(tcx, rx) + trans.trans_crate(tcx, rx) }); if tcx.sess.profile_queries() { profile::dump("profile_queries".to_string()) @@ -1121,25 +1070,6 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 't 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, - dep_graph: &DepGraph, - trans: ::OngoingCrateTranslation) - -> (CompileResult, ::TranslatedCrate) { - let trans = Trans::join_trans(trans, sess, dep_graph); - - if sess.opts.debugging_opts.incremental_info { - Trans::dump_incremental_data(&trans); - } - - time(sess.time_passes(), - "serialize work products", - move || rustc_incremental::save_work_products(sess, dep_graph)); - - (sess.compile_status(), trans) -} - fn escape_dep_filename(filename: &FileName) -> String { // Apparently clang and gcc *only* escape spaces: // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4 diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 237656eb43c..a1bfd2a4774 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -48,7 +48,7 @@ extern crate rustc_mir; extern crate rustc_resolve; extern crate rustc_save_analysis; #[cfg(feature="llvm")] -extern crate rustc_trans; +pub extern crate rustc_trans; extern crate rustc_trans_utils; extern crate rustc_typeck; extern crate serialize; @@ -66,7 +66,7 @@ use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; use rustc::session::{self, config, Session, build_session, CompileResult}; use rustc::session::CompileIncomplete; -use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType}; +use rustc::session::config::{Input, PrintRequest, ErrorOutputType}; use rustc::session::config::nightly_options; use rustc::session::{early_error, early_warn}; use rustc::lint::Lint; @@ -106,9 +106,32 @@ mod test; pub mod profile; pub mod driver; pub mod pretty; -pub mod target_features; mod derive_registrar; +pub mod target_features { + use syntax::ast; + use syntax::symbol::Symbol; + use rustc::session::Session; + use rustc_trans_utils::trans_crate::TransCrate; + + /// Add `target_feature = "..."` cfgs for a variety of platform + /// specific features (SSE, NEON etc.). + /// + /// This is performed by checking whether a whitelisted set of + /// features is available on the target machine, by querying LLVM. + pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session, trans: &TransCrate) { + let tf = Symbol::intern("target_feature"); + + for feat in trans.target_features(sess) { + cfg.insert((tf, Some(feat))); + } + + if sess.crt_static_feature() { + cfg.insert((tf, Some(Symbol::intern("crt-static")))); + } + } +} + const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\ md#bug-reports"; @@ -159,25 +182,22 @@ pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as DefaultTransCr pub use rustc_trans::LlvmTransCrate as DefaultTransCrate; #[cfg(not(feature="llvm"))] -mod rustc_trans { - use syntax_pos::symbol::Symbol; - use rustc::session::Session; - use rustc::session::config::PrintRequest; +pub mod rustc_trans { pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as LlvmTransCrate; - pub use rustc_trans_utils::trans_crate::TranslatedCrate as CrateTranslation; - pub fn init(_sess: &Session) {} pub fn print_version() {} pub fn print_passes() {} - pub fn print(_req: PrintRequest, _sess: &Session) {} - pub fn target_features(_sess: &Session) -> Vec { vec![] } +} - pub mod back { - pub mod write { - pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = []; - pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = []; - pub const TLS_MODEL_ARGS: [(&'static str, ()); 0] = []; +pub fn get_trans(sess: &Session) -> Box { + let trans_name = sess.opts.debugging_opts.codegen_backend.clone(); + match trans_name.as_ref().map(|s|&**s) { + None => DefaultTransCrate::new(&sess), + Some("llvm") => rustc_trans::LlvmTransCrate::new(&sess), + Some("metadata_only") => { + rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess) } + Some(trans_name) => sess.fatal(&format!("Invalid trans {}", trans_name)), } } @@ -222,30 +242,36 @@ pub fn run_compiler<'a>(args: &[String], }, }; - let cstore = CStore::new(DefaultTransCrate::metadata_loader()); - let loader = file_loader.unwrap_or(box RealFileLoader); let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping())); let mut sess = session::build_session_with_codemap( sopts, input_file_path.clone(), descriptions, codemap, emitter_dest, ); - rustc_trans::init(&sess); + + let trans = get_trans(&sess); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let mut cfg = config::build_configuration(&sess, cfg); - target_features::add_configuration(&mut cfg, &sess); + target_features::add_configuration(&mut cfg, &sess, &*trans); sess.parse_sess.config = cfg; - do_or_return!(callbacks.late_callback(&matches, + let plugins = sess.opts.debugging_opts.extra_plugins.clone(); + + let cstore = CStore::new(trans.metadata_loader()); + + do_or_return!(callbacks.late_callback(&*trans, + &matches, &sess, &cstore, &input, &odir, &ofile), Some(sess)); - let plugins = sess.opts.debugging_opts.extra_plugins.clone(); let control = callbacks.build_controller(&sess, &matches); - (driver::compile_input(&sess, + + (driver::compile_input(trans, + &sess, &cstore, &input_file_path, &input, @@ -338,6 +364,7 @@ pub trait CompilerCalls<'a> { // be called just before actual compilation starts (and before build_controller // is called), after all arguments etc. have been completely handled. fn late_callback(&mut self, + _: &TransCrate, _: &getopts::Matches, _: &Session, _: &CrateStore, @@ -517,13 +544,18 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { let mut sess = build_session(sopts.clone(), None, descriptions.clone()); - rustc_trans::init(&sess); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let mut cfg = config::build_configuration(&sess, cfg.clone()); - target_features::add_configuration(&mut cfg, &sess); + let trans = get_trans(&sess); + target_features::add_configuration(&mut cfg, &sess, &*trans); sess.parse_sess.config = cfg; - let should_stop = - RustcDefaultCalls::print_crate_info(&sess, None, odir, ofile); + let should_stop = RustcDefaultCalls::print_crate_info( + &*trans, + &sess, + None, + odir, + ofile + ); if should_stop == Compilation::Stop { return None; @@ -536,6 +568,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { } fn late_callback(&mut self, + trans: &TransCrate, matches: &getopts::Matches, sess: &Session, cstore: &CrateStore, @@ -543,7 +576,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { odir: &Option, ofile: &Option) -> Compilation { - RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile) + RustcDefaultCalls::print_crate_info(trans, sess, Some(input), odir, ofile) .and_then(|| RustcDefaultCalls::list_metadata(sess, cstore, matches, input)) } @@ -607,11 +640,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_hir_lowering.stop = Compilation::Stop; } - if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe || - i == OutputType::Metadata) { - control.after_llvm.stop = Compilation::Stop; - } - if save_analysis(sess) { enable_save_analysis(&mut control); } @@ -681,11 +709,13 @@ impl RustcDefaultCalls { } - fn print_crate_info(sess: &Session, + fn print_crate_info(trans: &TransCrate, + sess: &Session, input: Option<&Input>, odir: &Option, ofile: &Option) -> Compilation { + use rustc::session::config::PrintRequest::*; // PrintRequest::NativeStaticLibs is special - printed during linking // (empty iterator returns true) if sess.opts.prints.iter().all(|&p| p==PrintRequest::NativeStaticLibs) { @@ -707,15 +737,14 @@ impl RustcDefaultCalls { }; for req in &sess.opts.prints { match *req { - PrintRequest::TargetList => { + TargetList => { let mut targets = rustc_back::target::get_targets().collect::>(); targets.sort(); println!("{}", targets.join("\n")); }, - PrintRequest::Sysroot => println!("{}", sess.sysroot().display()), - PrintRequest::TargetSpec => println!("{}", sess.target.target.to_json().pretty()), - PrintRequest::FileNames | - PrintRequest::CrateName => { + Sysroot => println!("{}", sess.sysroot().display()), + TargetSpec => println!("{}", sess.target.target.to_json().pretty()), + FileNames | CrateName => { let input = match input { Some(input) => input, None => early_error(ErrorOutputType::default(), "no input file provided"), @@ -741,7 +770,7 @@ impl RustcDefaultCalls { .to_string_lossy()); } } - PrintRequest::Cfg => { + Cfg => { let allow_unstable_cfg = UnstableFeatures::from_environment() .is_nightly_build(); @@ -781,29 +810,8 @@ impl RustcDefaultCalls { println!("{}", cfg); } } - PrintRequest::RelocationModels => { - println!("Available relocation models:"); - for &(name, _) in rustc_trans::back::write::RELOC_MODEL_ARGS.iter() { - println!(" {}", name); - } - println!(""); - } - PrintRequest::CodeModels => { - println!("Available code models:"); - for &(name, _) in rustc_trans::back::write::CODE_GEN_MODEL_ARGS.iter(){ - println!(" {}", name); - } - println!(""); - } - PrintRequest::TlsModels => { - println!("Available TLS models:"); - for &(name, _) in rustc_trans::back::write::TLS_MODEL_ARGS.iter(){ - println!(" {}", name); - } - println!(""); - } - PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => { - rustc_trans::print(*req, sess); + RelocationModels | CodeModels | TlsModels | TargetCPUs | TargetFeatures => { + trans.print(*req, sess); } // Any output here interferes with Cargo's parsing of other printed output PrintRequest::NativeStaticLibs => {} @@ -1281,6 +1289,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry { all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS); #[cfg(feature="llvm")] all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_trans_utils::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 6ce6929af5c..af3d1e4d4d0 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -228,7 +228,8 @@ impl PpSourceMode { } PpmTyped => { let control = &driver::CompileController::basic(); - abort_on_err(driver::phase_3_run_analysis_passes(control, + abort_on_err(driver::phase_3_run_analysis_passes(&*::DefaultTransCrate::new(&sess), + control, sess, cstore, hir_map.clone(), @@ -1080,7 +1081,8 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, let mut out = Vec::new(); let control = &driver::CompileController::basic(); - abort_on_err(driver::phase_3_run_analysis_passes(control, + abort_on_err(driver::phase_3_run_analysis_passes(&*::DefaultTransCrate::new(&sess), + control, sess, cstore, hir_map.clone(), diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs deleted file mode 100644 index 96264472b5f..00000000000 --- a/src/librustc_driver/target_features.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use syntax::ast; -use rustc::session::Session; -use syntax::symbol::Symbol; -use rustc_trans; - -/// Add `target_feature = "..."` cfgs for a variety of platform -/// specific features (SSE, NEON etc.). -/// -/// This is performed by checking whether a whitelisted set of -/// features is available on the target machine, by querying LLVM. -pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) { - let tf = Symbol::intern("target_feature"); - - for feat in rustc_trans::target_features(sess) { - cfg.insert((tf, Some(feat))); - } - - if sess.crt_static_feature() { - cfg.insert((tf, Some(Symbol::intern("crt-static")))); - } -} diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 371f0e79a3a..f6f3b9193c6 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -104,7 +104,7 @@ fn test_env(source_string: &str, options.unstable_features = UnstableFeatures::Allow; let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter); - let cstore = Rc::new(CStore::new(::DefaultTransCrate::metadata_loader())); + let cstore = Rc::new(CStore::new(::DefaultTransCrate::new().metadata_loader())); let sess = session::build_session_(options, None, diagnostic_handler, diff --git a/src/librustc_trans/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs similarity index 98% rename from src/librustc_trans/assert_module_sources.rs rename to src/librustc_incremental/assert_module_sources.rs index 745197d64f2..46ba94f2061 100644 --- a/src/librustc_trans/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -40,7 +40,7 @@ const CFG: &'static str = "cfg"; #[derive(Debug, PartialEq, Clone, Copy)] enum Disposition { Reused, Translated } -pub(crate) fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { +pub fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.incremental.is_none() { return; diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 0b827a0ee98..b53ee1daada 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -32,6 +32,7 @@ extern crate syntax; extern crate syntax_pos; mod assert_dep_graph; +pub mod assert_module_sources; mod persist; pub use assert_dep_graph::assert_dep_graph; diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 195335dd64c..ea05a513f7e 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -24,4 +24,3 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } byteorder = { version = "1.1", features = ["i128"] } rustc_apfloat = { path = "../librustc_apfloat" } -rustc_trans_utils = { path = "../librustc_trans_utils" } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 5379bf3f5a7..1699ad0f19c 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -57,7 +57,6 @@ extern crate core; // for NonZero extern crate log_settings; extern crate rustc_apfloat; extern crate byteorder; -extern crate rustc_trans_utils; mod diagnostics; diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 024334f1c84..072c3398134 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -26,6 +26,7 @@ use std::fmt::{self, Write}; use std::iter; use rustc::mir::mono::Linkage; use syntax_pos::symbol::Symbol; +use syntax::codemap::Span; pub use rustc::mir::mono::MonoItem; pub fn linkage_by_name(name: &str) -> Option { @@ -244,6 +245,18 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { result } } + + fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { + match *self.as_mono_item() { + MonoItem::Fn(Instance { def, .. }) => { + tcx.hir.as_local_node_id(def.def_id()) + } + MonoItem::Static(node_id) | + MonoItem::GlobalAsm(node_id) => { + Some(node_id) + } + }.map(|node_id| tcx.hir.span(node_id)) + } } impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index fcf0d71dccb..95ebb6c970a 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -22,6 +22,54 @@ pub mod collector; pub mod item; pub mod partitioning; +#[inline(never)] // give this a place in the profiler +pub fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I) + where I: Iterator> +{ + let mut symbols: Vec<_> = trans_items.map(|trans_item| { + (trans_item, trans_item.symbol_name(tcx)) + }).collect(); + + (&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{ + sym1.cmp(sym2) + }); + + for pair in (&symbols[..]).windows(2) { + let sym1 = &pair[0].1; + let sym2 = &pair[1].1; + + if *sym1 == *sym2 { + let trans_item1 = pair[0].0; + let trans_item2 = pair[1].0; + + let span1 = trans_item1.local_span(tcx); + let span2 = trans_item2.local_span(tcx); + + // Deterministically select one of the spans for error reporting + let span = match (span1, span2) { + (Some(span1), Some(span2)) => { + Some(if span1.lo().0 > span2.lo().0 { + span1 + } else { + span2 + }) + } + (Some(span), None) | + (None, Some(span)) => Some(span), + _ => None + }; + + let error_message = format!("symbol `{}` is already defined", sym1); + + if let Some(span) = span { + tcx.sess.span_fatal(span, &error_message) + } else { + tcx.sess.fatal(&error_message) + } + } + } +} + fn fn_once_adapter_instance<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, closure_did: DefId, diff --git a/src/librustc_trans/back/command.rs b/src/librustc_trans/back/command.rs index ea68e3b28b6..f93f317a0a0 100644 --- a/src/librustc_trans/back/command.rs +++ b/src/librustc_trans/back/command.rs @@ -14,7 +14,7 @@ use std::ffi::{OsStr, OsString}; use std::fmt; use std::io; -use std::process::{self, Output, Child}; +use std::process::{self, Output}; pub struct Command { program: OsString, @@ -81,10 +81,6 @@ impl Command { self.command().output() } - pub fn spawn(&mut self) -> io::Result { - self.command().spawn() - } - pub fn command(&self) -> process::Command { let mut ret = process::Command::new(&self.program); ret.args(&self.args); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 633ed9b32cd..734ad8f3929 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -29,7 +29,6 @@ use super::ModuleTranslation; use super::ModuleKind; use abi; -use assert_module_sources; use back::link; use back::symbol_export; use back::write::{self, OngoingCrateTranslation, create_target_machine}; @@ -66,7 +65,7 @@ use meth; use mir; use monomorphize::Instance; use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt}; -use symbol_names_test; +use rustc_trans_utils::symbol_names_test; use time_graph; use trans_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames}; use type_::Type; @@ -904,7 +903,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, total_trans_time); if tcx.sess.opts.incremental.is_some() { - assert_module_sources::assert_module_sources(tcx); + ::rustc_incremental::assert_module_sources::assert_module_sources(tcx); } symbol_names_test::report_symbol_names(tcx); @@ -947,54 +946,6 @@ fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { || rustc_incremental::save_dep_graph(tcx)); } -#[inline(never)] // give this a place in the profiler -fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I) - where I: Iterator> -{ - let mut symbols: Vec<_> = trans_items.map(|trans_item| { - (trans_item, trans_item.symbol_name(tcx)) - }).collect(); - - (&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{ - sym1.cmp(sym2) - }); - - for pair in (&symbols[..]).windows(2) { - let sym1 = &pair[0].1; - let sym2 = &pair[1].1; - - if *sym1 == *sym2 { - let trans_item1 = pair[0].0; - let trans_item2 = pair[1].0; - - let span1 = trans_item1.local_span(tcx); - let span2 = trans_item2.local_span(tcx); - - // Deterministically select one of the spans for error reporting - let span = match (span1, span2) { - (Some(span1), Some(span2)) => { - Some(if span1.lo().0 > span2.lo().0 { - span1 - } else { - span2 - }) - } - (Some(span), None) | - (None, Some(span)) => Some(span), - _ => None - }; - - let error_message = format!("symbol `{}` is already defined", sym1); - - if let Some(span) = span { - tcx.sess.span_fatal(span, &error_message) - } else { - tcx.sess.fatal(&error_message) - } - } - } -} - fn collect_and_partition_translation_items<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum, @@ -1034,7 +985,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( collector::collect_crate_mono_items(tcx, collection_mode) }); - assert_symbols_are_distinct(tcx, items.iter()); + ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter()); let strategy = if tcx.sess.opts.incremental.is_some() { PartitioningStrategy::PerModule diff --git a/src/librustc_trans/diagnostics.rs b/src/librustc_trans/diagnostics.rs index 8f5d836f56f..57cc33d09bb 100644 --- a/src/librustc_trans/diagnostics.rs +++ b/src/librustc_trans/diagnostics.rs @@ -47,27 +47,9 @@ unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok! ``` "##, -E0558: r##" -The `export_name` attribute was malformed. - -Erroneous code example: - -```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) -#[export_name] // error: export_name attribute has invalid format -pub fn something() {} - -fn main() {} -``` - -The `export_name` attribute expects a string in order to determine the name of -the exported symbol. Example: - -``` -#[export_name = "some_function"] // ok! -pub fn something() {} - -fn main() {} -``` -"##, - +} + + +register_diagnostics! { + E0558 } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 974c268749b..a72fad7a911 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -33,6 +33,7 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] #![feature(conservative_impl_trait)] +#![feature(optin_builtin_traits)] use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; @@ -66,11 +67,9 @@ extern crate serialize; extern crate cc; // Used to locate MSVC extern crate tempdir; -pub use base::trans_crate; use back::bytecode::RLIB_BYTECODE_EXTENSION; -pub use metadata::LlvmMetadataLoader; -pub use llvm_util::{init, target_features, print_version, print_passes, print}; +pub use llvm_util::{target_features, print_version, print_passes}; use std::any::Any; use std::path::PathBuf; @@ -81,16 +80,16 @@ use rustc::dep_graph::DepGraph; use rustc::hir::def_id::CrateNum; use rustc::middle::cstore::MetadataLoader; use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource}; -use rustc::session::Session; -use rustc::session::config::{OutputFilenames, OutputType}; +use rustc::session::{Session, CompileIncomplete}; +use rustc::session::config::{OutputFilenames, OutputType, PrintRequest}; use rustc::ty::{self, TyCtxt}; use rustc::util::nodemap::{FxHashSet, FxHashMap}; - use rustc_mir::monomorphize; +use rustc_trans_utils::trans_crate::TransCrate; mod diagnostics; -pub mod back { +pub(crate) mod back { mod archive; pub mod bytecode; mod command; @@ -98,7 +97,7 @@ pub mod back { pub mod link; mod lto; pub(crate) mod symbol_export; - pub(crate) mod symbol_names; + pub(crate) use rustc_trans_utils::symbol_names; pub mod write; mod rpath; } @@ -106,7 +105,6 @@ pub mod back { mod abi; mod allocator; mod asm; -mod assert_module_sources; mod attributes; mod base; mod builder; @@ -139,7 +137,6 @@ mod llvm_util; mod metadata; mod meth; mod mir; -mod symbol_names_test; mod time_graph; mod trans_item; mod type_; @@ -148,53 +145,108 @@ mod value; pub struct LlvmTransCrate(()); +impl !Send for LlvmTransCrate {} // Llvm is on a per-thread basis +impl !Sync for LlvmTransCrate {} + impl LlvmTransCrate { - pub fn new() -> Self { - LlvmTransCrate(()) + pub fn new(sess: &Session) -> Box { + llvm_util::init(sess); // Make sure llvm is inited + box LlvmTransCrate(()) } } -impl rustc_trans_utils::trans_crate::TransCrate for LlvmTransCrate { - type MetadataLoader = metadata::LlvmMetadataLoader; - type OngoingCrateTranslation = back::write::OngoingCrateTranslation; - type TranslatedCrate = CrateTranslation; +impl TransCrate for LlvmTransCrate { + fn print(&self, req: PrintRequest, sess: &Session) { + match req { + PrintRequest::RelocationModels => { + println!("Available relocation models:"); + for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() { + println!(" {}", name); + } + println!(""); + } + PrintRequest::CodeModels => { + println!("Available code models:"); + for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){ + println!(" {}", name); + } + println!(""); + } + PrintRequest::TlsModels => { + println!("Available TLS models:"); + for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){ + println!(" {}", name); + } + println!(""); + } + req => llvm_util::print(req, sess), + } + } - fn metadata_loader() -> Box { + fn target_features(&self, sess: &Session) -> Vec { + target_features(sess) + } + + fn metadata_loader(&self) -> Box { box metadata::LlvmMetadataLoader } - fn provide(providers: &mut ty::maps::Providers) { + fn provide(&self, providers: &mut ty::maps::Providers) { back::symbol_names::provide(providers); back::symbol_export::provide(providers); base::provide(providers); attributes::provide(providers); } - fn provide_extern(providers: &mut ty::maps::Providers) { + fn provide_extern(&self, providers: &mut ty::maps::Providers) { back::symbol_export::provide_extern(providers); } fn trans_crate<'a, 'tcx>( + &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, rx: mpsc::Receiver> - ) -> Self::OngoingCrateTranslation { - base::trans_crate(tcx, rx) + ) -> Box { + box base::trans_crate(tcx, rx) } - fn join_trans( - trans: Self::OngoingCrateTranslation, + fn join_trans_and_link( + &self, + trans: Box, sess: &Session, - dep_graph: &DepGraph - ) -> Self::TranslatedCrate { - trans.join(sess, dep_graph) - } + dep_graph: &DepGraph, + outputs: &OutputFilenames, + ) -> Result<(), CompileIncomplete>{ + use rustc::util::common::time; + let trans = trans.downcast::<::back::write::OngoingCrateTranslation>() + .expect("Expected LlvmTransCrate's OngoingCrateTranslation, found Box") + .join(sess, dep_graph); + if sess.opts.debugging_opts.incremental_info { + back::write::dump_incremental_data(&trans); + } - fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) { - back::link::link_binary(sess, trans, outputs, &trans.crate_name.as_str()); - } + time(sess.time_passes(), + "serialize work products", + move || rustc_incremental::save_work_products(sess, &dep_graph)); - fn dump_incremental_data(trans: &Self::TranslatedCrate) { - back::write::dump_incremental_data(trans); + sess.compile_status()?; + + if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe || + i == OutputType::Metadata) { + return Ok(()); + } + + // Run the linker on any artifacts that resulted from the LLVM run. + // This should produce either a finished executable or library. + time(sess.time_passes(), "linking", || { + back::link::link_binary(sess, &trans, outputs, &trans.crate_name.as_str()); + }); + + // Now that we won't touch anything in the incremental compilation directory + // any more, we can finalize it (which involves renaming it) + rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash); + + Ok(()) } } diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs index 214fdbded4e..15988008de2 100644 --- a/src/librustc_trans/llvm_util.rs +++ b/src/librustc_trans/llvm_util.rs @@ -19,11 +19,12 @@ use std::ffi::{CStr, CString}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Once; -pub fn init(sess: &Session) { +static POISONED: AtomicBool = AtomicBool::new(false); +static INIT: Once = Once::new(); + +pub(crate) fn init(sess: &Session) { unsafe { // Before we touch LLVM, make sure that multithreading is enabled. - static POISONED: AtomicBool = AtomicBool::new(false); - static INIT: Once = Once::new(); INIT.call_once(|| { if llvm::LLVMStartMultithreaded() != 1 { // use an extra bool to make sure that all future usage of LLVM @@ -40,6 +41,13 @@ pub fn init(sess: &Session) { } } +fn require_inited() { + INIT.call_once(|| bug!("llvm is not initialized")); + if POISONED.load(Ordering::SeqCst) { + bug!("couldn't enable multi-threaded LLVM"); + } +} + unsafe fn configure_llvm(sess: &Session) { let mut llvm_c_strs = Vec::new(); let mut llvm_args = Vec::new(); @@ -125,6 +133,7 @@ pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> { } pub fn print_version() { + // Can be called without initializing LLVM unsafe { println!("LLVM version: {}.{}", llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor()); @@ -132,10 +141,12 @@ pub fn print_version() { } pub fn print_passes() { + // Can be called without initializing LLVM unsafe { llvm::LLVMRustPrintPasses(); } } -pub fn print(req: PrintRequest, sess: &Session) { +pub(crate) fn print(req: PrintRequest, sess: &Session) { + require_inited(); let tm = create_target_machine(sess); unsafe { match req { diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index cc270ab5f2d..5eb6679fe25 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -25,11 +25,10 @@ use monomorphize::Instance; use type_of::LayoutLlvmExt; use rustc::hir; use rustc::mir::mono::{Linkage, Visibility}; -use rustc::ty::{TyCtxt, TypeFoldable}; +use rustc::ty::TypeFoldable; use rustc::ty::layout::LayoutOf; use syntax::ast; use syntax::attr; -use syntax_pos::Span; use std::fmt; pub use rustc::mir::mono::MonoItem; @@ -107,18 +106,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { cx.codegen_unit.name()); } - fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { - match *self.as_mono_item() { - MonoItem::Fn(Instance { def, .. }) => { - tcx.hir.as_local_node_id(def.def_id()) - } - MonoItem::Static(node_id) | - MonoItem::GlobalAsm(node_id) => { - Some(node_id) - } - }.map(|node_id| tcx.hir.span(node_id)) - } - fn to_raw_string(&self) -> String { match *self.as_mono_item() { MonoItem::Fn(instance) => { diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml index 7b9537ee23e..7a01b6d261a 100644 --- a/src/librustc_trans_utils/Cargo.toml +++ b/src/librustc_trans_utils/Cargo.toml @@ -19,3 +19,5 @@ syntax_pos = { path = "../libsyntax_pos" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } rustc_data_structures = { path = "../librustc_data_structures" } +rustc_mir = { path = "../librustc_mir" } +rustc_incremental = { path = "../librustc_incremental" } diff --git a/src/librustc_trans_utils/diagnostics.rs b/src/librustc_trans_utils/diagnostics.rs new file mode 100644 index 00000000000..13fa15faf41 --- /dev/null +++ b/src/librustc_trans_utils/diagnostics.rs @@ -0,0 +1,38 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_snake_case)] + +register_long_diagnostics! { + +E0558: r##" +The `export_name` attribute was malformed. + +Erroneous code example: + +```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) +#[export_name] // error: export_name attribute has invalid format +pub fn something() {} + +fn main() {} +``` + +The `export_name` attribute expects a string in order to determine the name of +the exported symbol. Example: + +``` +#[export_name = "some_function"] // ok! +pub fn something() {} + +fn main() {} +``` +"##, + +} diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index 77afc2899c3..4920732c41f 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -35,6 +35,9 @@ extern crate log; #[macro_use] extern crate rustc; extern crate rustc_back; +extern crate rustc_mir; +extern crate rustc_incremental; +#[macro_use] extern crate syntax; extern crate syntax_pos; extern crate rustc_data_structures; @@ -45,8 +48,11 @@ use rustc::hir::def_id::LOCAL_CRATE; use rustc::hir::map as hir_map; use rustc::util::nodemap::NodeSet; +pub mod diagnostics; pub mod link; pub mod trans_crate; +pub mod symbol_names; +pub mod symbol_names_test; /// check for the #[rustc_error] annotation, which forces an /// error in trans. This is used to write compile-fail tests @@ -110,3 +116,5 @@ pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet { } }).collect() } + +__build_diagnostic_array! { librustc_trans_utils, DIAGNOSTICS } diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans_utils/symbol_names.rs similarity index 99% rename from src/librustc_trans/back/symbol_names.rs rename to src/librustc_trans_utils/symbol_names.rs index 3ceff659ea9..fb299bf7eea 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans_utils/symbol_names.rs @@ -97,11 +97,9 @@ //! virtually impossible. Thus, symbol hash generation exclusively relies on //! DefPaths which are much more robust in the face of changes to the code base. -use monomorphize::Instance; -use trans_item::{BaseMonoItemExt, InstantiationMode}; - use rustc::middle::weak_lang_items; -use rustc::mir::mono::MonoItem; +use rustc_mir::monomorphize::Instance; +use rustc_mir::monomorphize::item::{MonoItem, MonoItemExt, InstantiationMode}; use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; diff --git a/src/librustc_trans/symbol_names_test.rs b/src/librustc_trans_utils/symbol_names_test.rs similarity index 98% rename from src/librustc_trans/symbol_names_test.rs rename to src/librustc_trans_utils/symbol_names_test.rs index 15c142cf947..5d7d4f3055b 100644 --- a/src/librustc_trans/symbol_names_test.rs +++ b/src/librustc_trans_utils/symbol_names_test.rs @@ -19,7 +19,7 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::ty::TyCtxt; use syntax::ast; -use monomorphize::Instance; +use rustc_mir::monomorphize::Instance; const SYMBOL_NAME: &'static str = "rustc_symbol_name"; const ITEM_PATH: &'static str = "rustc_item_path"; diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 47143893e59..9d42091e132 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -35,83 +35,81 @@ use flate2::write::DeflateEncoder; use syntax::symbol::Symbol; use rustc::hir::def_id::LOCAL_CRATE; -use rustc::session::Session; -use rustc::session::config::{CrateType, OutputFilenames}; +use rustc::session::{Session, CompileIncomplete}; +use rustc::session::config::{CrateType, OutputFilenames, PrintRequest}; use rustc::ty::TyCtxt; use rustc::ty::maps::Providers; use rustc::middle::cstore::EncodedMetadata; -use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait; +use rustc::middle::cstore::MetadataLoader as MetadataLoader; use rustc::dep_graph::DepGraph; use rustc_back::target::Target; +use rustc_mir::monomorphize::collector; use link::{build_link_meta, out_filename}; pub trait TransCrate { - type MetadataLoader: MetadataLoaderTrait; - type OngoingCrateTranslation; - type TranslatedCrate; + fn print(&self, _req: PrintRequest, _sess: &Session) {} + fn target_features(&self, _sess: &Session) -> Vec { vec![] } - fn metadata_loader() -> Box; - fn provide(_providers: &mut Providers); - fn provide_extern(_providers: &mut Providers); + fn metadata_loader(&self) -> Box; + fn provide(&self, _providers: &mut Providers); + fn provide_extern(&self, _providers: &mut Providers); fn trans_crate<'a, 'tcx>( + &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, rx: mpsc::Receiver> - ) -> Self::OngoingCrateTranslation; - fn join_trans( - trans: Self::OngoingCrateTranslation, + ) -> Box; + + /// This is called on the returned `Box` from `trans_crate` + /// + /// # Panics + /// + /// Panics when the passed `Box` was not returned by `trans_crate`. + fn join_trans_and_link( + &self, + trans: Box, sess: &Session, - dep_graph: &DepGraph - ) -> Self::TranslatedCrate; - fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames); - fn dump_incremental_data(trans: &Self::TranslatedCrate); + dep_graph: &DepGraph, + outputs: &OutputFilenames, + ) -> Result<(), CompileIncomplete>; } pub struct DummyTransCrate; impl TransCrate for DummyTransCrate { - type MetadataLoader = DummyMetadataLoader; - type OngoingCrateTranslation = (); - type TranslatedCrate = (); - - fn metadata_loader() -> Box { + fn metadata_loader(&self) -> Box { box DummyMetadataLoader(()) } - fn provide(_providers: &mut Providers) { + fn provide(&self, _providers: &mut Providers) { bug!("DummyTransCrate::provide"); } - fn provide_extern(_providers: &mut Providers) { + fn provide_extern(&self, _providers: &mut Providers) { bug!("DummyTransCrate::provide_extern"); } fn trans_crate<'a, 'tcx>( + &self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _rx: mpsc::Receiver> - ) -> Self::OngoingCrateTranslation { + ) -> Box { bug!("DummyTransCrate::trans_crate"); } - fn join_trans( - _trans: Self::OngoingCrateTranslation, + fn join_trans_and_link( + &self, + _trans: Box, _sess: &Session, - _dep_graph: &DepGraph - ) -> Self::TranslatedCrate { - bug!("DummyTransCrate::join_trans"); - } - - fn link_binary(_sess: &Session, _trans: &Self::TranslatedCrate, _outputs: &OutputFilenames) { - bug!("DummyTransCrate::link_binary"); - } - - fn dump_incremental_data(_trans: &Self::TranslatedCrate) { - bug!("DummyTransCrate::dump_incremental_data"); + _dep_graph: &DepGraph, + _outputs: &OutputFilenames, + ) -> Result<(), CompileIncomplete> { + bug!("DummyTransCrate::join_trans_and_link"); } } pub struct DummyMetadataLoader(()); -impl MetadataLoaderTrait for DummyMetadataLoader { +impl MetadataLoader for DummyMetadataLoader { fn get_rlib_metadata( &self, _target: &Target, @@ -131,7 +129,7 @@ impl MetadataLoaderTrait for DummyMetadataLoader { pub struct NoLlvmMetadataLoader; -impl MetadataLoaderTrait for NoLlvmMetadataLoader { +impl MetadataLoader for NoLlvmMetadataLoader { fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result, String> { let file = File::open(filename) .map_err(|e| format!("metadata file open err: {:?}", e))?; @@ -161,87 +159,131 @@ impl MetadataLoaderTrait for NoLlvmMetadataLoader { } } -pub struct MetadataOnlyTransCrate; +pub struct MetadataOnlyTransCrate(()); pub struct OngoingCrateTranslation { metadata: EncodedMetadata, metadata_version: Vec, crate_name: Symbol, } -pub struct TranslatedCrate(OngoingCrateTranslation); impl MetadataOnlyTransCrate { - #[allow(dead_code)] - pub fn new() -> Self { - MetadataOnlyTransCrate + pub fn new(sess: &Session) -> Box { + for cty in sess.opts.crate_types.iter() { + match *cty { + CrateType::CrateTypeRlib | CrateType::CrateTypeDylib | + CrateType::CrateTypeExecutable => {}, + _ => { + sess.parse_sess.span_diagnostic.warn( + &format!("LLVM unsupported, so output type {} is not supported", cty) + ); + }, + } + } + + box MetadataOnlyTransCrate(()) } } impl TransCrate for MetadataOnlyTransCrate { - type MetadataLoader = NoLlvmMetadataLoader; - type OngoingCrateTranslation = OngoingCrateTranslation; - type TranslatedCrate = TranslatedCrate; - - fn metadata_loader() -> Box { + fn metadata_loader(&self) -> Box { box NoLlvmMetadataLoader } - fn provide(_providers: &mut Providers) {} - fn provide_extern(_providers: &mut Providers) {} + fn provide(&self, providers: &mut Providers) { + ::symbol_names::provide(providers); + } + fn provide_extern(&self, _providers: &mut Providers) {} fn trans_crate<'a, 'tcx>( + &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, _rx: mpsc::Receiver> - ) -> Self::OngoingCrateTranslation { + ) -> Box { + use rustc_mir::monomorphize::item::MonoItem; + ::check_for_rustc_errors_attr(tcx); + ::symbol_names_test::report_symbol_names(tcx); + ::rustc_incremental::assert_dep_graph(tcx); + ::rustc_incremental::assert_module_sources::assert_module_sources(tcx); + ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, + collector::collect_crate_mono_items( + tcx, + collector::MonoItemCollectionMode::Eager + ).0.iter() + ); + ::rustc::middle::dependency_format::calculate(tcx); let _ = tcx.link_args(LOCAL_CRATE); let _ = tcx.native_libraries(LOCAL_CRATE); + for trans_item in + collector::collect_crate_mono_items( + tcx, + collector::MonoItemCollectionMode::Eager + ).0 { + match trans_item { + MonoItem::Fn(inst) => { + let def_id = inst.def_id(); + if def_id.is_local() { + let _ = tcx.export_name(def_id); + let _ = tcx.contains_extern_indicator(def_id); + let _ = inst.def.is_inline(tcx); + let attrs = inst.def.attrs(tcx); + let _ = + ::syntax::attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs); + } + } + _ => {} + } + } tcx.sess.abort_if_errors(); let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE)); let exported_symbols = ::find_exported_symbols(tcx); let metadata = tcx.encode_metadata(&link_meta, &exported_symbols); - OngoingCrateTranslation { + box OngoingCrateTranslation { metadata: metadata, metadata_version: tcx.metadata_encoding_version().to_vec(), crate_name: tcx.crate_name(LOCAL_CRATE), } } - fn join_trans( - trans: Self::OngoingCrateTranslation, - _sess: &Session, + fn join_trans_and_link( + &self, + trans: Box, + sess: &Session, _dep_graph: &DepGraph, - ) -> Self::TranslatedCrate { - TranslatedCrate(trans) - } - - fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) { + outputs: &OutputFilenames, + ) -> Result<(), CompileIncomplete> { + let trans = trans.downcast::() + .expect("Expected MetadataOnlyTransCrate's OngoingCrateTranslation, found Box"); for &crate_type in sess.opts.crate_types.iter() { if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib { continue; } let output_name = - out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str()); - let mut compressed = trans.0.metadata_version.clone(); + out_filename(sess, crate_type, &outputs, &trans.crate_name.as_str()); + let mut compressed = trans.metadata_version.clone(); let metadata = if crate_type == CrateType::CrateTypeDylib { DeflateEncoder::new(&mut compressed, Compression::fast()) - .write_all(&trans.0.metadata.raw_data) + .write_all(&trans.metadata.raw_data) .unwrap(); &compressed } else { - &trans.0.metadata.raw_data + &trans.metadata.raw_data }; let mut builder = Builder::new(File::create(&output_name).unwrap()); let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64); builder.append(&header, Cursor::new(metadata)).unwrap(); } + sess.abort_if_errors(); if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib) - && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) { + && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) + // Don't error when running under compiletest + && ::std::env::var("RUSTC_COMPILETEST") != Ok("1".to_string()) + { sess.fatal("Executables are not supported by the metadata-only backend."); } + Ok(()) } - - fn dump_incremental_data(_trans: &Self::TranslatedCrate) {} } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b353c0da865..ef7d5b5ff84 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -19,7 +19,6 @@ use rustc::hir::map as hir_map; use rustc::lint; use rustc::util::nodemap::FxHashMap; use rustc_trans; -use rustc_trans::back::link; use rustc_resolve as resolve; use rustc_metadata::cstore::CStore; @@ -140,22 +139,22 @@ pub fn run_core(search_paths: SearchPaths, false, Some(codemap.clone())); - let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader)); let mut sess = session::build_session_( sessopts, cpath, diagnostic_handler, codemap, ); - rustc_trans::init(&sess); + let trans = rustc_trans::LlvmTransCrate::new(&sess); + let cstore = Rc::new(CStore::new(trans.metadata_loader())); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs)); - target_features::add_configuration(&mut cfg, &sess); + target_features::add_configuration(&mut cfg, &sess, &*trans); sess.parse_sess.config = cfg; let control = &driver::CompileController::basic(); let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input)); - let name = link::find_crate_name(Some(&sess), &krate.attrs, &input); + let name = ::rustc_trans_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input); let driver::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. } = { let result = driver::phase_2_configure_and_expand(&sess, @@ -177,7 +176,8 @@ pub fn run_core(search_paths: SearchPaths, &[], &sess); - abort_on_err(driver::phase_3_run_analysis_passes(control, + abort_on_err(driver::phase_3_run_analysis_passes(&*trans, + control, &sess, &*cstore, hir_map, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0b57d5d26ce..2e2dba7681c 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -34,7 +34,7 @@ extern crate libc; extern crate rustc; extern crate rustc_data_structures; extern crate rustc_const_math; -extern crate rustc_trans; +extern crate rustc_trans_utils; extern crate rustc_driver; extern crate rustc_resolve; extern crate rustc_lint; @@ -63,6 +63,8 @@ use std::path::{Path, PathBuf}; use std::process; use std::sync::mpsc::channel; +use rustc_driver::rustc_trans; + use externalfiles::ExternalHtml; use rustc::session::search_paths::SearchPaths; use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options, diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 5432f5cb6e1..10850f88f2d 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -34,7 +34,6 @@ use rustc_driver::driver::phase_2_configure_and_expand; use rustc_metadata::cstore::CStore; use rustc_resolve::MakeGlobMap; use rustc_trans; -use rustc_trans::back::link; use syntax::ast; use syntax::codemap::CodeMap; use syntax::feature_gate::UnstableFeatures; @@ -82,11 +81,11 @@ pub fn run(input_path: &Path, true, false, Some(codemap.clone())); - let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader)); let mut sess = session::build_session_( sessopts, Some(input_path.to_owned()), handler, codemap.clone(), ); - rustc_trans::init(&sess); + let trans = rustc_trans::LlvmTransCrate::new(&sess); + let cstore = Rc::new(CStore::new(trans.metadata_loader())); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); sess.parse_sess.config = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone())); @@ -108,7 +107,7 @@ pub fn run(input_path: &Path, }; let crate_name = crate_name.unwrap_or_else(|| { - link::find_crate_name(None, &hir_forest.krate().attrs, &input) + ::rustc_trans_utils::link::find_crate_name(None, &hir_forest.krate().attrs, &input) }); let opts = scrape_test_config(hir_forest.krate()); let mut collector = Collector::new(crate_name, @@ -247,11 +246,11 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, // Compile the code let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter); - let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader)); let mut sess = session::build_session_( sessopts, None, diagnostic_handler, codemap, ); - rustc_trans::init(&sess); + let trans = rustc_trans::LlvmTransCrate::new(&sess); + let cstore = Rc::new(CStore::new(trans.metadata_loader())); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir")); @@ -266,7 +265,17 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, } let res = panic::catch_unwind(AssertUnwindSafe(|| { - driver::compile_input(&sess, &cstore, &None, &input, &out, &None, None, &control) + driver::compile_input( + trans, + &sess, + &cstore, + &None, + &input, + &out, + &None, + None, + &control + ) })); let compile_result = match res { diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs index f0ab1d5dc0f..c360dde618e 100644 --- a/src/test/run-make/issue-19371/foo.rs +++ b/src/test/run-make/issue-19371/foo.rs @@ -16,6 +16,7 @@ extern crate rustc_lint; extern crate rustc_metadata; extern crate rustc_errors; extern crate rustc_trans; +extern crate rustc_trans_utils; extern crate syntax; use rustc::session::{build_session, Session}; @@ -25,6 +26,7 @@ use rustc_driver::driver::{compile_input, CompileController}; use rustc_metadata::cstore::CStore; use rustc_errors::registry::Registry; use syntax::codemap::FileName; +use rustc_trans_utils::trans_crate::TransCrate; use std::path::PathBuf; use std::rc::Rc; @@ -51,7 +53,7 @@ fn main() { compile(src.to_string(), tmpdir.join("out"), sysroot.clone()); } -fn basic_sess(sysroot: PathBuf) -> (Session, Rc) { +fn basic_sess(sysroot: PathBuf) -> (Session, Rc, Box) { let mut opts = basic_options(); opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); opts.maybe_sysroot = Some(sysroot); @@ -60,16 +62,26 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc) { } let descriptions = Registry::new(&rustc::DIAGNOSTICS); - let cstore = Rc::new(CStore::new(Box::new(rustc_trans::LlvmMetadataLoader))); let sess = build_session(opts, None, descriptions); - rustc_trans::init(&sess); + let trans = rustc_trans::LlvmTransCrate::new(&sess); + let cstore = Rc::new(CStore::new(trans.metadata_loader())); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); - (sess, cstore) + (sess, cstore, trans) } fn compile(code: String, output: PathBuf, sysroot: PathBuf) { - let (sess, cstore) = basic_sess(sysroot); + let (sess, cstore, trans) = basic_sess(sysroot); let control = CompileController::basic(); let input = Input::Str { name: FileName::Anon, input: code }; - let _ = compile_input(&sess, &cstore, &None, &input, &None, &Some(output), None, &control); + let _ = compile_input( + trans, + &sess, + &cstore, + &None, + &input, + &None, + &Some(output), + None, + &control + ); } diff --git a/src/test/run-make/llvm-phase/Makefile b/src/test/run-make/llvm-phase/Makefile deleted file mode 100644 index 6a8e1728b20..00000000000 --- a/src/test/run-make/llvm-phase/Makefile +++ /dev/null @@ -1,5 +0,0 @@ --include ../tools.mk - -all: - $(RUSTC) test.rs - $(call RUN,test $(RUSTC)) diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs deleted file mode 100644 index 2ff4593a801..00000000000 --- a/src/test/run-make/llvm-phase/test.rs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(plugin, rustc_private, box_syntax)] - -extern crate rustc; -extern crate rustc_driver; -extern crate rustc_llvm; -extern crate rustc_trans; -#[macro_use] extern crate syntax; -extern crate getopts; - -use rustc_driver::{CompilerCalls, Compilation}; -use rustc_driver::driver::CompileController; -use rustc_trans::ModuleSource; -use rustc::session::Session; -use syntax::codemap::FileLoader; -use std::env; -use std::io; -use std::path::{PathBuf, Path}; - -struct JitLoader; - -impl FileLoader for JitLoader { - fn file_exists(&self, _: &Path) -> bool { true } - fn abs_path(&self, _: &Path) -> Option { None } - fn read_file(&self, _: &Path) -> io::Result { - Ok(r#" -#[no_mangle] -pub fn test_add(a: i32, b: i32) -> i32 { a + b } -"#.to_string()) - } -} - -#[derive(Copy, Clone)] -struct JitCalls; - -impl<'a> CompilerCalls<'a> for JitCalls { - fn build_controller(&mut self, - _: &Session, - _: &getopts::Matches) - -> CompileController<'a> { - let mut cc = CompileController::basic(); - cc.after_llvm.stop = Compilation::Stop; - cc.after_llvm.run_callback_on_error = true; - cc.after_llvm.callback = Box::new(|state| { - state.session.abort_if_errors(); - let trans = state.trans.unwrap(); - assert_eq!(trans.modules.len(), 1); - println!("name of compiled module = {}", trans.modules[0].name); - }); - cc - } -} - -fn main() { - use rustc_driver; - - let mut path = match std::env::args().nth(2) { - Some(path) => PathBuf::from(&path), - None => panic!("missing rustc path") - }; - - // Remove two segments from rustc path to get sysroot. - path.pop(); - path.pop(); - - let mut args: Vec = - format!("_ _ --sysroot {} --crate-type dylib", path.to_str().unwrap()) - .split(' ').map(|s| s.to_string()).collect(); - args.push("--out-dir".to_string()); - args.push(env::var("TMPDIR").unwrap()); - args.push("-Ccodegen-units=1".to_string()); - - let (result, _) = rustc_driver::run_compiler( - &args, &mut JitCalls, Some(box JitLoader), None); - if let Err(n) = result { - panic!("Error {:?}", n); - } -} diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index b5c1ee09903..85aa92ce260 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -18,6 +18,7 @@ extern crate getopts; extern crate rustc; extern crate rustc_driver; +extern crate rustc_trans_utils; extern crate syntax; extern crate rustc_errors as errors; @@ -25,6 +26,7 @@ use rustc::middle::cstore::CrateStore; use rustc::session::Session; use rustc::session::config::{self, Input}; use rustc_driver::{driver, CompilerCalls, Compilation}; +use rustc_trans_utils::trans_crate::TransCrate; use syntax::ast; use std::path::PathBuf; @@ -46,6 +48,7 @@ impl<'a> CompilerCalls<'a> for TestCalls { } fn late_callback(&mut self, + _: &TransCrate, _: &getopts::Matches, _: &Session, _: &CrateStore, diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index efbe5e32fcd..f849b0a4410 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1278,7 +1278,7 @@ impl<'test> TestCx<'test> { TargetLocation::ThisFile(self.make_exe_name()), ); - rustc.arg("-L").arg(&self.aux_output_dir_name()); + rustc.arg("-L").arg(&self.aux_output_dir_name()).env("RUSTC_COMPILETEST", "1"); match self.config.mode { CompileFail | Ui => { From af0f17386fb2d598883ec4f801da3d7f10ba120b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 27 Dec 2017 18:54:07 +0100 Subject: [PATCH 02/17] Fix rustc_driver test.rs --- src/librustc_driver/test.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index f6f3b9193c6..426cbc5da05 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -16,7 +16,6 @@ use std::sync::mpsc; use driver; use rustc_lint; use rustc_resolve::MakeGlobMap; -use rustc_trans; use rustc::middle::region; use rustc::ty::subst::{Kind, Subst}; use rustc::traits::{ObligationCause, Reveal}; @@ -104,12 +103,11 @@ fn test_env(source_string: &str, options.unstable_features = UnstableFeatures::Allow; let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter); - let cstore = Rc::new(CStore::new(::DefaultTransCrate::new().metadata_loader())); let sess = session::build_session_(options, None, diagnostic_handler, Rc::new(CodeMap::new(FilePathMapping::empty()))); - rustc_trans::init(&sess); + let cstore = Rc::new(CStore::new(::get_trans(&sess).metadata_loader())); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let input = config::Input::Str { name: FileName::Anon, From 2af0f0dddff59625a658a061b3befaed82bb90ea Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 27 Dec 2017 19:03:48 +0100 Subject: [PATCH 03/17] Hide more stuff from rustc_trans --- src/librustc_trans/lib.rs | 42 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index a72fad7a911..96a130d86d2 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -89,15 +89,15 @@ use rustc_trans_utils::trans_crate::TransCrate; mod diagnostics; -pub(crate) mod back { +mod back { + pub use rustc_trans_utils::symbol_names; mod archive; pub mod bytecode; mod command; - pub(crate) mod linker; + pub mod linker; pub mod link; mod lto; - pub(crate) mod symbol_export; - pub(crate) use rustc_trans_utils::symbol_names; + pub mod symbol_export; pub mod write; mod rpath; } @@ -258,8 +258,8 @@ pub struct ModuleTranslation { /// as the crate name and disambiguator. name: String, llmod_id: String, - pub source: ModuleSource, - pub kind: ModuleKind, + source: ModuleSource, + kind: ModuleKind, } #[derive(Copy, Clone, Debug, PartialEq)] @@ -270,14 +270,14 @@ pub enum ModuleKind { } impl ModuleTranslation { - pub fn llvm(&self) -> Option<&ModuleLlvm> { + fn llvm(&self) -> Option<&ModuleLlvm> { match self.source { ModuleSource::Translated(ref llvm) => Some(llvm), ModuleSource::Preexisting(_) => None, } } - pub fn into_compiled_module(self, + fn into_compiled_module(self, emit_obj: bool, emit_bc: bool, emit_bc_compressed: bool, @@ -317,16 +317,16 @@ impl ModuleTranslation { #[derive(Debug)] pub struct CompiledModule { - pub name: String, - pub llmod_id: String, - pub kind: ModuleKind, - pub pre_existing: bool, - pub object: Option, - pub bytecode: Option, - pub bytecode_compressed: Option, + name: String, + llmod_id: String, + kind: ModuleKind, + pre_existing: bool, + object: Option, + bytecode: Option, + bytecode_compressed: Option, } -pub enum ModuleSource { +enum ModuleSource { /// Copy the `.o` files or whatever from the incr. comp. directory. Preexisting(WorkProduct), @@ -337,7 +337,7 @@ pub enum ModuleSource { #[derive(Debug)] pub struct ModuleLlvm { llcx: llvm::ContextRef, - pub llmod: llvm::ModuleRef, + llmod: llvm::ModuleRef, tm: llvm::TargetMachineRef, } @@ -355,12 +355,12 @@ impl Drop for ModuleLlvm { } pub struct CrateTranslation { - pub crate_name: Symbol, - pub modules: Vec, + crate_name: Symbol, + modules: Vec, allocator_module: Option, metadata_module: CompiledModule, - pub link: rustc::middle::cstore::LinkMeta, - pub metadata: rustc::middle::cstore::EncodedMetadata, + link: rustc::middle::cstore::LinkMeta, + metadata: rustc::middle::cstore::EncodedMetadata, windows_subsystem: Option, linker_info: back::linker::LinkerInfo, crate_info: CrateInfo, From bd2e808180e13e6e8411392ba164215237eb144a Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 28 Dec 2017 09:33:53 +0100 Subject: [PATCH 04/17] Fix rustc_driver test.rs --- src/librustc_driver/test.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 426cbc5da05..306e7e9c16d 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -28,7 +28,6 @@ use rustc_metadata::cstore::CStore; use rustc::hir::map as hir_map; use rustc::session::{self, config}; use rustc::session::config::{OutputFilenames, OutputTypes}; -use rustc_trans_utils::trans_crate::TransCrate; use std::rc::Rc; use syntax::ast; use syntax::abi::Abi; From 6dffaa9175449fa771e456210f339cdabe9d0c6d Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 28 Dec 2017 10:11:26 +0100 Subject: [PATCH 05/17] Hide even more of rustc_trans --- src/librustc_trans/allocator.rs | 2 +- src/librustc_trans/back/link.rs | 16 ++++++++-------- src/librustc_trans/back/lto.rs | 10 +++++----- src/librustc_trans/back/write.rs | 22 +++++++++++----------- src/librustc_trans/lib.rs | 12 ++++++------ 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs index 9abb6d66f9c..fd5aa1364d3 100644 --- a/src/librustc_trans/allocator.rs +++ b/src/librustc_trans/allocator.rs @@ -19,7 +19,7 @@ use rustc_allocator::{ALLOCATOR_METHODS, AllocatorTy}; use ModuleLlvm; use llvm::{self, False, True}; -pub unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) { +pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) { let llcx = mods.llcx; let llmod = mods.llmod; let usize = match &tcx.sess.target.target.target_pointer_width[..] { diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index f53c5b3f581..62b65b7952e 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -141,10 +141,10 @@ pub fn remove(sess: &Session, path: &Path) { /// Perform the linkage portion of the compilation phase. This will generate all /// of the requested outputs for this compilation session. -pub fn link_binary(sess: &Session, - trans: &CrateTranslation, - outputs: &OutputFilenames, - crate_name: &str) -> Vec { +pub(crate) fn link_binary(sess: &Session, + trans: &CrateTranslation, + outputs: &OutputFilenames, + crate_name: &str) -> Vec { let mut out_filenames = Vec::new(); for &crate_type in sess.crate_types.borrow().iter() { // Ignore executable crates if we have -Z no-trans, as they will error. @@ -201,9 +201,9 @@ fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilen out_filename } -pub fn each_linked_rlib(sess: &Session, - info: &CrateInfo, - f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> { +pub(crate) fn each_linked_rlib(sess: &Session, + info: &CrateInfo, + f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> { let crates = info.used_crates_static.iter(); let fmts = sess.dependency_formats.borrow(); let fmts = fmts.get(&config::CrateTypeExecutable) @@ -247,7 +247,7 @@ pub fn each_linked_rlib(sess: &Session, /// It's unusual for a crate to not participate in LTO. Typically only /// compiler-specific and unstable crates have a reason to not participate in /// LTO. -pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool { +pub(crate) fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool { // If our target enables builtin function lowering in LLVM then the // crates providing these functions don't participate in LTO (e.g. // no_builtins or compiler builtins crates). diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 60b24a578c6..b612247ffcd 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -42,7 +42,7 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool { } } -pub enum LtoModuleTranslation { +pub(crate) enum LtoModuleTranslation { Fat { module: Option, _serialized_bitcode: Vec, @@ -65,9 +65,9 @@ impl LtoModuleTranslation { /// points to LLVM data structures owned by this `LtoModuleTranslation`. /// It's intended that the module returned is immediately code generated and /// dropped, and then this LTO module is dropped. - pub unsafe fn optimize(&mut self, - cgcx: &CodegenContext, - timeline: &mut Timeline) + pub(crate) unsafe fn optimize(&mut self, + cgcx: &CodegenContext, + timeline: &mut Timeline) -> Result { match *self { @@ -100,7 +100,7 @@ pub enum LTOMode { JustThisCrate, } -pub fn run(cgcx: &CodegenContext, +pub(crate) fn run(cgcx: &CodegenContext, modules: Vec, mode: LTOMode, timeline: &mut Timeline) diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index db0b045ef1e..a013af7a460 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -363,7 +363,7 @@ impl CodegenContext { Handler::with_emitter(true, false, Box::new(self.diag_emitter.clone())) } - pub fn config(&self, kind: ModuleKind) -> &ModuleConfig { + pub(crate) fn config(&self, kind: ModuleKind) -> &ModuleConfig { match kind { ModuleKind::Regular => &self.regular_module_config, ModuleKind::Metadata => &self.metadata_module_config, @@ -371,7 +371,7 @@ impl CodegenContext { } } - pub fn save_temp_bitcode(&self, trans: &ModuleTranslation, name: &str) { + pub(crate) fn save_temp_bitcode(&self, trans: &ModuleTranslation, name: &str) { if !self.save_temps { return } @@ -822,7 +822,7 @@ fn binaryen_assemble(cgcx: &CodegenContext, } } -pub struct CompiledModules { +pub(crate) struct CompiledModules { pub modules: Vec, pub metadata_module: CompiledModule, pub allocator_module: Option, @@ -1162,7 +1162,7 @@ fn produce_final_output_artifacts(sess: &Session, // These are used in linking steps and will be cleaned up afterward. } -pub fn dump_incremental_data(trans: &CrateTranslation) { +pub(crate) fn dump_incremental_data(trans: &CrateTranslation) { println!("[incremental] Re-using {} out of {} modules", trans.modules.iter().filter(|m| m.pre_existing).count(), trans.modules.len()); @@ -2144,7 +2144,7 @@ pub struct OngoingCrateTranslation { } impl OngoingCrateTranslation { - pub fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation { + pub(crate) fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation { self.shared_emitter_main.check(sess, true); let compiled_modules = match self.future.join() { Ok(Ok(compiled_modules)) => compiled_modules, @@ -2212,9 +2212,9 @@ impl OngoingCrateTranslation { trans } - pub fn submit_pre_translated_module_to_llvm(&self, - tcx: TyCtxt, - mtrans: ModuleTranslation) { + pub(crate) fn submit_pre_translated_module_to_llvm(&self, + tcx: TyCtxt, + mtrans: ModuleTranslation) { self.wait_for_signal_to_translate_item(); self.check_for_errors(tcx.sess); @@ -2247,9 +2247,9 @@ impl OngoingCrateTranslation { } } -pub fn submit_translated_module_to_llvm(tcx: TyCtxt, - mtrans: ModuleTranslation, - cost: u64) { +pub(crate) fn submit_translated_module_to_llvm(tcx: TyCtxt, + mtrans: ModuleTranslation, + cost: u64) { let llvm_work_item = WorkItem::Optimize(mtrans); drop(tcx.tx_to_llvm_workers.send(Box::new(Message::TranslationDone { llvm_work_item, diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 96a130d86d2..d1dec63e0d8 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -250,7 +250,7 @@ impl TransCrate for LlvmTransCrate { } } -pub struct ModuleTranslation { +struct ModuleTranslation { /// 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 @@ -263,7 +263,7 @@ pub struct ModuleTranslation { } #[derive(Copy, Clone, Debug, PartialEq)] -pub enum ModuleKind { +enum ModuleKind { Regular, Metadata, Allocator, @@ -316,7 +316,7 @@ impl ModuleTranslation { } #[derive(Debug)] -pub struct CompiledModule { +struct CompiledModule { name: String, llmod_id: String, kind: ModuleKind, @@ -335,7 +335,7 @@ enum ModuleSource { } #[derive(Debug)] -pub struct ModuleLlvm { +struct ModuleLlvm { llcx: llvm::ContextRef, llmod: llvm::ModuleRef, tm: llvm::TargetMachineRef, @@ -354,7 +354,7 @@ impl Drop for ModuleLlvm { } } -pub struct CrateTranslation { +struct CrateTranslation { crate_name: Symbol, modules: Vec, allocator_module: Option, @@ -367,7 +367,7 @@ pub struct CrateTranslation { } // Misc info we load from metadata to persist beyond the tcx -pub struct CrateInfo { +struct CrateInfo { panic_runtime: Option, compiler_builtins: Option, profiler_runtime: Option, From 9315ed45c5d221b868848f8db9ba4a5be155e008 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 1 Jan 2018 12:17:07 +0100 Subject: [PATCH 06/17] Hot plug rustc_trans --- src/Cargo.lock | 12 ++ src/librustc_driver/lib.rs | 3 + src/librustc_trans/lib.rs | 3 + src/librustc_trans_utils/Cargo.toml | 1 + src/librustc_trans_utils/lib.rs | 4 + src/librustc_trans_utils/trans_crate.rs | 181 ++++++++++++++++++++++++ 6 files changed, 204 insertions(+) diff --git a/src/Cargo.lock b/src/Cargo.lock index 6f919fd1acd..1deb89092e6 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1021,6 +1021,16 @@ dependencies = [ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "libloading" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libssh2-sys" version = "0.2.6" @@ -2128,6 +2138,7 @@ version = "0.0.0" dependencies = [ "ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", @@ -2971,6 +2982,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" "checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" "checksum libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6eeae66e7b1c995de45cb4e65c5ab438a96a7b4077e448645d4048dc753ad357" +"checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" "checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index a1bfd2a4774..b5619a0eac0 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -197,6 +197,9 @@ pub fn get_trans(sess: &Session) -> Box { Some("metadata_only") => { rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess) } + Some(filename) if filename.starts_with("/") => { + rustc_trans_utils::trans_crate::ExternTransCrate::new(&sess, filename) + } Some(trans_name) => sess.fatal(&format!("Invalid trans {}", trans_name)), } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index d1dec63e0d8..d03086481a4 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -56,6 +56,7 @@ extern crate rustc_demangle; extern crate rustc_incremental; extern crate rustc_llvm as llvm; extern crate rustc_platform_intrinsics as intrinsics; +#[macro_use] extern crate rustc_trans_utils; #[macro_use] extern crate log; @@ -250,6 +251,8 @@ impl TransCrate for LlvmTransCrate { } } +hot_pluggable_trans_crate!(|sess| { LlvmTransCrate::new(sess) }); + struct ModuleTranslation { /// The name of the module. When the crate may be saved between /// compilations, incremental compilation requires that name be diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml index 7a01b6d261a..6d433bdef3e 100644 --- a/src/librustc_trans_utils/Cargo.toml +++ b/src/librustc_trans_utils/Cargo.toml @@ -13,6 +13,7 @@ test = false ar = "0.3.0" flate2 = "1.0" log = "0.4" +libloading = "0.4" syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index 4920732c41f..029a14a46e6 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -31,6 +31,7 @@ extern crate ar; extern crate flate2; #[macro_use] extern crate log; +extern crate libloading; #[macro_use] extern crate rustc; @@ -42,6 +43,8 @@ extern crate syntax; extern crate syntax_pos; extern crate rustc_data_structures; +pub extern crate rustc as __rustc; + use rustc::ty::{TyCtxt, Instance}; use rustc::hir; use rustc::hir::def_id::LOCAL_CRATE; @@ -50,6 +53,7 @@ use rustc::util::nodemap::NodeSet; pub mod diagnostics; pub mod link; +#[macro_export] pub mod trans_crate; pub mod symbol_names; pub mod symbol_names_test; diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 9d42091e132..31bfe5b02a2 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -24,6 +24,7 @@ use std::any::Any; use std::io::prelude::*; use std::io::{self, Cursor}; +use std::ffi::OsStr; use std::fs::File; use std::path::Path; use std::sync::mpsc; @@ -73,6 +74,186 @@ pub trait TransCrate { ) -> Result<(), CompileIncomplete>; } +#[macro_export] +macro_rules! hot_pluggable_trans_crate { + (|$sess:ident| { $body:expr }) => { + use $crate::__rustc::ty::maps::Providers; + #[no_mangle] + pub extern "C" fn __rustc_backend_new($sess: &Session) -> *mut Box { + let trans_crate = { $body }; + Box::into_raw(Box::new(trans_crate)) + } + + #[no_mangle] + pub extern "C" fn __rustc_backend_metadata_loader( + trans_crate: *const Box + ) -> *mut Box { + let trans_crate = unsafe { &*trans_crate }; + let metadata_loader = trans_crate.metadata_loader(); + Box::into_raw(Box::new(metadata_loader)) + } + + #[no_mangle] + pub extern "C" fn __rustc_backend_provide( + trans_crate: *const Box, + providers: *mut Providers + ) { + let trans_crate = unsafe { &*trans_crate }; + let providers = unsafe { &mut *providers }; + trans_crate.provide(providers); + } + + #[no_mangle] + pub extern "C" fn __rustc_backend_provide_extern( + trans_crate: *const Box, + providers: *mut Providers + ) { + let trans_crate = unsafe { &*trans_crate }; + let providers = unsafe { &mut *providers }; + trans_crate.provide_extern(providers); + } + + #[no_mangle] + pub extern "C" fn __rustc_backend_trans_crate<'a, 'tcx: 'a>( + trans_crate: *const Box, + tcx: *mut TyCtxt<'a, 'tcx, 'tcx>, + rx: *mut mpsc::Receiver> + ) -> *mut Box { + let trans_crate = unsafe { &*trans_crate }; + let tcx = unsafe { *tcx }; + let rx = unsafe { *Box::from_raw(rx) }; + let trans = trans_crate.trans_crate(tcx, rx); + Box::into_raw(Box::new(trans)) + } + + #[no_mangle] + pub extern "C" fn __rustc_backend_join_trans_and_link( + trans_crate: *const Box, + trans: *mut Box, + sess: *const Session, + dep_graph: *const DepGraph, + outputs: *const OutputFilenames + ) -> *mut Result<(), CompileIncomplete> { + let trans_crate = unsafe { &*trans_crate }; + let trans = unsafe { *Box::from_raw(trans) }; + let sess = unsafe { &*sess }; + let dep_graph = unsafe { &*dep_graph }; + let outputs = unsafe { &*outputs }; + let result = trans_crate.join_trans_and_link(trans, sess, dep_graph, outputs); + Box::into_raw(Box::new(result)) + } + } +} + +pub struct ExternTransCrate { + lib: ::libloading::Library, + backend: Box>, +} + +macro_rules! get_symbol { + (($lib:expr) . $name:ident : $type:ty) => { + let $name: ::libloading::Symbol<$type> = $lib.get(stringify!($name).as_bytes()).unwrap(); + } +} + +impl ExternTransCrate { + pub fn new>(sess: &Session, filename: P) -> Box { + use libloading::*; + let filename = filename.as_ref(); + match Library::new(filename) { + Ok(lib) => { + let backend = unsafe { + get_symbol!((lib).__rustc_backend_new: + unsafe extern "C" fn(&Session) -> *mut Box); + Box::from_raw(__rustc_backend_new(sess)) + }; + Box::new(ExternTransCrate { + lib, + backend, + }) + } + Err(err) => { + sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", filename, err)); + } + } + } +} + +impl TransCrate for ExternTransCrate { + fn metadata_loader(&self) -> Box { + unsafe { + get_symbol!((self.lib).__rustc_backend_metadata_loader: + unsafe extern "C" fn(*const Box) -> *mut Box); + *Box::from_raw(__rustc_backend_metadata_loader(self.backend.as_ref() as *const _)) + } + } + + fn provide(&self, providers: &mut Providers) { + unsafe { + get_symbol!((self.lib).__rustc_backend_provide: + unsafe extern "C" fn(*const Box, *mut Providers)); + __rustc_backend_provide(self.backend.as_ref() as *const _, providers as *mut _); + } + } + + fn provide_extern(&self, providers: &mut Providers) { + unsafe { + get_symbol!((self.lib).__rustc_backend_provide_extern: + unsafe extern "C" fn(*const Box, *mut Providers)); + __rustc_backend_provide_extern(self.backend.as_ref() as *const _, providers as *mut _); + } + } + + fn trans_crate<'a, 'tcx>( + &self, + mut tcx: TyCtxt<'a, 'tcx, 'tcx>, + rx: mpsc::Receiver> + ) -> Box { + unsafe { + get_symbol!((self.lib).__rustc_backend_trans_crate: + unsafe extern "C" fn( + *const Box, + *mut TyCtxt<'a, 'tcx, 'tcx>, + *mut mpsc::Receiver> + ) -> *mut Box + ); + let rx = Box::new(rx); + *Box::from_raw(__rustc_backend_trans_crate( + self.backend.as_ref() as *const _, + &mut tcx as *mut _, + Box::into_raw(rx) as *mut _ + )) + } + } + + fn join_trans_and_link( + &self, + trans: Box, + sess: &Session, + dep_graph: &DepGraph, + outputs: &OutputFilenames, + ) -> Result<(), CompileIncomplete> { + unsafe { + get_symbol!((self.lib).__rustc_backend_join_trans_and_link: + unsafe extern "C" fn( + *const Box, + *mut Box, + *const Session, + *const DepGraph, + *const OutputFilenames + ) -> *mut Result<(), CompileIncomplete> + ); + *Box::from_raw(__rustc_backend_join_trans_and_link( + self.backend.as_ref() as *const _, + Box::into_raw(Box::new(trans)) as *mut _, + sess as *const _, + dep_graph as *const _, + outputs as *const _ + )) + } + } +} + pub struct DummyTransCrate; impl TransCrate for DummyTransCrate { From 2d241f66fef30b27fad377ed49fe978541ac0ed8 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 3 Jan 2018 14:36:52 +0100 Subject: [PATCH 07/17] Cleanup hot plug codegen backend code --- src/librustc_driver/lib.rs | 2 +- src/librustc_trans_utils/trans_crate.rs | 181 ++---------------------- 2 files changed, 16 insertions(+), 167 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index b5619a0eac0..558fd3b02be 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -198,7 +198,7 @@ pub fn get_trans(sess: &Session) -> Box { rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess) } Some(filename) if filename.starts_with("/") => { - rustc_trans_utils::trans_crate::ExternTransCrate::new(&sess, filename) + rustc_trans_utils::trans_crate::link_extern_backend(&sess, filename) } Some(trans_name) => sess.fatal(&format!("Invalid trans {}", trans_name)), } diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 31bfe5b02a2..0def49132e4 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -77,179 +77,28 @@ pub trait TransCrate { #[macro_export] macro_rules! hot_pluggable_trans_crate { (|$sess:ident| { $body:expr }) => { - use $crate::__rustc::ty::maps::Providers; #[no_mangle] - pub extern "C" fn __rustc_backend_new($sess: &Session) -> *mut Box { - let trans_crate = { $body }; - Box::into_raw(Box::new(trans_crate)) - } - - #[no_mangle] - pub extern "C" fn __rustc_backend_metadata_loader( - trans_crate: *const Box - ) -> *mut Box { - let trans_crate = unsafe { &*trans_crate }; - let metadata_loader = trans_crate.metadata_loader(); - Box::into_raw(Box::new(metadata_loader)) - } - - #[no_mangle] - pub extern "C" fn __rustc_backend_provide( - trans_crate: *const Box, - providers: *mut Providers - ) { - let trans_crate = unsafe { &*trans_crate }; - let providers = unsafe { &mut *providers }; - trans_crate.provide(providers); - } - - #[no_mangle] - pub extern "C" fn __rustc_backend_provide_extern( - trans_crate: *const Box, - providers: *mut Providers - ) { - let trans_crate = unsafe { &*trans_crate }; - let providers = unsafe { &mut *providers }; - trans_crate.provide_extern(providers); - } - - #[no_mangle] - pub extern "C" fn __rustc_backend_trans_crate<'a, 'tcx: 'a>( - trans_crate: *const Box, - tcx: *mut TyCtxt<'a, 'tcx, 'tcx>, - rx: *mut mpsc::Receiver> - ) -> *mut Box { - let trans_crate = unsafe { &*trans_crate }; - let tcx = unsafe { *tcx }; - let rx = unsafe { *Box::from_raw(rx) }; - let trans = trans_crate.trans_crate(tcx, rx); - Box::into_raw(Box::new(trans)) - } - - #[no_mangle] - pub extern "C" fn __rustc_backend_join_trans_and_link( - trans_crate: *const Box, - trans: *mut Box, - sess: *const Session, - dep_graph: *const DepGraph, - outputs: *const OutputFilenames - ) -> *mut Result<(), CompileIncomplete> { - let trans_crate = unsafe { &*trans_crate }; - let trans = unsafe { *Box::from_raw(trans) }; - let sess = unsafe { &*sess }; - let dep_graph = unsafe { &*dep_graph }; - let outputs = unsafe { &*outputs }; - let result = trans_crate.join_trans_and_link(trans, sess, dep_graph, outputs); - Box::into_raw(Box::new(result)) + pub fn __rustc_backend_new($sess: &Session) -> Box { + { $body } } } } -pub struct ExternTransCrate { - lib: ::libloading::Library, - backend: Box>, -} - -macro_rules! get_symbol { - (($lib:expr) . $name:ident : $type:ty) => { - let $name: ::libloading::Symbol<$type> = $lib.get(stringify!($name).as_bytes()).unwrap(); - } -} - -impl ExternTransCrate { - pub fn new>(sess: &Session, filename: P) -> Box { - use libloading::*; - let filename = filename.as_ref(); - match Library::new(filename) { - Ok(lib) => { - let backend = unsafe { - get_symbol!((lib).__rustc_backend_new: - unsafe extern "C" fn(&Session) -> *mut Box); - Box::from_raw(__rustc_backend_new(sess)) - }; - Box::new(ExternTransCrate { - lib, - backend, - }) - } - Err(err) => { - sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", filename, err)); +pub fn link_extern_backend>(sess: &Session, filename: P) -> Box { + use libloading::*; + let filename = filename.as_ref(); + match Library::new(filename) { + Ok(lib) => { + unsafe { + let __rustc_backend_new: Symbol Box>; + __rustc_backend_new = lib.get(b"__rustc_backend_new") + .expect("Couldnt load codegen backend as it\ + doesnt export the __rustc_backend_new symbol"); + __rustc_backend_new(sess) } } - } -} - -impl TransCrate for ExternTransCrate { - fn metadata_loader(&self) -> Box { - unsafe { - get_symbol!((self.lib).__rustc_backend_metadata_loader: - unsafe extern "C" fn(*const Box) -> *mut Box); - *Box::from_raw(__rustc_backend_metadata_loader(self.backend.as_ref() as *const _)) - } - } - - fn provide(&self, providers: &mut Providers) { - unsafe { - get_symbol!((self.lib).__rustc_backend_provide: - unsafe extern "C" fn(*const Box, *mut Providers)); - __rustc_backend_provide(self.backend.as_ref() as *const _, providers as *mut _); - } - } - - fn provide_extern(&self, providers: &mut Providers) { - unsafe { - get_symbol!((self.lib).__rustc_backend_provide_extern: - unsafe extern "C" fn(*const Box, *mut Providers)); - __rustc_backend_provide_extern(self.backend.as_ref() as *const _, providers as *mut _); - } - } - - fn trans_crate<'a, 'tcx>( - &self, - mut tcx: TyCtxt<'a, 'tcx, 'tcx>, - rx: mpsc::Receiver> - ) -> Box { - unsafe { - get_symbol!((self.lib).__rustc_backend_trans_crate: - unsafe extern "C" fn( - *const Box, - *mut TyCtxt<'a, 'tcx, 'tcx>, - *mut mpsc::Receiver> - ) -> *mut Box - ); - let rx = Box::new(rx); - *Box::from_raw(__rustc_backend_trans_crate( - self.backend.as_ref() as *const _, - &mut tcx as *mut _, - Box::into_raw(rx) as *mut _ - )) - } - } - - fn join_trans_and_link( - &self, - trans: Box, - sess: &Session, - dep_graph: &DepGraph, - outputs: &OutputFilenames, - ) -> Result<(), CompileIncomplete> { - unsafe { - get_symbol!((self.lib).__rustc_backend_join_trans_and_link: - unsafe extern "C" fn( - *const Box, - *mut Box, - *const Session, - *const DepGraph, - *const OutputFilenames - ) -> *mut Result<(), CompileIncomplete> - ); - *Box::from_raw(__rustc_backend_join_trans_and_link( - self.backend.as_ref() as *const _, - Box::into_raw(Box::new(trans)) as *mut _, - sess as *const _, - dep_graph as *const _, - outputs as *const _ - )) + Err(err) => { + sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", filename, err)); } } } From ace502a10736dba186785ea439c50be75d0cfdfb Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 4 Jan 2018 12:40:11 +0100 Subject: [PATCH 08/17] Fix review comments --- src/librustc_driver/lib.rs | 81 ++++++++++++++++++++++++- src/librustc_trans/lib.rs | 7 ++- src/librustc_trans_utils/lib.rs | 2 - src/librustc_trans_utils/trans_crate.rs | 32 +--------- 4 files changed, 84 insertions(+), 38 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 558fd3b02be..14d14ab591e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -189,6 +189,81 @@ pub mod rustc_trans { pub fn print_passes() {} } +fn load_backend_from_dylib(sess: &Session, backend_name: &str) -> Box { + use std::sync::mpsc; + use std::path::Path; + use syntax::symbol::Symbol; + use rustc::session::config::OutputFilenames; + use rustc::ty::TyCtxt; + use rustc::ty::maps::Providers; + use rustc::middle::cstore::MetadataLoader; + use rustc::dep_graph::DepGraph; + use rustc_metadata::dynamic_lib::DynamicLibrary; + /// This prevents the dylib from being unloaded when there is still a TransCrate open + struct ExternTransCrate { + _lib: DynamicLibrary, + trans: Box, + } + impl TransCrate for ExternTransCrate { + fn print(&self, req: PrintRequest, sess: &Session) { + self.trans.print(req, sess); + } + fn target_features(&self, sess: &Session) -> Vec { + self.trans.target_features((sess)) + } + + fn metadata_loader(&self) -> Box { + self.trans.metadata_loader() + } + fn provide(&self, providers: &mut Providers) { + self.trans.provide(providers) + } + fn provide_extern(&self, providers: &mut Providers) { + self.trans.provide_extern(providers) + } + fn trans_crate<'a, 'tcx>( + &self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + rx: mpsc::Receiver> + ) -> Box { + self.trans.trans_crate(tcx, rx) + } + + fn join_trans_and_link( + &self, + trans: Box, + sess: &Session, + dep_graph: &DepGraph, + outputs: &OutputFilenames, + ) -> Result<(), CompileIncomplete> { + self.trans.join_trans_and_link(trans, sess, dep_graph, outputs) + } + } + + match DynamicLibrary::open(Some(Path::new(backend_name))) { + Ok(lib) => { + unsafe { + let trans = { + let __rustc_codegen_backend: unsafe fn(&Session) -> Box; + __rustc_codegen_backend = match lib.symbol("__rustc_codegen_backend") { + Ok(f) => ::std::mem::transmute::<*mut u8, _>(f), + Err(e) => sess.fatal(&format!("Couldnt load codegen backend as it\ + doesn't export the __rustc_backend_new symbol: {:?}", e)), + }; + __rustc_codegen_backend(sess) + }; + Box::new(ExternTransCrate { + _lib: lib, + trans + }) + } + } + Err(err) => { + sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", backend_name, err)); + } + } +} + pub fn get_trans(sess: &Session) -> Box { let trans_name = sess.opts.debugging_opts.codegen_backend.clone(); match trans_name.as_ref().map(|s|&**s) { @@ -197,10 +272,10 @@ pub fn get_trans(sess: &Session) -> Box { Some("metadata_only") => { rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess) } - Some(filename) if filename.starts_with("/") => { - rustc_trans_utils::trans_crate::link_extern_backend(&sess, filename) + Some(filename) if filename.contains(".") => { + load_backend_from_dylib(&sess, &filename) } - Some(trans_name) => sess.fatal(&format!("Invalid trans {}", trans_name)), + Some(trans_name) => sess.fatal(&format!("Unknown codegen backend {}", trans_name)), } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index d03086481a4..a2a7d0df2a9 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -56,7 +56,6 @@ extern crate rustc_demangle; extern crate rustc_incremental; extern crate rustc_llvm as llvm; extern crate rustc_platform_intrinsics as intrinsics; -#[macro_use] extern crate rustc_trans_utils; #[macro_use] extern crate log; @@ -251,7 +250,11 @@ impl TransCrate for LlvmTransCrate { } } -hot_pluggable_trans_crate!(|sess| { LlvmTransCrate::new(sess) }); +/// This is the entrypoint for a hot plugged rustc_trans +#[no_mangle] +pub extern "C" fn __rustc_codegen_backend(sess: &Session) -> Box { + LlvmTransCrate::new(sess) +} struct ModuleTranslation { /// The name of the module. When the crate may be saved between diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index 029a14a46e6..bfecb201983 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -31,7 +31,6 @@ extern crate ar; extern crate flate2; #[macro_use] extern crate log; -extern crate libloading; #[macro_use] extern crate rustc; @@ -53,7 +52,6 @@ use rustc::util::nodemap::NodeSet; pub mod diagnostics; pub mod link; -#[macro_export] pub mod trans_crate; pub mod symbol_names; pub mod symbol_names_test; diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 0def49132e4..33adf24374a 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -24,7 +24,6 @@ use std::any::Any; use std::io::prelude::*; use std::io::{self, Cursor}; -use std::ffi::OsStr; use std::fs::File; use std::path::Path; use std::sync::mpsc; @@ -41,7 +40,7 @@ use rustc::session::config::{CrateType, OutputFilenames, PrintRequest}; use rustc::ty::TyCtxt; use rustc::ty::maps::Providers; use rustc::middle::cstore::EncodedMetadata; -use rustc::middle::cstore::MetadataLoader as MetadataLoader; +use rustc::middle::cstore::MetadataLoader; use rustc::dep_graph::DepGraph; use rustc_back::target::Target; use rustc_mir::monomorphize::collector; @@ -74,35 +73,6 @@ pub trait TransCrate { ) -> Result<(), CompileIncomplete>; } -#[macro_export] -macro_rules! hot_pluggable_trans_crate { - (|$sess:ident| { $body:expr }) => { - #[no_mangle] - pub fn __rustc_backend_new($sess: &Session) -> Box { - { $body } - } - } -} - -pub fn link_extern_backend>(sess: &Session, filename: P) -> Box { - use libloading::*; - let filename = filename.as_ref(); - match Library::new(filename) { - Ok(lib) => { - unsafe { - let __rustc_backend_new: Symbol Box>; - __rustc_backend_new = lib.get(b"__rustc_backend_new") - .expect("Couldnt load codegen backend as it\ - doesnt export the __rustc_backend_new symbol"); - __rustc_backend_new(sess) - } - } - Err(err) => { - sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", filename, err)); - } - } -} - pub struct DummyTransCrate; impl TransCrate for DummyTransCrate { From 4ef16d7466cca262c682fb3a9441a88a61a089df Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 4 Jan 2018 18:15:40 +0100 Subject: [PATCH 09/17] Fix hotplug backend and add test --- src/librustc_driver/lib.rs | 8 +++ .../run-make/hotplug_codegen_backend/Makefile | 10 +++ .../hotplug_codegen_backend/some_crate.rs | 3 + .../hotplug_codegen_backend/the_backend.rs | 72 +++++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 src/test/run-make/hotplug_codegen_backend/Makefile create mode 100644 src/test/run-make/hotplug_codegen_backend/some_crate.rs create mode 100644 src/test/run-make/hotplug_codegen_backend/the_backend.rs diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 14d14ab591e..e9535ba6396 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -204,6 +204,14 @@ fn load_backend_from_dylib(sess: &Session, backend_name: &str) -> Box, } + + impl Drop for ExternTransCrate { + fn drop(&mut self) { + // Make sure trans gets dropped before _lib as bad things happen otherwise + self.trans = Box::new(::rustc_trans_utils::trans_crate::DummyTransCrate) + } + } + impl TransCrate for ExternTransCrate { fn print(&self, req: PrintRequest, sess: &Session) { self.trans.print(req, sess); diff --git a/src/test/run-make/hotplug_codegen_backend/Makefile b/src/test/run-make/hotplug_codegen_backend/Makefile new file mode 100644 index 00000000000..1916983a9e7 --- /dev/null +++ b/src/test/run-make/hotplug_codegen_backend/Makefile @@ -0,0 +1,10 @@ +include ../tools.mk + +all: + /bin/echo || exit 0 # This test requires /bin/echo to exist + $(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \ + -o $(TMPDIR)/the_backend.dylib + sleep 10 + $(RUSTC) some_crate.rs --crate-name some_crate --crate-type bin -o $(TMPDIR)/some_crate \ + -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options + grep -x "This has been \"compiled\" succesfully." $(TMPDIR)/some_crate diff --git a/src/test/run-make/hotplug_codegen_backend/some_crate.rs b/src/test/run-make/hotplug_codegen_backend/some_crate.rs new file mode 100644 index 00000000000..7d01978dcee --- /dev/null +++ b/src/test/run-make/hotplug_codegen_backend/some_crate.rs @@ -0,0 +1,3 @@ +fn main() { + ::std::process::exit(1); +} diff --git a/src/test/run-make/hotplug_codegen_backend/the_backend.rs b/src/test/run-make/hotplug_codegen_backend/the_backend.rs new file mode 100644 index 00000000000..8200658b1f1 --- /dev/null +++ b/src/test/run-make/hotplug_codegen_backend/the_backend.rs @@ -0,0 +1,72 @@ +#![feature(rustc_private)] + +extern crate syntax; +extern crate rustc; +extern crate rustc_trans_utils; + +use std::any::Any; +use std::sync::mpsc; +use syntax::symbol::Symbol; +use rustc::session::{Session, CompileIncomplete}; +use rustc::session::config::OutputFilenames; +use rustc::ty::TyCtxt; +use rustc::ty::maps::Providers; +use rustc::middle::cstore::MetadataLoader; +use rustc::dep_graph::DepGraph; +use rustc_trans_utils::trans_crate::{TransCrate, MetadataOnlyTransCrate}; + +struct TheBackend(Box); + +impl TransCrate for TheBackend { + fn metadata_loader(&self) -> Box { + self.0.metadata_loader() + } + + fn provide(&self, providers: &mut Providers) { + self.0.provide(providers); + } + + fn provide_extern(&self, providers: &mut Providers) { + self.0.provide_extern(providers); + } + + fn trans_crate<'a, 'tcx>( + &self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + _rx: mpsc::Receiver> + ) -> Box { + use rustc::hir::def_id::LOCAL_CRATE; + + Box::new(tcx.crate_name(LOCAL_CRATE) as Symbol) + } + + fn join_trans_and_link( + &self, + trans: Box, + sess: &Session, + _dep_graph: &DepGraph, + outputs: &OutputFilenames, + ) -> Result<(), CompileIncomplete> { + use std::io::Write; + use rustc::session::config::CrateType; + use rustc_trans_utils::link::out_filename; + let crate_name = trans.downcast::() + .expect("in join_trans_and_link: trans is not a Symbol"); + for &crate_type in sess.opts.crate_types.iter() { + if crate_type != CrateType::CrateTypeExecutable { + sess.fatal(&format!("Crate type is {:?}", crate_type)); + } + let output_name = + out_filename(sess, crate_type, &outputs, &*crate_name.as_str()); + let mut out_file = ::std::fs::File::create(output_name).unwrap(); + write!(out_file, "This has been \"compiled\" succesfully.").unwrap(); + } + Ok(()) + } +} + +/// This is the entrypoint for a hot plugged rustc_trans +#[no_mangle] +pub extern "C" fn __rustc_codegen_backend(sess: &Session) -> Box { + Box::new(TheBackend(MetadataOnlyTransCrate::new(sess))) +} From d2c53f8b4d6a5ba69eaaa883a417fbd08e0d75b7 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 4 Jan 2018 18:26:34 +0100 Subject: [PATCH 10/17] Add missing licenses --- .../run-make/hotplug_codegen_backend/some_crate.rs | 10 ++++++++++ .../run-make/hotplug_codegen_backend/the_backend.rs | 12 +++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/test/run-make/hotplug_codegen_backend/some_crate.rs b/src/test/run-make/hotplug_codegen_backend/some_crate.rs index 7d01978dcee..26ffce01b2e 100644 --- a/src/test/run-make/hotplug_codegen_backend/some_crate.rs +++ b/src/test/run-make/hotplug_codegen_backend/some_crate.rs @@ -1,3 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + fn main() { ::std::process::exit(1); } diff --git a/src/test/run-make/hotplug_codegen_backend/the_backend.rs b/src/test/run-make/hotplug_codegen_backend/the_backend.rs index 8200658b1f1..fc06737e0e9 100644 --- a/src/test/run-make/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make/hotplug_codegen_backend/the_backend.rs @@ -1,3 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #![feature(rustc_private)] extern crate syntax; @@ -36,7 +46,7 @@ impl TransCrate for TheBackend { _rx: mpsc::Receiver> ) -> Box { use rustc::hir::def_id::LOCAL_CRATE; - + Box::new(tcx.crate_name(LOCAL_CRATE) as Symbol) } From 77dec3b03a57c10a90eb33f1759c0be470132e9e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 9 Jan 2018 18:37:33 +0100 Subject: [PATCH 11/17] Remove use of RUSTC_COMPILETEST env var --- src/librustc_trans_utils/trans_crate.rs | 2 -- src/tools/compiletest/src/runtest.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 33adf24374a..0d81d6fde6a 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -279,8 +279,6 @@ impl TransCrate for MetadataOnlyTransCrate { sess.abort_if_errors(); if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib) && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) - // Don't error when running under compiletest - && ::std::env::var("RUSTC_COMPILETEST") != Ok("1".to_string()) { sess.fatal("Executables are not supported by the metadata-only backend."); } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f849b0a4410..efbe5e32fcd 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1278,7 +1278,7 @@ impl<'test> TestCx<'test> { TargetLocation::ThisFile(self.make_exe_name()), ); - rustc.arg("-L").arg(&self.aux_output_dir_name()).env("RUSTC_COMPILETEST", "1"); + rustc.arg("-L").arg(&self.aux_output_dir_name()); match self.config.mode { CompileFail | Ui => { From c0444242ef800938ebcfd41a9da20b61ca6be4fb Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 10 Jan 2018 15:20:54 +0100 Subject: [PATCH 12/17] Fix ICE --- src/librustc_trans_utils/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index bfecb201983..9b7ab204492 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -119,4 +119,5 @@ pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet { }).collect() } +#[cfg(not(stage0))] // remove after the next snapshot __build_diagnostic_array! { librustc_trans_utils, DIAGNOSTICS } From a09aebee21f5d394a62846091b1d08e9d10c3a67 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 12 Jan 2018 08:17:34 +0100 Subject: [PATCH 13/17] Remove accidential libloading dependency --- src/Cargo.lock | 12 ------------ src/librustc_trans_utils/Cargo.toml | 1 - 2 files changed, 13 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 1deb89092e6..6f919fd1acd 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1021,16 +1021,6 @@ dependencies = [ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "libloading" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "libssh2-sys" version = "0.2.6" @@ -2138,7 +2128,6 @@ version = "0.0.0" dependencies = [ "ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", @@ -2982,7 +2971,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" "checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" "checksum libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6eeae66e7b1c995de45cb4e65c5ab438a96a7b4077e448645d4048dc753ad357" -"checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" "checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml index 6d433bdef3e..7a01b6d261a 100644 --- a/src/librustc_trans_utils/Cargo.toml +++ b/src/librustc_trans_utils/Cargo.toml @@ -13,7 +13,6 @@ test = false ar = "0.3.0" flate2 = "1.0" log = "0.4" -libloading = "0.4" syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } From cc4deb2767b418d88f8520a2d55488f7b9b27b19 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 12 Jan 2018 18:57:00 +0100 Subject: [PATCH 14/17] Just forget the DynamicLibrary after getting a hot plugged backend --- src/librustc_driver/lib.rs | 61 ++------------------------------------ 1 file changed, 2 insertions(+), 59 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index e9535ba6396..de5559c8b14 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -190,63 +190,8 @@ pub mod rustc_trans { } fn load_backend_from_dylib(sess: &Session, backend_name: &str) -> Box { - use std::sync::mpsc; use std::path::Path; - use syntax::symbol::Symbol; - use rustc::session::config::OutputFilenames; - use rustc::ty::TyCtxt; - use rustc::ty::maps::Providers; - use rustc::middle::cstore::MetadataLoader; - use rustc::dep_graph::DepGraph; use rustc_metadata::dynamic_lib::DynamicLibrary; - /// This prevents the dylib from being unloaded when there is still a TransCrate open - struct ExternTransCrate { - _lib: DynamicLibrary, - trans: Box, - } - - impl Drop for ExternTransCrate { - fn drop(&mut self) { - // Make sure trans gets dropped before _lib as bad things happen otherwise - self.trans = Box::new(::rustc_trans_utils::trans_crate::DummyTransCrate) - } - } - - impl TransCrate for ExternTransCrate { - fn print(&self, req: PrintRequest, sess: &Session) { - self.trans.print(req, sess); - } - fn target_features(&self, sess: &Session) -> Vec { - self.trans.target_features((sess)) - } - - fn metadata_loader(&self) -> Box { - self.trans.metadata_loader() - } - fn provide(&self, providers: &mut Providers) { - self.trans.provide(providers) - } - fn provide_extern(&self, providers: &mut Providers) { - self.trans.provide_extern(providers) - } - fn trans_crate<'a, 'tcx>( - &self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - rx: mpsc::Receiver> - ) -> Box { - self.trans.trans_crate(tcx, rx) - } - - fn join_trans_and_link( - &self, - trans: Box, - sess: &Session, - dep_graph: &DepGraph, - outputs: &OutputFilenames, - ) -> Result<(), CompileIncomplete> { - self.trans.join_trans_and_link(trans, sess, dep_graph, outputs) - } - } match DynamicLibrary::open(Some(Path::new(backend_name))) { Ok(lib) => { @@ -260,10 +205,8 @@ fn load_backend_from_dylib(sess: &Session, backend_name: &str) -> Box { From 82ac9f7532accc29730848242411dbe15a143c51 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 19 Jan 2018 20:24:42 +0100 Subject: [PATCH 15/17] Hopefully fix the 32bit SEGV --- src/librustc_trans/lib.rs | 2 +- src/test/run-make/hotplug_codegen_backend/Makefile | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index a2a7d0df2a9..b67997081aa 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -252,7 +252,7 @@ impl TransCrate for LlvmTransCrate { /// This is the entrypoint for a hot plugged rustc_trans #[no_mangle] -pub extern "C" fn __rustc_codegen_backend(sess: &Session) -> Box { +pub fn __rustc_codegen_backend(sess: &Session) -> Box { LlvmTransCrate::new(sess) } diff --git a/src/test/run-make/hotplug_codegen_backend/Makefile b/src/test/run-make/hotplug_codegen_backend/Makefile index 1916983a9e7..9a216d1d81f 100644 --- a/src/test/run-make/hotplug_codegen_backend/Makefile +++ b/src/test/run-make/hotplug_codegen_backend/Makefile @@ -4,7 +4,6 @@ all: /bin/echo || exit 0 # This test requires /bin/echo to exist $(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \ -o $(TMPDIR)/the_backend.dylib - sleep 10 $(RUSTC) some_crate.rs --crate-name some_crate --crate-type bin -o $(TMPDIR)/some_crate \ -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options grep -x "This has been \"compiled\" succesfully." $(TMPDIR)/some_crate From a4854e84f283c19db8383e40bfe0b16c3119cf67 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 20 Jan 2018 11:55:55 +0100 Subject: [PATCH 16/17] Fix ICE --- src/librustc_trans_utils/trans_crate.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 0d81d6fde6a..49756d754fe 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -26,6 +26,7 @@ use std::io::prelude::*; use std::io::{self, Cursor}; use std::fs::File; use std::path::Path; +use std::rc::Rc; use std::sync::mpsc; use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef}; @@ -191,6 +192,9 @@ impl TransCrate for MetadataOnlyTransCrate { fn provide(&self, providers: &mut Providers) { ::symbol_names::provide(providers); + providers.target_features_enabled = |_tcx, _id| { + Rc::new(Vec::new()) // Just a dummy + }; } fn provide_extern(&self, _providers: &mut Providers) {} From a30232f9fd6be9b81e7aa7cfe38b1755ecd9c770 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 20 Jan 2018 17:27:00 +0100 Subject: [PATCH 17/17] Remove the 'extern "C"' in the right place --- src/test/run-make/hotplug_codegen_backend/the_backend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make/hotplug_codegen_backend/the_backend.rs b/src/test/run-make/hotplug_codegen_backend/the_backend.rs index fc06737e0e9..0de404ed249 100644 --- a/src/test/run-make/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make/hotplug_codegen_backend/the_backend.rs @@ -77,6 +77,6 @@ impl TransCrate for TheBackend { /// This is the entrypoint for a hot plugged rustc_trans #[no_mangle] -pub extern "C" fn __rustc_codegen_backend(sess: &Session) -> Box { +pub fn __rustc_codegen_backend(sess: &Session) -> Box { Box::new(TheBackend(MetadataOnlyTransCrate::new(sess))) }