Skip to content

Commit 11f1486

Browse files
authored
Unrolled build for #149323
Rollup merge of #149323 - bjorn3:miri_llvm_target_config, r=RalfJung Use cg_llvm's target_config in miri Fixes #149314 r? `@RalfJung`
2 parents 10776a4 + 57b57b8 commit 11f1486

File tree

5 files changed

+125
-67
lines changed

5 files changed

+125
-67
lines changed

compiler/rustc_interface/src/interface.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc_session::parse::ParseSess;
2424
use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint};
2525
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
2626
use rustc_span::{FileName, sym};
27+
use rustc_target::spec::Target;
2728
use tracing::trace;
2829

2930
use crate::util;
@@ -385,7 +386,7 @@ pub struct Config {
385386
/// custom driver where the custom codegen backend has arbitrary data."
386387
/// (See #102759.)
387388
pub make_codegen_backend:
388-
Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>,
389+
Option<Box<dyn FnOnce(&config::Options, &Target) -> Box<dyn CodegenBackend> + Send>>,
389390

390391
/// Registry of diagnostics codes.
391392
pub registry: Registry,
@@ -453,7 +454,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
453454
Some(make_codegen_backend) => {
454455
// N.B. `make_codegen_backend` takes precedence over
455456
// `target.default_codegen_backend`, which is ignored in this case.
456-
make_codegen_backend(&config.opts)
457+
make_codegen_backend(&config.opts, &target)
457458
}
458459
};
459460

