mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Rollup merge of #77795 - bjorn3:codegen_backend_interface_refactor, r=oli-obk
Codegen backend interface refactor This moves several things away from the codegen backend to rustc_interface. There are a few behavioral changes where previously the incremental cache (incorrectly) wouldn't get finalized, but now it does. See the individual commit messages.
This commit is contained in:
commit
17ee28b71f
@ -6,7 +6,7 @@ use rustc_codegen_ssa::traits::*;
|
|||||||
use rustc_data_structures::const_cstr;
|
use rustc_data_structures::const_cstr;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use rustc_middle::ty::layout::HasTyCtxt;
|
use rustc_middle::ty::layout::HasTyCtxt;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
@ -367,23 +367,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide_both(providers: &mut Providers) {
|
||||||
use rustc_codegen_ssa::target_features::{all_known_features, supported_target_features};
|
|
||||||
providers.supported_target_features = |tcx, cnum| {
|
|
||||||
assert_eq!(cnum, LOCAL_CRATE);
|
|
||||||
if tcx.sess.opts.actually_rustdoc {
|
|
||||||
// rustdoc needs to be able to document functions that use all the features, so
|
|
||||||
// provide them all.
|
|
||||||
all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
|
|
||||||
} else {
|
|
||||||
supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
provide_extern(providers);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn provide_extern(providers: &mut Providers) {
|
|
||||||
providers.wasm_import_module_map = |tcx, cnum| {
|
providers.wasm_import_module_map = |tcx, cnum| {
|
||||||
// Build up a map from DefId to a `NativeLib` structure, where
|
// Build up a map from DefId to a `NativeLib` structure, where
|
||||||
// `NativeLib` internally contains information about
|
// `NativeLib` internally contains information about
|
||||||
|
@ -23,18 +23,17 @@ use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
|
|||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_codegen_ssa::ModuleCodegen;
|
use rustc_codegen_ssa::ModuleCodegen;
|
||||||
use rustc_codegen_ssa::{CodegenResults, CompiledModule};
|
use rustc_codegen_ssa::{CodegenResults, CompiledModule};
|
||||||
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{ErrorReported, FatalError, Handler};
|
use rustc_errors::{ErrorReported, FatalError, Handler};
|
||||||
use rustc_middle::dep_graph::{DepGraph, WorkProduct};
|
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||||
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
|
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_serialize::json;
|
use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest};
|
||||||
use rustc_session::config::{self, OptLevel, OutputFilenames, PrintRequest};
|
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fs;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
mod back {
|
mod back {
|
||||||
@ -252,11 +251,11 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn provide(&self, providers: &mut ty::query::Providers) {
|
fn provide(&self, providers: &mut ty::query::Providers) {
|
||||||
attributes::provide(providers);
|
attributes::provide_both(providers);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn provide_extern(&self, providers: &mut ty::query::Providers) {
|
fn provide_extern(&self, providers: &mut ty::query::Providers) {
|
||||||
attributes::provide_extern(providers);
|
attributes::provide_both(providers);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_crate<'tcx>(
|
fn codegen_crate<'tcx>(
|
||||||
@ -277,47 +276,27 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||||||
&self,
|
&self,
|
||||||
ongoing_codegen: Box<dyn Any>,
|
ongoing_codegen: Box<dyn Any>,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
dep_graph: &DepGraph,
|
) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> {
|
||||||
) -> Result<Box<dyn Any>, ErrorReported> {
|
|
||||||
let (codegen_results, work_products) = ongoing_codegen
|
let (codegen_results, work_products) = ongoing_codegen
|
||||||
.downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<LlvmCodegenBackend>>()
|
.downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<LlvmCodegenBackend>>()
|
||||||
.expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
|
.expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
|
||||||
.join(sess);
|
.join(sess);
|
||||||
if sess.opts.debugging_opts.incremental_info {
|
|
||||||
rustc_codegen_ssa::back::write::dump_incremental_data(&codegen_results);
|
|
||||||
}
|
|
||||||
|
|
||||||
sess.time("serialize_work_products", move || {
|
sess.time("llvm_dump_timing_file", || {
|
||||||
rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
|
if sess.opts.debugging_opts.llvm_time_trace {
|
||||||
|
llvm_util::time_trace_profiler_finish("llvm_timings.json");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
sess.compile_status()?;
|
Ok((codegen_results, work_products))
|
||||||
|
|
||||||
Ok(Box::new(codegen_results))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link(
|
fn link(
|
||||||
&self,
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
codegen_results: Box<dyn Any>,
|
codegen_results: CodegenResults,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
) -> Result<(), ErrorReported> {
|
) -> Result<(), ErrorReported> {
|
||||||
let codegen_results = codegen_results
|
|
||||||
.downcast::<CodegenResults>()
|
|
||||||
.expect("Expected CodegenResults, found Box<Any>");
|
|
||||||
|
|
||||||
if sess.opts.debugging_opts.no_link {
|
|
||||||
// FIXME: use a binary format to encode the `.rlink` file
|
|
||||||
let rlink_data = json::encode(&codegen_results).map_err(|err| {
|
|
||||||
sess.fatal(&format!("failed to encode rlink: {}", err));
|
|
||||||
})?;
|
|
||||||
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));
|
|
||||||
})?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the linker on any artifacts that resulted from the LLVM run.
|
// Run the linker on any artifacts that resulted from the LLVM run.
|
||||||
// This should produce either a finished executable or library.
|
// This should produce either a finished executable or library.
|
||||||
sess.time("link_crate", || {
|
sess.time("link_crate", || {
|
||||||
@ -334,16 +313,6 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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, codegen_results.crate_hash);
|
|
||||||
|
|
||||||
sess.time("llvm_dump_timing_file", || {
|
|
||||||
if sess.opts.debugging_opts.llvm_time_trace {
|
|
||||||
llvm_util::time_trace_profiler_finish("llvm_timings.json");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ use rustc_data_structures::fx::FxHashMap;
|
|||||||
use rustc_data_structures::profiling::SelfProfilerRef;
|
use rustc_data_structures::profiling::SelfProfilerRef;
|
||||||
use rustc_data_structures::profiling::TimingGuard;
|
use rustc_data_structures::profiling::TimingGuard;
|
||||||
use rustc_data_structures::profiling::VerboseTimingGuard;
|
use rustc_data_structures::profiling::VerboseTimingGuard;
|
||||||
use rustc_data_structures::svh::Svh;
|
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::emitter::Emitter;
|
use rustc_errors::emitter::Emitter;
|
||||||
use rustc_errors::{DiagnosticId, FatalError, Handler, Level};
|
use rustc_errors::{DiagnosticId, FatalError, Handler, Level};
|
||||||
@ -414,7 +413,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
|
|||||||
let sess = tcx.sess;
|
let sess = tcx.sess;
|
||||||
|
|
||||||
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
||||||
let crate_hash = tcx.crate_hash(LOCAL_CRATE);
|
|
||||||
let no_builtins = tcx.sess.contains_name(&tcx.hir().krate().item.attrs, sym::no_builtins);
|
let no_builtins = tcx.sess.contains_name(&tcx.hir().krate().item.attrs, sym::no_builtins);
|
||||||
let is_compiler_builtins =
|
let is_compiler_builtins =
|
||||||
tcx.sess.contains_name(&tcx.hir().krate().item.attrs, sym::compiler_builtins);
|
tcx.sess.contains_name(&tcx.hir().krate().item.attrs, sym::compiler_builtins);
|
||||||
@ -463,7 +461,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
|
|||||||
OngoingCodegen {
|
OngoingCodegen {
|
||||||
backend,
|
backend,
|
||||||
crate_name,
|
crate_name,
|
||||||
crate_hash,
|
|
||||||
metadata,
|
metadata,
|
||||||
windows_subsystem,
|
windows_subsystem,
|
||||||
linker_info,
|
linker_info,
|
||||||
@ -658,15 +655,6 @@ fn produce_final_output_artifacts(
|
|||||||
// These are used in linking steps and will be cleaned up afterward.
|
// These are used in linking steps and will be cleaned up afterward.
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump_incremental_data(_codegen_results: &CodegenResults) {
|
|
||||||
// FIXME(mw): This does not work at the moment because the situation has
|
|
||||||
// become more complicated due to incremental LTO. Now a CGU
|
|
||||||
// can have more than two caching states.
|
|
||||||
// println!("[incremental] Re-using {} out of {} modules",
|
|
||||||
// codegen_results.modules.iter().filter(|m| m.pre_existing).count(),
|
|
||||||
// codegen_results.modules.len());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum WorkItem<B: WriteBackendMethods> {
|
pub enum WorkItem<B: WriteBackendMethods> {
|
||||||
/// Optimize a newly codegened, totally unoptimized module.
|
/// Optimize a newly codegened, totally unoptimized module.
|
||||||
Optimize(ModuleCodegen<B::Module>),
|
Optimize(ModuleCodegen<B::Module>),
|
||||||
@ -1720,7 +1708,6 @@ impl SharedEmitterMain {
|
|||||||
pub struct OngoingCodegen<B: ExtraBackendMethods> {
|
pub struct OngoingCodegen<B: ExtraBackendMethods> {
|
||||||
pub backend: B,
|
pub backend: B,
|
||||||
pub crate_name: Symbol,
|
pub crate_name: Symbol,
|
||||||
pub crate_hash: Svh,
|
|
||||||
pub metadata: EncodedMetadata,
|
pub metadata: EncodedMetadata,
|
||||||
pub windows_subsystem: Option<String>,
|
pub windows_subsystem: Option<String>,
|
||||||
pub linker_info: LinkerInfo,
|
pub linker_info: LinkerInfo,
|
||||||
@ -1766,7 +1753,6 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
|
|||||||
(
|
(
|
||||||
CodegenResults {
|
CodegenResults {
|
||||||
crate_name: self.crate_name,
|
crate_name: self.crate_name,
|
||||||
crate_hash: self.crate_hash,
|
|
||||||
metadata: self.metadata,
|
metadata: self.metadata,
|
||||||
windows_subsystem: self.windows_subsystem,
|
windows_subsystem: self.windows_subsystem,
|
||||||
linker_info: self.linker_info,
|
linker_info: self.linker_info,
|
||||||
|
@ -21,7 +21,6 @@ extern crate tracing;
|
|||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::svh::Svh;
|
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_hir::def_id::CrateNum;
|
use rustc_hir::def_id::CrateNum;
|
||||||
use rustc_hir::LangItem;
|
use rustc_hir::LangItem;
|
||||||
@ -134,7 +133,6 @@ pub struct CodegenResults {
|
|||||||
pub modules: Vec<CompiledModule>,
|
pub modules: Vec<CompiledModule>,
|
||||||
pub allocator_module: Option<CompiledModule>,
|
pub allocator_module: Option<CompiledModule>,
|
||||||
pub metadata_module: Option<CompiledModule>,
|
pub metadata_module: Option<CompiledModule>,
|
||||||
pub crate_hash: Svh,
|
|
||||||
pub metadata: rustc_middle::middle::cstore::EncodedMetadata,
|
pub metadata: rustc_middle::middle::cstore::EncodedMetadata,
|
||||||
pub windows_subsystem: Option<String>,
|
pub windows_subsystem: Option<String>,
|
||||||
pub linker_info: back::linker::LinkerInfo,
|
pub linker_info: back::linker::LinkerInfo,
|
||||||
@ -144,6 +142,7 @@ pub struct CodegenResults {
|
|||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
crate::back::symbol_export::provide(providers);
|
crate::back::symbol_export::provide(providers);
|
||||||
crate::base::provide_both(providers);
|
crate::base::provide_both(providers);
|
||||||
|
crate::target_features::provide(providers);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn provide_extern(providers: &mut Providers) {
|
pub fn provide_extern(providers: &mut Providers) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use rustc_hir::def_id::LOCAL_CRATE;
|
||||||
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
@ -148,3 +150,16 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
|
|||||||
_ => &[],
|
_ => &[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
|
providers.supported_target_features = |tcx, cnum| {
|
||||||
|
assert_eq!(cnum, LOCAL_CRATE);
|
||||||
|
if tcx.sess.opts.actually_rustdoc {
|
||||||
|
// rustdoc needs to be able to document functions that use all the features, so
|
||||||
|
// whitelist them all
|
||||||
|
all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
|
||||||
|
} else {
|
||||||
|
supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use super::write::WriteBackendMethods;
|
use super::write::WriteBackendMethods;
|
||||||
use super::CodegenObject;
|
use super::CodegenObject;
|
||||||
use crate::ModuleCodegen;
|
use crate::{CodegenResults, ModuleCodegen};
|
||||||
|
|
||||||
use rustc_ast::expand::allocator::AllocatorKind;
|
use rustc_ast::expand::allocator::AllocatorKind;
|
||||||
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_middle::dep_graph::DepGraph;
|
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||||
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
|
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
|
||||||
use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
|
use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
@ -80,8 +81,7 @@ pub trait CodegenBackend {
|
|||||||
&self,
|
&self,
|
||||||
ongoing_codegen: Box<dyn Any>,
|
ongoing_codegen: Box<dyn Any>,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
dep_graph: &DepGraph,
|
) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported>;
|
||||||
) -> Result<Box<dyn Any>, ErrorReported>;
|
|
||||||
|
|
||||||
/// This is called on the returned `Box<dyn Any>` from `join_codegen`
|
/// This is called on the returned `Box<dyn Any>` from `join_codegen`
|
||||||
///
|
///
|
||||||
@ -91,7 +91,7 @@ pub trait CodegenBackend {
|
|||||||
fn link(
|
fn link(
|
||||||
&self,
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
codegen_results: Box<dyn Any>,
|
codegen_results: CodegenResults,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
) -> Result<(), ErrorReported>;
|
) -> Result<(), ErrorReported>;
|
||||||
}
|
}
|
||||||
|
@ -642,7 +642,7 @@ impl RustcDefaultCalls {
|
|||||||
let codegen_results: CodegenResults = json::decode(&rlink_data).unwrap_or_else(|err| {
|
let codegen_results: CodegenResults = json::decode(&rlink_data).unwrap_or_else(|err| {
|
||||||
sess.fatal(&format!("failed to decode rlink: {}", err));
|
sess.fatal(&format!("failed to decode rlink: {}", err));
|
||||||
});
|
});
|
||||||
compiler.codegen_backend().link(&sess, Box::new(codegen_results), &outputs)
|
compiler.codegen_backend().link(&sess, codegen_results, &outputs)
|
||||||
} else {
|
} else {
|
||||||
sess.fatal("rlink must be a file")
|
sess.fatal("rlink must be a file")
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ use crate::passes::{self, BoxedResolver, QueryContext};
|
|||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||||
|
use rustc_data_structures::svh::Svh;
|
||||||
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
|
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_hir::def_id::LOCAL_CRATE;
|
use rustc_hir::def_id::LOCAL_CRATE;
|
||||||
@ -13,7 +14,8 @@ use rustc_middle::arena::Arena;
|
|||||||
use rustc_middle::dep_graph::DepGraph;
|
use rustc_middle::dep_graph::DepGraph;
|
||||||
use rustc_middle::ty::steal::Steal;
|
use rustc_middle::ty::steal::Steal;
|
||||||
use rustc_middle::ty::{GlobalCtxt, ResolverOutputs, TyCtxt};
|
use rustc_middle::ty::{GlobalCtxt, ResolverOutputs, TyCtxt};
|
||||||
use rustc_session::config::{OutputFilenames, OutputType};
|
use rustc_serialize::json;
|
||||||
|
use rustc_session::config::{self, OutputFilenames, OutputType};
|
||||||
use rustc_session::{output::find_crate_name, Session};
|
use rustc_session::{output::find_crate_name, Session};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
@ -331,6 +333,7 @@ impl<'tcx> Queries<'tcx> {
|
|||||||
pub fn linker(&'tcx self) -> Result<Linker> {
|
pub fn linker(&'tcx self) -> Result<Linker> {
|
||||||
let dep_graph = self.dep_graph()?;
|
let dep_graph = self.dep_graph()?;
|
||||||
let prepare_outputs = self.prepare_outputs()?;
|
let prepare_outputs = self.prepare_outputs()?;
|
||||||
|
let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE));
|
||||||
let ongoing_codegen = self.ongoing_codegen()?;
|
let ongoing_codegen = self.ongoing_codegen()?;
|
||||||
|
|
||||||
let sess = self.session().clone();
|
let sess = self.session().clone();
|
||||||
@ -340,6 +343,7 @@ impl<'tcx> Queries<'tcx> {
|
|||||||
sess,
|
sess,
|
||||||
dep_graph: dep_graph.peek().clone(),
|
dep_graph: dep_graph.peek().clone(),
|
||||||
prepare_outputs: prepare_outputs.take(),
|
prepare_outputs: prepare_outputs.take(),
|
||||||
|
crate_hash,
|
||||||
ongoing_codegen: ongoing_codegen.take(),
|
ongoing_codegen: ongoing_codegen.take(),
|
||||||
codegen_backend,
|
codegen_backend,
|
||||||
})
|
})
|
||||||
@ -350,18 +354,31 @@ pub struct Linker {
|
|||||||
sess: Lrc<Session>,
|
sess: Lrc<Session>,
|
||||||
dep_graph: DepGraph,
|
dep_graph: DepGraph,
|
||||||
prepare_outputs: OutputFilenames,
|
prepare_outputs: OutputFilenames,
|
||||||
|
crate_hash: Svh,
|
||||||
ongoing_codegen: Box<dyn Any>,
|
ongoing_codegen: Box<dyn Any>,
|
||||||
codegen_backend: Lrc<Box<dyn CodegenBackend>>,
|
codegen_backend: Lrc<Box<dyn CodegenBackend>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Linker {
|
impl Linker {
|
||||||
pub fn link(self) -> Result<()> {
|
pub fn link(self) -> Result<()> {
|
||||||
let codegen_results =
|
let (codegen_results, work_products) =
|
||||||
self.codegen_backend.join_codegen(self.ongoing_codegen, &self.sess, &self.dep_graph)?;
|
self.codegen_backend.join_codegen(self.ongoing_codegen, &self.sess)?;
|
||||||
let prof = self.sess.prof.clone();
|
|
||||||
|
self.sess.compile_status()?;
|
||||||
|
|
||||||
|
let sess = &self.sess;
|
||||||
let dep_graph = self.dep_graph;
|
let dep_graph = self.dep_graph;
|
||||||
|
sess.time("serialize_work_products", || {
|
||||||
|
rustc_incremental::save_work_product_index(&sess, &dep_graph, work_products)
|
||||||
|
});
|
||||||
|
|
||||||
|
let prof = self.sess.prof.clone();
|
||||||
prof.generic_activity("drop_dep_graph").run(move || drop(dep_graph));
|
prof.generic_activity("drop_dep_graph").run(move || drop(dep_graph));
|
||||||
|
|
||||||
|
// 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(&self.sess, self.crate_hash);
|
||||||
|
|
||||||
if !self
|
if !self
|
||||||
.sess
|
.sess
|
||||||
.opts
|
.opts
|
||||||
@ -371,6 +388,19 @@ impl Linker {
|
|||||||
{
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sess.opts.debugging_opts.no_link {
|
||||||
|
// FIXME: use a binary format to encode the `.rlink` file
|
||||||
|
let rlink_data = json::encode(&codegen_results).map_err(|err| {
|
||||||
|
sess.fatal(&format!("failed to encode rlink: {}", err));
|
||||||
|
})?;
|
||||||
|
let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT);
|
||||||
|
std::fs::write(&rlink_file, rlink_data).map_err(|err| {
|
||||||
|
sess.fatal(&format!("failed to write file {}: {}", rlink_file.display(), err));
|
||||||
|
})?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
self.codegen_backend.link(&self.sess, codegen_results, &self.prepare_outputs)
|
self.codegen_backend.link(&self.sess, codegen_results, &self.prepare_outputs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
extern crate rustc_codegen_ssa;
|
extern crate rustc_codegen_ssa;
|
||||||
extern crate rustc_errors;
|
extern crate rustc_errors;
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
#[macro_use]
|
|
||||||
extern crate rustc_data_structures;
|
extern crate rustc_data_structures;
|
||||||
extern crate rustc_driver;
|
extern crate rustc_driver;
|
||||||
extern crate rustc_hir;
|
extern crate rustc_hir;
|
||||||
@ -12,17 +11,19 @@ extern crate rustc_span;
|
|||||||
extern crate rustc_symbol_mangling;
|
extern crate rustc_symbol_mangling;
|
||||||
extern crate rustc_target;
|
extern crate rustc_target;
|
||||||
|
|
||||||
|
use rustc_codegen_ssa::back::linker::LinkerInfo;
|
||||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||||
use rustc_data_structures::owning_ref::OwningRef;
|
use rustc_codegen_ssa::{CodegenResults, CrateInfo};
|
||||||
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::sync::MetadataRef;
|
use rustc_data_structures::sync::MetadataRef;
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_middle::dep_graph::DepGraph;
|
use rustc_middle::dep_graph::DepGraph;
|
||||||
|
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||||
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn};
|
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn};
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::config::OutputFilenames;
|
use rustc_session::config::OutputFilenames;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::Symbol;
|
|
||||||
use rustc_target::spec::Target;
|
use rustc_target::spec::Target;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -31,14 +32,11 @@ pub struct NoLlvmMetadataLoader;
|
|||||||
|
|
||||||
impl MetadataLoader for NoLlvmMetadataLoader {
|
impl MetadataLoader for NoLlvmMetadataLoader {
|
||||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> {
|
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> {
|
||||||
let buf =
|
unreachable!("some_crate.rs shouldn't depend on any external crates");
|
||||||
std::fs::read(filename).map_err(|e| format!("metadata file open err: {:?}", e))?;
|
|
||||||
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf);
|
|
||||||
Ok(rustc_erase_owner!(buf.map_owner_box()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String> {
|
fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String> {
|
||||||
self.get_rlib_metadata(target, filename)
|
unreachable!("some_crate.rs shouldn't depend on any external crates");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,53 +47,49 @@ impl CodegenBackend for TheBackend {
|
|||||||
Box::new(NoLlvmMetadataLoader)
|
Box::new(NoLlvmMetadataLoader)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn provide(&self, providers: &mut Providers) {
|
fn provide(&self, providers: &mut Providers) {}
|
||||||
rustc_symbol_mangling::provide(providers);
|
fn provide_extern(&self, providers: &mut Providers) {}
|
||||||
|
|
||||||
providers.supported_target_features = |tcx, _cnum| {
|
|
||||||
Default::default() // Just a dummy
|
|
||||||
};
|
|
||||||
providers.is_reachable_non_generic = |_tcx, _defid| true;
|
|
||||||
providers.exported_symbols = |_tcx, _crate| &[];
|
|
||||||
}
|
|
||||||
|
|
||||||
fn provide_extern(&self, providers: &mut Providers) {
|
|
||||||
providers.is_reachable_non_generic = |_tcx, _defid| true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn codegen_crate<'a, 'tcx>(
|
fn codegen_crate<'a, 'tcx>(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
_metadata: EncodedMetadata,
|
metadata: EncodedMetadata,
|
||||||
_need_metadata_module: bool,
|
_need_metadata_module: bool,
|
||||||
) -> Box<dyn Any> {
|
) -> Box<dyn Any> {
|
||||||
use rustc_hir::def_id::LOCAL_CRATE;
|
use rustc_hir::def_id::LOCAL_CRATE;
|
||||||
|
|
||||||
Box::new(tcx.crate_name(LOCAL_CRATE) as Symbol)
|
Box::new(CodegenResults {
|
||||||
|
crate_name: tcx.crate_name(LOCAL_CRATE),
|
||||||
|
modules: vec![],
|
||||||
|
allocator_module: None,
|
||||||
|
metadata_module: None,
|
||||||
|
metadata,
|
||||||
|
windows_subsystem: None,
|
||||||
|
linker_info: LinkerInfo::new(tcx),
|
||||||
|
crate_info: CrateInfo::new(tcx),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn join_codegen(
|
fn join_codegen(
|
||||||
&self,
|
&self,
|
||||||
ongoing_codegen: Box<dyn Any>,
|
ongoing_codegen: Box<dyn Any>,
|
||||||
_sess: &Session,
|
_sess: &Session,
|
||||||
_dep_graph: &DepGraph,
|
) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> {
|
||||||
) -> Result<Box<dyn Any>, ErrorReported> {
|
let codegen_results = ongoing_codegen
|
||||||
let crate_name = ongoing_codegen
|
.downcast::<CodegenResults>()
|
||||||
.downcast::<Symbol>()
|
.expect("in join_codegen: ongoing_codegen is not a CodegenResults");
|
||||||
.expect("in join_codegen: ongoing_codegen is not a Symbol");
|
Ok((*codegen_results, FxHashMap::default()))
|
||||||
Ok(crate_name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link(
|
fn link(
|
||||||
&self,
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
codegen_results: Box<dyn Any>,
|
codegen_results: CodegenResults,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
) -> Result<(), ErrorReported> {
|
) -> Result<(), ErrorReported> {
|
||||||
use rustc_session::{config::CrateType, output::out_filename};
|
use rustc_session::{config::CrateType, output::out_filename};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
let crate_name =
|
let crate_name = codegen_results.crate_name;
|
||||||
codegen_results.downcast::<Symbol>().expect("in link: codegen_results is not a Symbol");
|
|
||||||
for &crate_type in sess.opts.crate_types.iter() {
|
for &crate_type in sess.opts.crate_types.iter() {
|
||||||
if crate_type != CrateType::Rlib {
|
if crate_type != CrateType::Rlib {
|
||||||
sess.fatal(&format!("Crate type is {:?}", crate_type));
|
sess.fatal(&format!("Crate type is {:?}", crate_type));
|
||||||
|
Loading…
Reference in New Issue
Block a user