diff --git a/Cargo.lock b/Cargo.lock index ec976b69016..b9f0753e2be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3541,6 +3541,7 @@ dependencies = [ "log", "rustc", "rustc_ast_pretty", + "rustc_codegen_ssa", "rustc_codegen_utils", "rustc_data_structures", "rustc_error_codes", diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 8091a748540..e189bea4a09 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -39,7 +39,7 @@ use syntax::expand::allocator::AllocatorKind; use rustc::dep_graph::DepGraph; use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; -use rustc::session::config::{OptLevel, OutputFilenames, PrintRequest}; +use rustc::session::config::{self, OptLevel, OutputFilenames, PrintRequest}; use rustc::session::Session; use rustc::ty::{self, TyCtxt}; use rustc::util::common::ErrorReported; @@ -308,7 +308,7 @@ impl CodegenBackend for LlvmCodegenBackend { let rlink_data = json::encode(&codegen_results).map_err(|err| { sess.fatal(&format!("failed to encode rlink: {}", err)); })?; - let rlink_file = outputs.with_extension("rlink"); + let rlink_file = outputs.with_extension(config::RLINK_EXT); fs::write(&rlink_file, rlink_data).map_err(|err| { sess.fatal(&format!("failed to write file {}: {}", rlink_file.display(), err)); })?; diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 7a5966269b3..5b185f9a8b6 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -26,6 +26,7 @@ rustc_mir = { path = "../librustc_mir" } rustc_parse = { path = "../librustc_parse" } rustc_plugin_impl = { path = "../librustc_plugin_impl" } rustc_save_analysis = { path = "../librustc_save_analysis" } +rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_error_codes = { path = "../librustc_error_codes" } rustc_interface = { path = "../librustc_interface" } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 019ff431bcb..17957a3aa77 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -31,25 +31,27 @@ use rustc::session::{config, DiagnosticOutput, Session}; use rustc::session::{early_error, early_warn}; use rustc::ty::TyCtxt; use rustc::util::common::ErrorReported; +use rustc_codegen_ssa::CodegenResults; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::profiling::print_time_passes_entry; use rustc_data_structures::sync::SeqCst; use rustc_errors::{registry::Registry, PResult}; use rustc_feature::{find_gated_cfg, UnstableFeatures}; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_interface::util::get_builtin_codegen_backend; +use rustc_interface::util::{collect_crate_types, get_builtin_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; use rustc_metadata::locator; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; -use rustc_serialize::json::ToJson; +use rustc_serialize::json::{self, ToJson}; use std::borrow::Cow; use std::cmp::max; use std::default::Default; use std::env; use std::ffi::OsString; +use std::fs; use std::io::{self, Read, Write}; use std::mem; use std::panic::{self, catch_unwind}; @@ -286,7 +288,8 @@ pub fn run_compiler( &matches, compiler.input(), ) - }); + }) + .and_then(|| RustcDefaultCalls::try_process_rlink(sess, compiler)); if should_stop == Compilation::Stop { return sess.compile_status(); @@ -593,6 +596,34 @@ fn show_content_with_pager(content: &String) { } impl RustcDefaultCalls { + fn process_rlink(sess: &Session, compiler: &interface::Compiler) -> Result<(), ErrorReported> { + if let Input::File(file) = compiler.input() { + // FIXME: #![crate_type] and #![crate_name] support not implemented yet + let attrs = vec![]; + sess.crate_types.set(collect_crate_types(sess, &attrs)); + let outputs = compiler.build_output_filenames(&sess, &attrs); + let rlink_data = fs::read_to_string(file).unwrap_or_else(|err| { + sess.fatal(&format!("failed to read rlink file: {}", err)); + }); + let codegen_results: CodegenResults = json::decode(&rlink_data).unwrap_or_else(|err| { + sess.fatal(&format!("failed to decode rlink: {}", err)); + }); + compiler.codegen_backend().link(&sess, Box::new(codegen_results), &outputs) + } else { + sess.fatal(&format!("rlink must be a file")) + } + } + + pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation { + if sess.opts.debugging_opts.link_only { + let result = RustcDefaultCalls::process_rlink(sess, compiler); + abort_on_err(result, sess); + Compilation::Stop + } else { + Compilation::Continue + } + } + pub fn list_metadata( sess: &Session, metadata_loader: &dyn MetadataLoader, @@ -668,7 +699,7 @@ impl RustcDefaultCalls { println!("{}", id); continue; } - let crate_types = rustc_interface::util::collect_crate_types(sess, attrs); + let crate_types = collect_crate_types(sess, attrs); for &style in &crate_types { let fname = rustc_codegen_utils::link::filename_for_input( sess, style, &id, &t_outputs, diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 2a667541ad3..e213a4d33a6 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -2,7 +2,7 @@ pub use crate::passes::BoxedResolver; use crate::util; use rustc::lint; -use rustc::session::config::{self, ErrorOutputType, Input}; +use rustc::session::config::{self, ErrorOutputType, Input, OutputFilenames}; use rustc::session::early_error; use rustc::session::{DiagnosticOutput, Session}; use rustc::ty; @@ -20,7 +20,7 @@ use rustc_span::source_map::{FileLoader, FileName, SourceMap}; use std::path::PathBuf; use std::result; use std::sync::{Arc, Mutex}; -use syntax::ast::MetaItemKind; +use syntax::ast::{self, MetaItemKind}; use syntax::token; pub type Result = result::Result; @@ -61,6 +61,19 @@ impl Compiler { pub fn output_file(&self) -> &Option { &self.output_file } + pub fn build_output_filenames( + &self, + sess: &Session, + attrs: &[ast::Attribute], + ) -> OutputFilenames { + util::build_output_filenames( + &self.input, + &self.output_dir, + &self.output_file, + &attrs, + &sess, + ) + } } /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`. diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index 813d14d616d..c23071205a2 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -467,6 +467,7 @@ pub struct OutputFilenames { impl_stable_hash_via_hash!(OutputFilenames); +pub const RLINK_EXT: &str = "rlink"; pub const RUST_CGU_EXT: &str = "rcgu"; impl OutputFilenames { diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index be0e668a467..1c30d0340b7 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -968,4 +968,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "use Windows Control Flow Guard (`disabled`, `nochecks` or `checks`)"), no_link: bool = (false, parse_bool, [TRACKED], "compile without linking"), + link_only: bool = (false, parse_bool, [TRACKED], + "link the `.rlink` file generated by `-Z no-link`"), }