diff --git a/src/eval.rs b/src/eval.rs index cf4f7d689a..6d5ddf9593 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -21,6 +21,7 @@ use rustc_target::spec::Os; use crate::concurrency::GenmcCtx; use crate::concurrency::thread::TlsAllocAction; use crate::diagnostics::report_leaks; +use crate::helpers::is_no_core; use crate::shims::{global_ctor, tls}; use crate::*; @@ -289,14 +290,20 @@ pub fn create_ecx<'tcx>( MiriMachine::new(config, layout_cx, genmc_ctx), ); - // Make sure we have MIR. We check MIR for some stable monomorphic function in libcore. - let sentinel = - helpers::try_resolve_path(tcx, &["core", "ascii", "escape_default"], Namespace::ValueNS); - if !matches!(sentinel, Some(s) if tcx.is_mir_available(s.def.def_id())) { - tcx.dcx().fatal( - "the current sysroot was built without `-Zalways-encode-mir`, or libcore seems missing.\n\ - Note that directly invoking the `miri` binary is not supported; please use `cargo miri` instead." + // Make sure we have MIR. We check MIR for some stable monomorphic function in libcore, except + // if the current crate is #![no_core] it's fine to be missing the usual items from libcore. + if !is_no_core(tcx) { + let sentinel = helpers::try_resolve_path( + tcx, + &["core", "ascii", "escape_default"], + Namespace::ValueNS, ); + if !matches!(sentinel, Some(s) if tcx.is_mir_available(s.def.def_id())) { + tcx.dcx().fatal( + "the current sysroot was built without `-Zalways-encode-mir`, or libcore seems missing.\n\ + Note that directly invoking the `miri` binary is not supported; please use `cargo miri` instead." + ); + } } // Compute argc and argv from `config.args`. diff --git a/src/helpers.rs b/src/helpers.rs index a40ad4b553..0b4611b3b1 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1089,6 +1089,11 @@ pub(crate) fn windows_check_buffer_size((success, len): (bool, u64)) -> u32 { } } +/// Check whether the local crate has the `#![no_core]` attribute. +pub fn is_no_core(tcx: TyCtxt<'_>) -> bool { + rustc_hir::find_attr!(tcx, crate, NoCore(..)) +} + /// We don't support 16-bit systems, so let's have ergonomic conversion from `u32` to `usize`. pub trait ToUsize { fn to_usize(self) -> usize; diff --git a/src/machine.rs b/src/machine.rs index 566a775b90..62ace26e93 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -40,6 +40,7 @@ use crate::concurrency::sync::SyncObj; use crate::concurrency::{ AllocDataRaceHandler, GenmcCtx, GenmcEvalContextExt as _, GlobalDataRaceHandler, weak_memory, }; +use crate::helpers::is_no_core; use crate::*; /// First real-time signal. @@ -731,7 +732,8 @@ impl<'tcx> MiriMachine<'tcx> { ); let threads = ThreadManager::new(config); let mut thread_cpu_affinity = FxHashMap::default(); - if matches!(&tcx.sess.target.os, Os::Linux | Os::FreeBsd | Os::Android) { + if matches!(&tcx.sess.target.os, Os::Linux | Os::FreeBsd | Os::Android) && !is_no_core(tcx) + { thread_cpu_affinity .insert(threads.active_thread(), CpuAffinityMask::new(&layout_cx, config.num_cpus)); } diff --git a/tests/pass/no_core.rs b/tests/pass/no_core.rs new file mode 100644 index 0000000000..0cbffcb1ae --- /dev/null +++ b/tests/pass/no_core.rs @@ -0,0 +1,22 @@ +//! Test that Miri is able to run no_core programs. +//! This ensures that we don't depend on any paths from core when no_core is set. + +#![no_std] +#![no_core] +#![no_main] +#![feature(rustc_attrs, no_core, lang_items, intrinsics)] +#![allow(internal_features)] + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "sized"] +pub trait Sized: MetaSized {} + +#[no_mangle] +fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +}