diff --git a/src/Cargo.lock b/src/Cargo.lock index 1a38a5365db18f2f1156a3a10ce237ca89cc9ed0..6f919fd1acd3c79d7c011b8595baeeb4923d3c54 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 69b86416afab0651df18b3a9b253966ac8f522da..cd4e3cfed7a3391fac50249ceec17fb8455147e2 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1045,6 +1045,8 @@ fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) -> 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 f7e35ba0081e46300d3d88f7e1193f1db65b5725..468a08b1fd9f37fd36989e6a6377a315d98af693 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -31,7 +31,6 @@ 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_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 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 @@ pub fn basic() -> 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 @@ fn empty(input: &'a Input, resolutions: None, analysis: None, tcx: None, - trans: None, } } @@ -528,19 +488,6 @@ fn state_after_analysis(input: &'a Input, } } - 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 237656eb43c69d3d0001e4f9e29ed6698c5e0d49..a1bfd2a47742e5b1edfa3c1800283d7725bc3a89 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -48,7 +48,7 @@ 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::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 @@ 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 fn run(run_compiler: F) -> isize 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 @@ fn early_callback(&mut self, // 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 @@ fn no_input(&mut self, 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 @@ fn no_input(&mut self, } fn late_callback(&mut self, + trans: &TransCrate, matches: &getopts::Matches, sess: &Session, cstore: &CrateStore, @@ -543,7 +576,7 @@ fn late_callback(&mut self, 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 @@ fn build_controller(&mut self, 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 @@ pub fn list_metadata(sess: &Session, } - 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 @@ fn print_crate_info(sess: &Session, }; 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 @@ fn print_crate_info(sess: &Session, .to_string_lossy()); } } - PrintRequest::Cfg => { + Cfg => { let allow_unstable_cfg = UnstableFeatures::from_environment() .is_nightly_build(); @@ -781,29 +810,8 @@ fn print_crate_info(sess: &Session, 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 6ce6929af5cabf6e9b959b4245e607ed2f473a81..af3d1e4d4d0108acf1aa555f46f6d7a62d4b3b91 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -228,7 +228,8 @@ fn call_with_pp_support_hir<'tcx, A, F>(&self, } 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 96264472b5f8e53e0fe752afd6f5d174ef6ebcdf..0000000000000000000000000000000000000000 --- 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 371f0e79a3ad1dc9c8f82639821463a4d195f9da..f6f3b9193c6491193e72d1ba13f9169d4e178bfa 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 745197d64f2f676487e2c7279064321a6f1d98e7..46ba94f2061512963fea18f207c780e38635c6d5 100644 --- a/src/librustc_trans/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -40,7 +40,7 @@ #[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 0b827a0ee9873e58cb7be015eaefe98aca199c61..b53ee1daada429427c18040a8bdf48619b7972fd 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -32,6 +32,7 @@ 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 195335dd64c1349aa0692784295af8737e9b39a2..ea05a513f7e7d9c5d7190d3cd00cf91d885eace3 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 5379bf3f5a7aeed0db424d3ab5617e611b170eef..1699ad0f19cf63eed34c815acd17b523e9a0c9fa 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -57,7 +57,6 @@ 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 024334f1c849c2f0464a560658a3b52d078fffb3..072c339813490bbd2e0e450de7674a8379b0eb68 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -26,6 +26,7 @@ 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 @@ fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, 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 fcf0d71dccb48ab2a7121c28c745f7efa9635fd2..95ebb6c970a588ec4c3758818f4bd7ff88bec703 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -22,6 +22,54 @@ 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 ea68e3b28b668e8047630f476b673c51fc0ec071..f93f317a0a0f772ad05aad62cf8c16a4f9b24d8c 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 @@ pub fn output(&mut self) -> io::Result { 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 633ed9b32cd1e59880f0708182e7027495810ec2..734ad8f3929ed0d9ac2e130cf940002a4ca319d9 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -29,7 +29,6 @@ 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 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 8f5d836f56f3ffffca87481525ce758d20669e2a..57cc33d09bbea94e1f36f7fa1c82fe58ae831ce5 100644 --- a/src/librustc_trans/diagnostics.rs +++ b/src/librustc_trans/diagnostics.rs @@ -47,27 +47,9 @@ fn main() { ``` "##, -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 974c268749b859a5620059aea0f6e6846963aaa7..a72fad7a9118dc3434e703a059c307e41287def2 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 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::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 @@ pub mod back { mod metadata; mod meth; mod mir; -mod symbol_names_test; mod time_graph; mod trans_item; mod type_; @@ -148,53 +145,108 @@ pub mod back { 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)); + + 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); - fn dump_incremental_data(trans: &Self::TranslatedCrate) { - back::write::dump_incremental_data(trans); + Ok(()) } } diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs index 214fdbded4e90bf74a17a290f3ae676f896abdbb..15988008de2fc6981a4e3c44d9a7fb69cfcc7fd7 100644 --- a/src/librustc_trans/llvm_util.rs +++ b/src/librustc_trans/llvm_util.rs @@ -19,11 +19,12 @@ 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 cc270ab5f2d25264f9d50ca79a794105bd493fe4..5eb6679fe252c0480d176e2419f90595d2840dc7 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -25,11 +25,10 @@ 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 @@ fn predefine(&self, 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 7b9537ee23e23c8f729a6f622e82390f5126c7dc..7a01b6d261a34cca1cb90c6c6cad730037aabbb4 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 0000000000000000000000000000000000000000..13fa15faf4123048174da692bd8aa276b75a7a26 --- /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 77afc2899c329517e5958e4568871f85a8fe2995..4920732c41f372e96e5b54144b1d1ba9ea19a5ad 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -35,6 +35,9 @@ #[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::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 3ceff659ea93a40e79fbcbe0f74b2dbffc5b20c2..fb299bf7eea0c4ebadd4bea011c7ca19b7b16036 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 15c142cf947c89b5e2a476b2d19fc475580766aa..5d7d4f3055bad6f47a6520561ce861f0eece9751 100644 --- a/src/librustc_trans/symbol_names_test.rs +++ b/src/librustc_trans_utils/symbol_names_test.rs @@ -19,7 +19,7 @@ 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 47143893e59e23393da133feff95be4f6aa17100..9d42091e132a6a4f2dd92bfa7a4f2d2f35b68b8f 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -35,83 +35,81 @@ 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 @@ fn get_dylib_metadata( 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 @@ fn get_dylib_metadata( } } -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 b353c0da865c86cfa5fbf66b78add79382845fa8..ef7d5b5ff84afb8926f1c3743a253d6899034a88 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -19,7 +19,6 @@ 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 0b57d5d26cecf8d110ebe5d42c930cdb28e225fd..2e2dba7681cc39a9c3156bf28028e70b162949e7 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -34,7 +34,7 @@ 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::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 5432f5cb6e1656b4c0f8891c4a1d2d007fee0873..10850f88f2d624d2944d0aef915f9a4ba2f65638 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -34,7 +34,6 @@ 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 drop(&mut self) { // 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 drop(&mut self) { } 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 f0ab1d5dc0fec7eabec80afd1a2bb6c1c907e803..c360dde618ef54f2f2a7167c0081f4643a505716 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_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_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 6a8e1728b20a83773edaac0598ce0e119455cdd0..0000000000000000000000000000000000000000 --- 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 2ff4593a801fe74601708e30d9ea0d79a87edf32..0000000000000000000000000000000000000000 --- 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 b5c1ee099037cac9ea64d425cd5b8d710906f6f2..85aa92ce26076059b10fd46ba0e80d0581f56db6 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::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 @@ fn early_callback(&mut self, } 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 efbe5e32fcd277d93fca84de8e8fbaacf93c6c88..f849b0a441084bbe577995fe009f835ba9984a67 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1278,7 +1278,7 @@ fn compile_test(&self) -> ProcRes { 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 => {