Skip to content

Commit 59f099e

Browse files
committed
Make ongoing_codegen a query
1 parent e29f8f1 commit 59f099e

File tree

10 files changed

+81
-63
lines changed

10 files changed

+81
-63
lines changed

src/librustc/query/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ rustc_queries! {
102102
desc { "running analysis passes on this crate" }
103103
}
104104

105+
query ongoing_codegen(_: CrateNum) -> Result<Lrc<ty::OngoingCodegen>, ErrorReported> {
106+
no_hash
107+
eval_always
108+
desc { "starting code generation" }
109+
}
110+
105111
/// Records the type of every item.
106112
query type_of(key: DefId) -> Ty<'tcx> {
107113
cache_on_disk_if { key.is_local() }

src/librustc/ty/context.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
5353
StableVec};
5454
use arena::SyncDroplessArena;
5555
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
56-
use rustc_data_structures::sync::{self, Lrc, Lock, WorkerLocal, AtomicOnce, Once};
56+
use rustc_data_structures::sync::{self, Lrc, Lock, WorkerLocal, AtomicOnce, Once, OneThread};
5757
use std::any::Any;
5858
use std::borrow::Borrow;
5959
use std::cmp::Ordering;
@@ -1016,6 +1016,9 @@ pub struct GlobalCtxt<'tcx> {
10161016

10171017
pub sess_rc: Lrc<Session>,
10181018

1019+
// This stores a `Arc<dyn CodegenBackend + Send + Sync>`.
1020+
pub codegen_backend: Box<dyn Any + Send + Sync>,
1021+
10191022
lowered_hir: AtomicOnce<&'tcx hir::LoweredHir>,
10201023
hir_map: AtomicOnce<&'tcx hir_map::Map<'tcx>>,
10211024

@@ -1056,6 +1059,7 @@ pub struct GlobalCtxt<'tcx> {
10561059
/// when satisfying the query for a particular codegen unit. Internally in
10571060
/// the query it'll send data along this channel to get processed later.
10581061
pub tx_to_llvm_workers: Lock<mpsc::Sender<Box<dyn Any + Send>>>,
1062+
pub rx_to_llvm_workers: Steal<OneThread<mpsc::Receiver<Box<dyn Any + Send>>>>,
10591063
}
10601064

