Skip to content

Commit ac1e234

Browse files
committed
[WIP] Use the dummy codegen backend
This allows getting rid of all the argument mangling hacks as well as the exported_non_generic_symbols override hack by doing cargo build instead of cargo check. This is also a prerequisite for using native jit mode support in miri that I hope to add to rustc in the future to be used with cg_clif too. Currently this still has two issues: The dummy backend can't build dylibs, but cargo tries to build libstd as dylib. And required target features are not set by the dummy backend. Both of these require rustc side changes.
1 parent d88cfbc commit ac1e234

File tree

4 files changed

+9
-137
lines changed

4 files changed

+9
-137
lines changed

cargo-miri/src/phases.rs

Lines changed: 5 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,6 @@ fn show_version() {
5252
println!();
5353
}
5454

55-
fn forward_patched_extern_arg(args: &mut impl Iterator<Item = String>, cmd: &mut Command) {
56-
cmd.arg("--extern"); // always forward flag, but adjust filename:
57-
let path = args.next().expect("`--extern` should be followed by a filename");
58-
if let Some(lib) = path.strip_suffix(".rlib") {
59-
// If this is an rlib, make it an rmeta.
60-
cmd.arg(format!("{lib}.rmeta"));
61-
} else {
62-
// Some other extern file (e.g. a `.so`). Forward unchanged.
63-
cmd.arg(path);
64-
}
65-
}
66-
6755
pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
6856
// Require a subcommand before any flags.
6957
// We cannot know which of those flags take arguments and which do not,
@@ -407,7 +395,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
407395
assert_eq!(val, "metadata");
408396
} else {
409397
// For all other kinds of tests, we can just add our flag.
410-
cmd.arg("--emit=metadata");
398+
cmd.arg("--emit=metadata,link");
411399
}
412400

413401
// Alter the `-o` parameter so that it does not overwrite the JSON file we stored above.
@@ -444,7 +432,6 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
444432
}
445433

446434
let mut cmd = miri();
447-
let mut emit_link_hack = false;
448435
// Arguments are treated very differently depending on whether this crate is
449436
// for interpretation by Miri, or for use by a build script / proc macro.
450437
if target_crate {
@@ -455,7 +442,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
455442
}
456443

