Skip to content

Commit ca0cc6b

Browse files
committed
Add a dummy codegen backend
This allows building a rustc capable of running the frontend without any backend present. While this may not seem all that useful, it allows running the frontend of rustc to report errors or running miri to interpret a program without any backend present. This is useful when you are trying to say run miri in the browser as upstream LLVM can't be compiled for wasm yet. Or to run rustc itself in miri like I did a while ago and caught some UB.
1 parent d1ed52b commit ca0cc6b

File tree

1 file changed

+59
-4
lines changed
  • compiler/rustc_interface/src

1 file changed

+59
-4
lines changed

compiler/rustc_interface/src/util.rs

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::any::Any;
12
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
23
use std::path::{Path, PathBuf};
34
use std::sync::atomic::{AtomicBool, Ordering};
@@ -6,13 +7,20 @@ use std::{env, thread};
67

78
use rustc_ast as ast;
89
use rustc_attr_parsing::{ShouldEmit, validate_attr};
10+
use rustc_codegen_ssa::back::archive::ArArchiveBuilderBuilder;
11+
use rustc_codegen_ssa::back::link::link_binary;
912
use rustc_codegen_ssa::traits::CodegenBackend;
13+
use rustc_codegen_ssa::{CodegenResults, CrateInfo};
14+
use rustc_data_structures::fx::FxIndexMap;
1015
use rustc_data_structures::jobserver::Proxy;
1116
use rustc_data_structures::sync;
1217
use rustc_errors::LintBuffer;
13-
use rustc_metadata::{DylibError, load_symbol_from_dylib};
14-
use rustc_middle::ty::CurrentGcx;
15-
use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, Sysroot, host_tuple};
18+
use rustc_metadata::{DylibError, EncodedMetadata, load_symbol_from_dylib};
19+
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
20+
use rustc_middle::ty::{CurrentGcx, TyCtxt};
21+
use rustc_session::config::{
22+
Cfg, CrateType, OutFileName, OutputFilenames, OutputTypes, Sysroot, host_tuple,
23+
};
1624
use rustc_session::output::{CRATE_TYPES, categorize_crate_type};
1725
use rustc_session::{EarlyDiagCtxt, Session, filesearch, lint};
1826
use rustc_span::edit_distance::find_best_match_for_name;
@@ -316,12 +324,13 @@ pub fn get_codegen_backend(
316324
let backend = backend_name
317325
.or(target.default_codegen_backend.as_deref())
318326
.or(option_env!("CFG_DEFAULT_CODEGEN_BACKEND"))
319-
.unwrap_or("llvm");
327+
.unwrap_or("dummy");
320328

321329
match backend {
322330
filename if filename.contains('.') => {
323331
load_backend_from_dylib(early_dcx, filename.as_ref())
324332
}
333+
"dummy" => || Box::new(DummyCodegenBackend),
325334
#[cfg(feature = "llvm")]
326335
"llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
327336
backend_name => get_codegen_sysroot(early_dcx, sysroot, backend_name),
@@ -334,6 +343,52 @@ pub fn get_codegen_backend(
334343
unsafe { load() }
335344
}
336345

346+
struct DummyCodegenBackend;
347+
348+
impl CodegenBackend for DummyCodegenBackend {
349+
fn locale_resource(&self) -> &'static str {
350+
""
351+
}
352+
353+
fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box<dyn Any> {
354+
Box::new(CodegenResults {
355+
modules: vec![],
356+
allocator_module: None,
357+
crate_info: CrateInfo::new(tcx, String::new()),
358+
})
359+
}
360+
361+
fn join_codegen(
362+
&self,
363+
ongoing_codegen: Box<dyn Any>,
364+
_sess: &Session,
365+
_outputs: &OutputFilenames,
366+
) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
367+
(*ongoing_codegen.downcast().unwrap(), FxIndexMap::default())
368+
}
369+
370+
fn link(
371+
&self,
372+
sess: &Session,
373+
codegen_results: CodegenResults,
374+
metadata: EncodedMetadata,
375+
outputs: &OutputFilenames,
376+
) {
377+
// JUSTIFICATION: TyCtxt no longer available here
378+
#[allow(rustc::bad_opt_access)]
379+
if sess.opts.crate_types.iter().any(|&crate_type| crate_type != CrateType::Rlib) {
380+
#[allow(rustc::untranslatable_diagnostic)]
381+
#[allow(rustc::diagnostic_outside_of_impl)]
382+
sess.dcx().fatal(format!(
383+
"crate type {} not supported by the dummy codegen backend",
384+
sess.opts.crate_types[0],
385+
));
386+
}
387+
388+
link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, metadata, outputs);
389+
}
390+
}
391+
337392
// This is used for rustdoc, but it uses similar machinery to codegen backend
338393
// loading, so we leave the code here. It is potentially useful for other tools
339394
// that want to invoke the rustc binary while linking to rustc as well.

0 commit comments

Comments
 (0)