10611065
impl<'tcx> TyCtxt<'tcx> {
@@ -1188,7 +1192,7 @@ impl<'tcx> TyCtxt<'tcx> {
11881192
extern_providers: ty::query::Providers<'tcx>,
11891193
arenas: &'tcx AllArenas,
11901194
crate_name: Option<String>,
1191-
tx: mpsc::Sender<Box<dyn Any + Send>>,
1195+
codegen_backend: Box<dyn Any + Send + Sync>,
11921196
io: InputsAndOutputs,
11931197
) -> GlobalCtxt<'tcx> {
11941198
let data_layout = TargetDataLayout::parse(&s.target.target).unwrap_or_else(|err| {
@@ -1207,13 +1211,15 @@ impl<'tcx> TyCtxt<'tcx> {
12071211
let max_cnum = cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0);
12081212
let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1);
12091213
providers[LOCAL_CRATE] = local_providers;
1214+
let (tx, rx) = mpsc::channel();
12101215

12111216
GlobalCtxt {
12121217
sess: &**s,
12131218
arena: WorkerLocal::new(|_| Arena::default()),
12141219
cstore,
12151220
cstore_rc,
12161221
sess_rc: s.clone(),
1222+
codegen_backend,
12171223
interners,
12181224
dep_graph: AtomicOnce::new(),
12191225
common,
@@ -1237,6 +1243,7 @@ impl<'tcx> TyCtxt<'tcx> {
12371243
allocation_interner: Default::default(),
12381244
alloc_map: Lock::new(interpret::AllocMap::new()),
12391245
tx_to_llvm_workers: Lock::new(tx),
1246+
rx_to_llvm_workers: Steal::new(OneThread::new(rx)),
12401247
io,
12411248
}
12421249
}

src/librustc/ty/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@ use crate::mir::Body;
2121
use crate::mir::interpret::{GlobalId, ErrorHandled};
2222
use crate::mir::GeneratorLayout;
2323
use crate::session::CrateDisambiguator;
24+
use crate::session::config::OutputFilenames;
25+
use crate::dep_graph::DepGraph;
2426
use crate::traits::{self, Reveal};
2527
use crate::ty;
2628
use crate::ty::layout::VariantIdx;
2729
use crate::ty::subst::{Subst, InternalSubsts, SubstsRef};
2830
use crate::ty::util::{IntTypeExt, Discr};
2931
use crate::ty::walk::TypeWalker;
32+
use crate::ty::steal::Steal;
3033
use crate::util::captures::Captures;
3134
use crate::util::nodemap::{NodeSet, DefIdMap, FxHashMap};
3235
use arena::SyncDroplessArena;
@@ -39,6 +42,7 @@ use std::fmt;
3942
use std::hash::{Hash, Hasher};
4043
use std::ops::Deref;
4144
use std::any::Any;
45+
use std::sync::Arc;
4246
use rustc_data_structures::sync::{self, Lrc, OneThread, ParallelIterator, par_iter};
4347
use std::slice;
4448
use std::{mem, ptr};
@@ -122,6 +126,12 @@ mod sty;
122126

123127
// Data types
124128

129+
pub struct OngoingCodegen {
130+
pub outputs: Arc<OutputFilenames>,
131+
pub dep_graph: DepGraph,
132+
pub codegen_object: Steal<OneThread<Box<dyn Any>>>,
133+
}
134+
125135
pub struct PluginInfo {
126136
pub syntax_exts: Vec<NamedSyntaxExtension>,
127137
pub attributes: Vec<(Symbol, AttributeType)>,

src/librustc_codegen_llvm/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ unsafe impl Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
212212
unsafe impl Sync for LlvmCodegenBackend {}
213213

214214
impl LlvmCodegenBackend {
215-
pub fn new() -> Box<dyn CodegenBackend> {
216-
box LlvmCodegenBackend(())
215+
pub fn new() -> Arc<dyn CodegenBackend + Send + Sync> {
216+
Arc::new(LlvmCodegenBackend(()))
217217
}
218218
}
219219

@@ -349,7 +349,7 @@ impl CodegenBackend for LlvmCodegenBackend {
349349

350350
/// This is the entrypoint for a hot plugged rustc_codegen_llvm
351351
#[no_mangle]
352-
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
352+
pub fn __rustc_codegen_backend() -> Arc<dyn CodegenBackend + Send + Sync> {
353353
LlvmCodegenBackend::new()
354354
}
355355

src/librustc_driver/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ pub fn run_compiler(
192192
return;
193193
}
194194
let should_stop = RustcDefaultCalls::print_crate_info(
195-
&***compiler.codegen_backend(),
195+
&**compiler.codegen_backend(),
196196
compiler.session(),
197197
None,
198198
&odir,
@@ -246,7 +246,7 @@ pub fn run_compiler(
246246
interface::run_compiler(config, |compiler| {
247247
let sess = compiler.session();
248248
let should_stop = RustcDefaultCalls::print_crate_info(
249-
&***compiler.codegen_backend(),
249+
&**compiler.codegen_backend(),
250250
sess,
251251
Some(compiler.input()),
252252
compiler.output_dir(),

src/librustc_interface/interface.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub type Result<T> = result::Result<T, ErrorReported>;
2828
/// Created by passing `Config` to `run_compiler`.
2929
pub struct Compiler {
3030
pub(crate) sess: Lrc<Session>,
31-
codegen_backend: Lrc<Box<dyn CodegenBackend>>,
31+
codegen_backend: Arc<dyn CodegenBackend + Send + Sync>,
3232
source_map: Lrc<SourceMap>,
3333
pub(crate) io: InputsAndOutputs,
3434
pub(crate) queries: Queries,
@@ -40,7 +40,7 @@ impl Compiler {
4040
pub fn session(&self) -> &Lrc<Session> {
4141
&self.sess
4242
}
43-
pub fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
43+
pub fn codegen_backend(&self) -> &Arc<dyn CodegenBackend + Send + Sync> {
4444
&self.codegen_backend
4545
}
4646
pub fn cstore(&self) -> &Lrc<CStore> {

src/librustc_interface/passes.rs

+32-10
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,7 @@ fn load_query_result_cache<'tcx>(
906906
}
907907

908908
pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
909+
providers.ongoing_codegen = ongoing_codegen;
909910
providers.analysis = analysis;
910911
providers.hir_map = hir_map;
911912
providers.lower_ast_to_hir = lower_ast_to_hir;
@@ -963,7 +964,6 @@ impl BoxedGlobalCtxt {
963964
pub fn create_global_ctxt(
964965
compiler: &Compiler,
965966
io: InputsAndOutputs,
966-
tx: mpsc::Sender<Box<dyn Any + Send>>,
967967
) -> BoxedGlobalCtxt {
968968
let sess = compiler.session().clone();
969969
let cstore = compiler.cstore.clone();
@@ -985,6 +985,13 @@ pub fn create_global_ctxt(
985985
default_provide_extern(&mut extern_providers);
986986
codegen_backend.provide_extern(&mut extern_providers);
987987

988+
// Move the dyn Any coercion outside the generator to avoid lifetime issues
989+
fn codegen_backend_any(
990+
i: Arc<dyn CodegenBackend + Send + Sync>
991+
) -> Box<dyn Any + Send + Sync> {
992+
Box::new(i)
993+
}
994+
988995
let gcx = TyCtxt::create_global_ctxt(
989996
sess,
990997
&**cstore,
@@ -993,7 +1000,7 @@ pub fn create_global_ctxt(
9931000
extern_providers,
9941001
&arenas,
9951002
crate_name,
996-
tx,
1003+
codegen_backend_any(codegen_backend.clone()),
9971004
io,
9981005
);
9991006

@@ -1211,12 +1218,23 @@ fn encode_and_write_metadata(
12111218

12121219
/// Runs the codegen backend, after which the AST and analysis can
12131220
/// be discarded.
1214-
pub fn start_codegen<'tcx>(
1215-
codegen_backend: &dyn CodegenBackend,
1221+
fn ongoing_codegen<'tcx>(
12161222
tcx: TyCtxt<'tcx>,
1217-
rx: mpsc::Receiver<Box<dyn Any + Send>>,
1218-
outputs: &OutputFilenames,
1219-
) -> Box<dyn Any> {
1223+
cnum: CrateNum,
1224+
) -> Result<Lrc<ty::OngoingCodegen>> {
1225+
tcx.analysis(cnum)?;
1226+
1227+
assert_eq!(cnum, LOCAL_CRATE);
1228+
// Don't do code generation if there were any errors
1229+
tcx.sess.compile_status()?;
1230+
1231+
let outputs = tcx.prepare_outputs(())?;
1232+
1233+
let rx = OneThread::into_inner(tcx.rx_to_llvm_workers.steal());
1234+
let codegen_backend: &dyn Any = &*tcx.codegen_backend;
1235+
let codegen_backend = codegen_backend.downcast_ref::<Arc<dyn CodegenBackend + Send + Sync>>()
1236+
.unwrap();
1237+
12201238
if log_enabled!(::log::Level::Info) {
12211239
println!("Pre-codegen");
12221240
tcx.print_debug_stats();
@@ -1227,7 +1245,7 @@ pub fn start_codegen<'tcx>(
12271245
});
12281246

12291247
let (metadata, need_metadata_module) = time(tcx.sess, "metadata encoding and writing", || {
1230-
encode_and_write_metadata(tcx, outputs)
1248+
encode_and_write_metadata(tcx, &outputs)
12311249
});
12321250

12331251
tcx.sess.profiler(|p| p.start_activity("codegen crate"));
@@ -1242,11 +1260,15 @@ pub fn start_codegen<'tcx>(
12421260
}
12431261

12441262
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
1245-
if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, outputs) {
1263+
if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, &outputs) {
12461264
tcx.sess.err(&format!("could not emit MIR: {}", e));
12471265
tcx.sess.abort_if_errors();
12481266
}
12491267
}
12501268

1251-
codegen
1269+
Ok(Lrc::new(ty::OngoingCodegen {
1270+
outputs,
1271+
dep_graph: tcx.dep_graph().clone(),
1272+
codegen_object: Steal::new(OneThread::new(codegen)),
1273+
}))
12521274
}

src/librustc_interface/queries.rs

+9-36
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::interface::{Compiler, Result};
22
use crate::passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt};
33

4-
use rustc_data_structures::sync::{Lrc, Lock};
4+
use rustc_data_structures::sync::{Lrc, Lock, OneThread};
55
use rustc::session::config::{Input, OutputFilenames, OutputType};
66
use rustc::session::Session;
77
use rustc::util::common::{time, ErrorReported};
@@ -83,67 +83,40 @@ impl<T> Default for Query<T> {
8383

8484
#[derive(Default)]
8585
pub(crate) struct Queries {
86-
codegen_channel: Query<(Steal<mpsc::Sender<Box<dyn Any + Send>>>,
87-
Steal<mpsc::Receiver<Box<dyn Any + Send>>>)>,
8886
global_ctxt: Query<BoxedGlobalCtxt>,
89-
ongoing_codegen: Query<(Box<dyn Any>, Arc<OutputFilenames>, DepGraph)>,
87+
ongoing_codegen: Query<Lrc<ty::OngoingCodegen>>,
9088
link: Query<()>,
9189
}
9290

9391
impl Compiler {
94-
pub fn codegen_channel(&self) -> Result<&Query<(Steal<mpsc::Sender<Box<dyn Any + Send>>>,
95-
Steal<mpsc::Receiver<Box<dyn Any + Send>>>)>> {
96-
self.queries.codegen_channel.compute(|| {
97-
let (tx, rx) = mpsc::channel();
98-
Ok((Steal::new(tx), Steal::new(rx)))
99-
})
100-
}
101-
10292
pub fn global_ctxt(&self) -> Result<&Query<BoxedGlobalCtxt>> {
10393
self.queries.global_ctxt.compute(|| {
104-
let tx = self.codegen_channel()?.peek().0.steal();
10594
Ok(passes::create_global_ctxt(
10695
self,
10796
self.io.clone(),
108-
tx
10997
))
11098
})
11199
}
112100

113101
pub fn ongoing_codegen(
114102
&self
115-
) -> Result<&Query<(Box<dyn Any>, Arc<OutputFilenames>, DepGraph)>> {
103+
) -> Result<&Query<Lrc<ty::OngoingCodegen>>> {
116104
self.queries.ongoing_codegen.compute(|| {
117-
let rx = self.codegen_channel()?.peek().1.steal();
118105
self.global_ctxt()?.peek_mut().enter(|tcx| {
119-
tcx.analysis(LOCAL_CRATE).ok();
120-
121-
// Don't do code generation if there were any errors
122-
self.session().compile_status()?;
123-
124-
let outputs = tcx.prepare_outputs(())?;
125-
126-
Ok((passes::start_codegen(
127-
&***self.codegen_backend(),
128-
tcx,
129-
rx,
130-
&outputs,
131-
), outputs, tcx.dep_graph().clone()))
106+
tcx.ongoing_codegen(LOCAL_CRATE)
132107
})
133108
})
134109
}
135110

136111
pub fn link(&self) -> Result<&Query<()>> {
137112
self.queries.link.compute(|| {
138-
let sess = self.session();
139-
140-
let (ongoing_codegen, outputs, dep_graph) = self.ongoing_codegen()?.take();
113+
let ongoing_codegen = self.ongoing_codegen()?.take();
141114

142115
self.codegen_backend().join_codegen_and_link(
143-
ongoing_codegen,
144-
sess,
145-
&dep_graph,
146-
&outputs,
116+
OneThread::into_inner(ongoing_codegen.codegen_object.steal()),
117+
self.session(),
118+
&ongoing_codegen.dep_graph,
119+
&ongoing_codegen.outputs,
147120
).map_err(|_| ErrorReported)?;
148121

149122
Ok(())

src/librustc_interface/util.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub fn create_session(
8989
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
9090
input_path: Option<PathBuf>,
9191
lint_caps: FxHashMap<lint::LintId, lint::Level>,
92-
) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>, Lrc<SourceMap>) {
92+
) -> (Lrc<Session>, Arc<dyn CodegenBackend + Send + Sync>, Lrc<SourceMap>) {
9393
let descriptions = diagnostics_registry();
9494

9595
let loader = file_loader.unwrap_or(box RealFileLoader);
@@ -117,7 +117,7 @@ pub fn create_session(
117117
add_configuration(&mut cfg, &sess, &*codegen_backend);
118118
sess.parse_sess.config = cfg;
119119

120-
(Lrc::new(sess), Lrc::new(codegen_backend), source_map)
120+
(Lrc::new(sess), codegen_backend, source_map)
121121
}
122122

123123
// Temporarily have stack size set to 32MB to deal with various crates with long method
@@ -246,7 +246,7 @@ pub fn spawn_thread_pool<F: FnOnce() -> R + Send, R: Send>(
246246
})
247247
}
248248

249-
fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
249+
fn load_backend_from_dylib(path: &Path) -> fn() -> Arc<dyn CodegenBackend + Send + Sync> {
250250
let lib = DynamicLibrary::open(Some(path)).unwrap_or_else(|err| {
251251
let err = format!("couldn't load codegen backend {:?}: {:?}", path, err);
252252
early_error(ErrorOutputType::default(), &err);
@@ -267,10 +267,10 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
267267
}
268268
}
269269

270-
pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
270+
pub fn get_codegen_backend(sess: &Session) -> Arc<dyn CodegenBackend + Send + Sync> {
271271
static INIT: Once = Once::new();
272272

273-
static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
273+
static mut LOAD: fn() -> Arc<dyn CodegenBackend + Send + Sync> = || unreachable!();
274274

275275
INIT.call_once(|| {
276276
let codegen_name = sess.opts.debugging_opts.codegen_backend.as_ref()
@@ -291,7 +291,7 @@ pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
291291
backend
292292
}
293293

294-
pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
294+
pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Arc<dyn CodegenBackend + Send + Sync> {
295295
// For now we only allow this function to be called once as it'll dlopen a
296296
// few things, which seems to work best if we only do that once. In
297297
// general this assertion never trips due to the once guard in `get_codegen_backend`,

0 commit comments

Comments
 (0)