457444
// Forward arguments, but patched.
458-
let emit_flag = "--emit";
445+
459446
// This hack helps bootstrap run standard library tests in Miri. The issue is as follows:
460447
// when running `cargo miri test` on libcore, cargo builds a local copy of core and makes it
461448
// a dependency of the integration test crate. This copy duplicates all the lang items, so
@@ -472,29 +459,6 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
472459
&& !runnable_crate
473460
&& phase == RustcPhase::Build;
474461
while let Some(arg) = args.next() {
475-
// Patch `--emit`: remove "link" from "--emit" to make this a check-only build.
476-
if let Some(val) = arg.strip_prefix(emit_flag) {
477-
// Patch this argument. First, extract its value.
478-
let val =
479-
val.strip_prefix('=').expect("`cargo` should pass `--emit=X` as one argument");
480-
let mut val: Vec<_> = val.split(',').collect();
481-
// Now make sure "link" is not in there, but "metadata" is.
482-
if let Some(i) = val.iter().position(|&s| s == "link") {
483-
emit_link_hack = true;
484-
val.remove(i);
485-
if !val.contains(&"metadata") {
486-
val.push("metadata");
487-
}
488-
}
489-
cmd.arg(format!("{emit_flag}={}", val.join(",")));
490-
continue;
491-
}
492-
// Patch `--extern` filenames, since Cargo sometimes passes stub `.rlib` files:
493-
// https://github.com/rust-lang/miri/issues/1705
494-
if arg == "--extern" {
495-
forward_patched_extern_arg(&mut args, &mut cmd);
496-
continue;
497-
}
498462
// If the REPLACE_LIBRS hack is enabled and we are building a `lib.rs` file, and a
499463
// `lib.miri.rs` file exists, then build that instead.
500464
if replace_librs {
@@ -543,17 +507,6 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
543507
eprintln!("[cargo-miri rustc] target_crate={target_crate} runnable_crate={runnable_crate}");
544508
}
545509

546-
// Create a stub .rlib file if "link" was requested by cargo.
547-
// This is necessary to prevent cargo from doing rebuilds all the time.
548-
if emit_link_hack {
549-
for filename in out_filenames() {
550-
if verbose > 0 {
551-
eprintln!("[cargo-miri rustc] creating fake lib file at `{}`", filename.display());
552-
}
553-
File::create(filename).expect("failed to create fake lib file");
554-
}
555-
}
556-
557510
debug_cmd("[cargo-miri rustc]", verbose, &cmd);
558511
exec(cmd);
559512
}
@@ -624,17 +577,12 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
624577
cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
625578
}
626579
// Forward rustc arguments.
627-
// We need to patch "--extern" filenames because we forced a check-only
628-
// build without cargo knowing about that: replace `.rlib` suffix by
629-
// `.rmeta`.
630-
// We also need to remove `--error-format` as cargo specifies that to be JSON,
580+
// We need to remove `--error-format` as cargo specifies that to be JSON,
631581
// but when we run here, cargo does not interpret the JSON any more. `--json`
632582
// then also needs to be dropped.
633583
let mut args = info.args.iter();
634584
while let Some(arg) = args.next() {
635-
if arg == "--extern" {
636-
forward_patched_extern_arg(&mut (&mut args).cloned(), &mut cmd);
637-
} else if let Some(suffix) = arg.strip_prefix("--error-format") {
585+
if let Some(suffix) = arg.strip_prefix("--error-format") {
638586
assert!(suffix.starts_with('='));
639587
// Drop this argument.
640588
} else if let Some(suffix) = arg.strip_prefix("--json") {
@@ -676,15 +624,7 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
676624
// of the old value into MIRI_ORIG_RUSTDOC. So that's what we have to invoke now.
677625
let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string());
678626
let mut cmd = Command::new(rustdoc);
679-
680-
while let Some(arg) = args.next() {
681-
if arg == "--extern" {
682-
// Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files.
683-
forward_patched_extern_arg(&mut args, &mut cmd);
684-
} else {
685-
cmd.arg(arg);
686-
}
687-
}
627+
cmd.args(args);
688628

689629
// Doctests of `proc-macro` crates (and their dependencies) are always built for the host,
690630
// so we are not able to run them in Miri.

cargo-miri/src/setup.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ pub fn setup(
160160

161161
// Do the build.
162162
let status = SysrootBuilder::new(&sysroot_dir, target)
163-
.build_mode(BuildMode::Check)
163+
.build_mode(BuildMode::Build)
164164
.rustc_version(rustc_version.clone())
165165
.sysroot_config(sysroot_config)
166166
.rustflags(rustflags)

src/bin/miri.rs

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,12 @@ use miri::{
3939
use rustc_abi::ExternAbi;
4040
use rustc_data_structures::sync;
4141
use rustc_driver::Compilation;
42+
use rustc_hir as hir;
4243
use rustc_hir::def_id::LOCAL_CRATE;
43-
use rustc_hir::{self as hir, Node};
4444
use rustc_hir_analysis::check::check_function_signature;
4545
use rustc_interface::interface::Config;
4646
use rustc_log::tracing::debug;
47-
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
48-
use rustc_middle::middle::exported_symbols::{
49-
ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
50-
};
51-
use rustc_middle::query::LocalCrate;
47+
use rustc_middle::middle::exported_symbols::ExportedSymbol;
5248
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
5349
use rustc_middle::ty::{self, Ty, TyCtxt};
5450
use rustc_middle::util::Providers;
@@ -250,71 +246,6 @@ struct MiriBeRustCompilerCalls {
250246
}
251247

252248
impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
253-
#[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint
254-
fn config(&mut self, config: &mut Config) {
255-
if config.opts.prints.is_empty() && self.target_crate {
256-
// Queries overridden here affect the data stored in `rmeta` files of dependencies,
257-
// which will be used later in non-`MIRI_BE_RUSTC` mode.
258-
config.override_queries = Some(|_, local_providers| {
259-
// `exported_non_generic_symbols` and `reachable_non_generics` provided by rustc always returns
260-
// an empty result if `tcx.sess.opts.output_types.should_codegen()` is false.
261-
// In addition we need to add #[used] symbols to exported_symbols for `lookup_link_section`.
262-
local_providers.exported_non_generic_symbols = |tcx, LocalCrate| {
263-
let reachable_set = tcx.with_stable_hashing_context(|hcx| {
264-
tcx.reachable_set(()).to_sorted(&hcx, true)
265-
});
266-
tcx.arena.alloc_from_iter(
267-
// This is based on:
268-
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L62-L63
269-
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L174
270-
reachable_set.into_iter().filter_map(|&local_def_id| {
271-
// Do the same filtering that rustc does:
272-
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L84-L102
273-
// Otherwise it may cause unexpected behaviours and ICEs
274-
// (https://github.com/rust-lang/rust/issues/86261).
275-
let is_reachable_non_generic = matches!(
276-
tcx.hir_node_by_def_id(local_def_id),
277-
Node::Item(&hir::Item {
278-
kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn{ .. },
279-
..
280-
}) | Node::ImplItem(&hir::ImplItem {
281-
kind: hir::ImplItemKind::Fn(..),
282-
..
283-
})
284-
if !tcx.generics_of(local_def_id).requires_monomorphization(tcx)
285-
);
286-
if !is_reachable_non_generic {
287-
return None;
288-
}
289-
let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id);
290-
if codegen_fn_attrs.contains_extern_indicator()
291-
|| codegen_fn_attrs
292-
.flags
293-
.contains(CodegenFnAttrFlags::USED_COMPILER)
294-
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
295-
{
296-
Some((
297-
ExportedSymbol::NonGeneric(local_def_id.to_def_id()),
298-
// Some dummy `SymbolExportInfo` here. We only use
299-
// `exported_symbols` in shims/foreign_items.rs and the export info
300-
// is ignored.
301-
SymbolExportInfo {
302-
level: SymbolExportLevel::C,
303-
kind: SymbolExportKind::Text,
304-
used: false,
305-
rustc_std_internal_symbol: false,
306-
},
307-
))
308-
} else {
309-
None
310-
}
311-
}),
312-
)
313-
}
314-
});
315-
}
316-
}
317-
318249
fn after_analysis<'tcx>(
319250
&mut self,
320251
_: &rustc_interface::interface::Compiler,

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ pub use crate::shims::unwind::{CatchUnwindData, EvalContextExt as _};
165165
/// Also disable the MIR pass that inserts an alignment check on every pointer dereference. Miri
166166
/// does that too, and with a better error message.
167167
pub const MIRI_DEFAULT_ARGS: &[&str] = &[
168+
"-Zcodegen-backend=dummy",
168169
"--cfg=miri",
169170
"-Zalways-encode-mir",
170171
"-Zextra-const-ub-checks",

0 commit comments

Comments
 (0)