compiler/rustc_interface/src/util.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ pub fn get_codegen_backend(
339339
filename if filename.contains('.') => {
340340
load_backend_from_dylib(early_dcx, filename.as_ref())
341341
}
342-
"dummy" => || Box::new(DummyCodegenBackend),
342+
"dummy" => || Box::new(DummyCodegenBackend { target_config_override: None }),
343343
#[cfg(feature = "llvm")]
344344
"llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
345345
backend_name => get_codegen_sysroot(early_dcx, sysroot, backend_name),
@@ -352,7 +352,9 @@ pub fn get_codegen_backend(
352352
unsafe { load() }
353353
}
354354

355-
struct DummyCodegenBackend;
355+
pub struct DummyCodegenBackend {
356+
pub target_config_override: Option<Box<dyn Fn(&Session) -> TargetConfig>>,
357+
}
356358

357359
impl CodegenBackend for DummyCodegenBackend {
358360
fn locale_resource(&self) -> &'static str {
@@ -364,6 +366,10 @@ impl CodegenBackend for DummyCodegenBackend {
364366
}
365367

366368
fn target_config(&self, sess: &Session) -> TargetConfig {
369+
if let Some(target_config_override) = &self.target_config_override {
370+
return target_config_override(sess);
371+
}
372+
367373
let abi_required_features = sess.target.abi_required_features();
368374
let (target_features, unstable_target_features) = cfg_target_feature::<0>(
369375
sess,

src/tools/miri/src/bin/miri.rs

Lines changed: 98 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
// The rustc crates we need
1212
extern crate rustc_abi;
13+
extern crate rustc_codegen_ssa;
1314
extern crate rustc_data_structures;
1415
extern crate rustc_driver;
1516
extern crate rustc_hir;
@@ -19,6 +20,7 @@ extern crate rustc_log;
1920
extern crate rustc_middle;
2021
extern crate rustc_session;
2122
extern crate rustc_span;
23+
extern crate rustc_target;
2224

2325
/// See docs in https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc/src/main.rs
2426
/// and https://github.com/rust-lang/rust/pull/146627 for why we need this.
@@ -36,19 +38,22 @@ use std::num::{NonZero, NonZeroI32};
3638
use std::ops::Range;
3739
use std::rc::Rc;
3840
use std::str::FromStr;
41+
use std::sync::Once;
3942
use std::sync::atomic::{AtomicU32, Ordering};
4043

4144
use miri::{
4245
BacktraceStyle, BorrowTrackerMethod, GenmcConfig, GenmcCtx, MiriConfig, MiriEntryFnType,
4346
ProvenanceMode, TreeBorrowsParams, ValidationMode, run_genmc_mode,
4447
};
4548
use rustc_abi::ExternAbi;
49+
use rustc_codegen_ssa::traits::CodegenBackend;
4650
use rustc_data_structures::sync::{self, DynSync};
4751
use rustc_driver::Compilation;
4852
use rustc_hir::def_id::LOCAL_CRATE;
4953
use rustc_hir::{self as hir, Node};
5054
use rustc_hir_analysis::check::check_function_signature;
5155
use rustc_interface::interface::Config;
56+
use rustc_interface::util::DummyCodegenBackend;
5257
use rustc_log::tracing::debug;
5358
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
5459
use rustc_middle::middle::exported_symbols::{
@@ -58,8 +63,9 @@ use rustc_middle::query::LocalCrate;
5863
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
5964
use rustc_middle::ty::{self, Ty, TyCtxt};
6065
use rustc_session::EarlyDiagCtxt;
61-
use rustc_session::config::{CrateType, ErrorOutputType, OptLevel};
66+
use rustc_session::config::{CrateType, ErrorOutputType, OptLevel, Options};
6267
use rustc_span::def_id::DefId;
68+
use rustc_target::spec::Target;
6369

6470
use crate::log::setup::{deinit_loggers, init_early_loggers, init_late_loggers};
6571

@@ -161,7 +167,31 @@ fn run_many_seeds(
161167
}
162168
}
163169

170+
/// Generates the codegen backend for code that Miri will interpret: we basically
171+
/// use the dummy backend, except that we put the LLVM backend in charge of
172+
/// target features.
173+
fn make_miri_codegen_backend(opts: &Options, target: &Target) -> Box<dyn CodegenBackend> {
174+
let early_dcx = EarlyDiagCtxt::new(opts.error_format);
175+
176+
// Use the target_config method of the default codegen backend (eg LLVM) to ensure the
177+
// calculated target features match said backend by respecting eg -Ctarget-cpu.
178+
let target_config_backend =
179+
rustc_interface::util::get_codegen_backend(&early_dcx, &opts.sysroot, None, &target);
180+
let target_config_backend_init = Once::new();
181+
182+
Box::new(DummyCodegenBackend {
183+
target_config_override: Some(Box::new(move |sess| {
184+
target_config_backend_init.call_once(|| target_config_backend.init(sess));
185+
target_config_backend.target_config(sess)
186+
})),
187+
})
188+
}
189+
164190
impl rustc_driver::Callbacks for MiriCompilerCalls {
191+
fn config(&mut self, config: &mut rustc_interface::interface::Config) {
192+
config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend));
193+
}
194+
165195
fn after_analysis<'tcx>(
166196
&mut self,
167197
_: &rustc_interface::interface::Compiler,
@@ -244,11 +274,20 @@ struct MiriBeRustCompilerCalls {
244274
impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
245275
#[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint
246276
fn config(&mut self, config: &mut Config) {
247-
if config.opts.prints.is_empty() && self.target_crate {
277+
if !self.target_crate {
278+
// For a host crate, we fully behave like rustc.
279+
return;
280+
}
281+
// For a target crate, we emit an rlib that Miri can later consume.
282+
config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend));
283+
284+
// Avoid warnings about unsupported crate types. However, only do that we we are *not* being
285+
// queried by cargo about the supported crate types so that cargo still receives the
286+
// warnings it expects.
287+
if config.opts.prints.is_empty() {
248288
#[allow(rustc::bad_opt_access)] // tcx does not exist yet
249289
{
250290
let any_crate_types = !config.opts.crate_types.is_empty();
251-
// Avoid warnings about unsupported crate types.
252291
config
253292
.opts
254293
.crate_types
@@ -259,66 +298,63 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
259298
assert!(!config.opts.crate_types.is_empty());
260299
}
261300
}
262-
263-
// Queries overridden here affect the data stored in `rmeta` files of dependencies,
264-
// which will be used later in non-`MIRI_BE_RUSTC` mode.
265-
config.override_queries = Some(|_, local_providers| {
266-
// We need to add #[used] symbols to exported_symbols for `lookup_link_section`.
267-
// FIXME handle this somehow in rustc itself to avoid this hack.
268-
local_providers.exported_non_generic_symbols = |tcx, LocalCrate| {
269-
let reachable_set = tcx.with_stable_hashing_context(|hcx| {
270-
tcx.reachable_set(()).to_sorted(&hcx, true)
271-
});
272-
tcx.arena.alloc_from_iter(
273-
// This is based on:
274-
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L62-L63
275-
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L174
276-
reachable_set.into_iter().filter_map(|&local_def_id| {
277-
// Do the same filtering that rustc does:
278-
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L84-L102
279-
// Otherwise it may cause unexpected behaviours and ICEs
280-
// (https://github.com/rust-lang/rust/issues/86261).
281-
let is_reachable_non_generic = matches!(
282-
tcx.hir_node_by_def_id(local_def_id),
283-
Node::Item(&hir::Item {
284-
kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn{ .. },
285-
..
286-
}) | Node::ImplItem(&hir::ImplItem {
287-
kind: hir::ImplItemKind::Fn(..),
288-
..
289-
})
290-
if !tcx.generics_of(local_def_id).requires_monomorphization(tcx)
291-
);
292-
if !is_reachable_non_generic {
293-
return None;
294-
}
295-
let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id);
296-
if codegen_fn_attrs.contains_extern_indicator()
297-
|| codegen_fn_attrs
298-
.flags
299-
.contains(CodegenFnAttrFlags::USED_COMPILER)
300-
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
301-
{
302-
Some((
303-
ExportedSymbol::NonGeneric(local_def_id.to_def_id()),
304-
// Some dummy `SymbolExportInfo` here. We only use
305-
// `exported_symbols` in shims/foreign_items.rs and the export info
306-
// is ignored.
307-
SymbolExportInfo {
308-
level: SymbolExportLevel::C,
309-
kind: SymbolExportKind::Text,
310-
used: false,
311-
rustc_std_internal_symbol: false,
312-
},
313-
))
314-
} else {
315-
None
316-
}
317-
}),
318-
)
319-
}
320-
});
321301
}
302+
303+
// Queries overridden here affect the data stored in `rmeta` files of dependencies,
304+
// which will be used later in non-`MIRI_BE_RUSTC` mode.
305+
config.override_queries = Some(|_, local_providers| {
306+
// We need to add #[used] symbols to exported_symbols for `lookup_link_section`.
307+
// FIXME handle this somehow in rustc itself to avoid this hack.
308+
local_providers.exported_non_generic_symbols = |tcx, LocalCrate| {
309+
let reachable_set = tcx
310+
.with_stable_hashing_context(|hcx| tcx.reachable_set(()).to_sorted(&hcx, true));
311+
tcx.arena.alloc_from_iter(
312+
// This is based on:
313+
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L62-L63
314+
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L174
315+
reachable_set.into_iter().filter_map(|&local_def_id| {
316+
// Do the same filtering that rustc does:
317+
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L84-L102
318+
// Otherwise it may cause unexpected behaviours and ICEs
319+
// (https://github.com/rust-lang/rust/issues/86261).
320+
let is_reachable_non_generic = matches!(
321+
tcx.hir_node_by_def_id(local_def_id),
322+
Node::Item(&hir::Item {
323+
kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn{ .. },
324+
..
325+
}) | Node::ImplItem(&hir::ImplItem {
326+
kind: hir::ImplItemKind::Fn(..),
327+
..
328+
})
329+
if !tcx.generics_of(local_def_id).requires_monomorphization(tcx)
330+
);
331+
if !is_reachable_non_generic {
332+
return None;
333+
}
334+
let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id);
335+
if codegen_fn_attrs.contains_extern_indicator()
336+
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
337+
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
338+
{
339+
Some((
340+
ExportedSymbol::NonGeneric(local_def_id.to_def_id()),
341+
// Some dummy `SymbolExportInfo` here. We only use
342+
// `exported_symbols` in shims/foreign_items.rs and the export info
343+
// is ignored.
344+
SymbolExportInfo {
345+
level: SymbolExportLevel::C,
346+
kind: SymbolExportKind::Text,
347+
used: false,
348+
rustc_std_internal_symbol: false,
349+
},
350+
))
351+
} else {
352+
None
353+
}
354+
}),
355+
)
356+
}
357+
});
322358
}
323359

324360
fn after_analysis<'tcx>(

src/tools/miri/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ 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",
169168
"--cfg=miri",
170169
"-Zalways-encode-mir",
171170
"-Zextra-const-ub-checks",
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Test that target-cpu implies the correct target features
2+
//@only-target: x86_64
3+
//@compile-flags: -C target-cpu=x86-64-v4
4+
5+
fn main() {
6+
assert!(cfg!(target_feature = "avx2"));
7+
assert!(cfg!(target_feature = "avx512bw"));
8+
assert!(cfg!(target_feature = "avx512cd"));
9+
assert!(cfg!(target_feature = "avx512dq"));
10+
assert!(cfg!(target_feature = "avx512f"));
11+
assert!(cfg!(target_feature = "avx512vl"));
12+
assert!(is_x86_feature_detected!("avx512bw"));
13+
14+
assert!(cfg!(not(target_feature = "avx512vpopcntdq")));
15+
assert!(!is_x86_feature_detected!("avx512vpopcntdq"));
16+
}

0 commit comments

Comments
 (0)