Skip to content

Commit 5ef299e

Browse files
committed
Auto merge of rust-lang#74681 - RalfJung:miri-extern-fn, r=oli-obk
Miri: use extern fn to expose interpreter operations to program; fix leak checker on Windows This PR realizes an idea that @oli-obk has been suggesting for a while: to use Miri-specific `extern` functions to provide some extra capabilities to the program. Initially, we have two of these methods, which libstd itself needs: * `miri_start_panic`, which replaces the intrinsic of the same name (mostly for consistency, to avoid having multiple mechanisms for Miri-specific functionality). * `miri_static_root`, which adds an allocation to a list of static "roots" that Miri considers as not having leaked (including all memory reachable through them). This is needed for rust-lang/miri#1302. We use `extern` functions instead of intrinsics for this so that user code can more easily call these Miri hoolks -- e.g. `miri_static_root` should be useful for rust-lang/miri#1318. The Miri side of this is at rust-lang/miri#1485. r? @oli-obk
2 parents d8cf749 + 67b4f3b commit 5ef299e

File tree

7 files changed

+27
-23
lines changed

7 files changed

+27
-23
lines changed

src/libcore/intrinsics.rs

-8
Original file line numberDiff line numberDiff line change
@@ -1947,14 +1947,6 @@ extern "rust-intrinsic" {
19471947
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
19481948
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
19491949

1950-
/// Internal hook used by Miri to implement unwinding.
1951-
/// ICEs when encountered during non-Miri codegen.
1952-
///
1953-
/// The `payload` ptr here will be exactly the one `do_catch` gets passed by `try`.
1954-
///
1955-
/// Perma-unstable: do not use.
1956-
pub fn miri_start_panic(payload: *mut u8) -> !;
1957-
19581950
/// Internal placeholder for injecting code coverage counters when the "instrument-coverage"
19591951
/// option is enabled. The placeholder is replaced with `llvm.instrprof.increment` during code
19601952
/// generation.

src/libpanic_unwind/miri.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,16 @@ use core::any::Any;
66
// Must be pointer-sized.
77
type Payload = Box<Box<dyn Any + Send>>;
88

9+
extern "Rust" {
10+
/// Miri-provided extern function to begin unwinding.
11+
fn miri_start_panic(payload: *mut u8) -> !;
12+
}
13+
914
pub unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 {
1015
// The payload we pass to `miri_start_panic` will be exactly the argument we get
1116
// in `cleanup` below. So we just box it up once, to get something pointer-sized.
1217
let payload_box: Payload = Box::new(payload);
13-
core::intrinsics::miri_start_panic(Box::into_raw(payload_box) as *mut u8)
18+
miri_start_panic(Box::into_raw(payload_box) as *mut u8)
1419
}
1520

1621
pub unsafe fn cleanup(payload_box: *mut u8) -> Box<dyn Any + Send> {

src/librustc_codegen_ssa/mir/block.rs

-5
Original file line numberDiff line numberDiff line change
@@ -606,11 +606,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
606606
return;
607607
}
608608

609-
// For normal codegen, this Miri-specific intrinsic should never occur.
610-
if intrinsic == Some(sym::miri_start_panic) {
611-
bug!("`miri_start_panic` should never end up in compiled code");
612-
}
613-
614609
if self.codegen_panic_intrinsic(
615610
&helper,
616611
&mut bx,

src/librustc_mir/interpret/memory.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -716,14 +716,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
716716
}
717717
}
718718

719-
pub fn leak_report(&self) -> usize {
719+
/// Print leaked memory. Allocations reachable from `static_roots` or a `Global` allocation
720+
/// are not considered leaked. Leaks whose kind `may_leak()` returns true are not reported.
721+
pub fn leak_report(&self, static_roots: &[AllocId]) -> usize {
720722
// Collect the set of allocations that are *reachable* from `Global` allocations.
721723
let reachable = {
722724
let mut reachable = FxHashSet::default();
723725
let global_kind = M::GLOBAL_KIND.map(MemoryKind::Machine);
724726
let mut todo: Vec<_> = self.alloc_map.filter_map_collect(move |&id, &(kind, _)| {
725727
if Some(kind) == global_kind { Some(id) } else { None }
726728
});
729+
todo.extend(static_roots);
727730
while let Some(id) = todo.pop() {
728731
if reachable.insert(id) {
729732
// This is a new allocation, add its relocations to `todo`.

src/librustc_span/symbol.rs

-1
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,6 @@ symbols! {
677677
minnumf32,
678678
minnumf64,
679679
mips_target_feature,
680-
miri_start_panic,
681680
mmx_target_feature,
682681
module,
683682
module_path,

src/librustc_typeck/check/intrinsic.rs

-6
Original file line numberDiff line numberDiff line change
@@ -379,12 +379,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
379379

380380
sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
381381

382-
sym::miri_start_panic => {
383-
// FIXME - the relevant types aren't lang items,
384-
// so it's not trivial to check this
385-
return;
386-
}
387-
388382
sym::count_code_region => {
389383
(0, vec![tcx.types.u64, tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit())
390384
}

src/libstd/sys/windows/thread_local_key.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,30 @@ struct Node {
110110
next: *mut Node,
111111
}
112112

113+
#[cfg(miri)]
114+
extern "Rust" {
115+
/// Miri-provided extern function to mark the block `ptr` points to as a "root"
116+
/// for some static memory. This memory and everything reachable by it is not
117+
/// considered leaking even if it still exists when the program terminates.
118+
///
119+
/// `ptr` has to point to the beginning of an allocated block.
120+
fn miri_static_root(ptr: *const u8);
121+
}
122+
113123
unsafe fn register_dtor(key: Key, dtor: Dtor) {
114124
let mut node = Box::new(Node { key, dtor, next: ptr::null_mut() });
115125

116126
let mut head = DTORS.load(SeqCst);
117127
loop {
118128
node.next = head;
119129
match DTORS.compare_exchange(head, &mut *node, SeqCst, SeqCst) {
120-
Ok(_) => return mem::forget(node),
130+
Ok(_) => {
131+
#[cfg(miri)]
132+
miri_static_root(&*node as *const _ as *const u8);
133+
134+
mem::forget(node);
135+
return;
136+
}
121137
Err(cur) => head = cur,
122138
}
123139
}

0 commit comments

Comments
 (0)