Skip to content

Commit f82083d

Browse files
committed
Revert some miri changes
1 parent 4405ce4 commit f82083d

File tree

7 files changed

+142
-17
lines changed

7 files changed

+142
-17
lines changed

library/alloc/src/alloc.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ use core::ptr::{self, NonNull};
1010

1111
unsafe extern "Rust" {
1212
// These are the magic symbols to call the global allocator. rustc generates
13-
// them to call the global allocator if there is a `#[global_allocator]` attribute
14-
// (the code expanding that attribute macro generates those functions), or to call
13+
// them to call `GLOBAL.alloc` etc. if there is a `#[global_allocator]` attribute
14+
// (the code expanding that attribute macro generates those functions), or if not
1515
// the default implementations in std (weak symbols in `library/std/src/alloc.rs`)
16-
// otherwise.
16+
// is used otherwise.
17+
// The rustc fork of LLVM 14 and earlier also special-cases these function names to
18+
// be able to optimize them like `malloc`, `realloc`, and `free`, respectively.
1719
#[rustc_allocator]
1820
#[rustc_nounwind]
1921
#[rustc_std_internal_symbol]

src/tools/miri/src/helpers.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
988988
return interp_ok(());
989989
}
990990

991+
if ["__rust_alloc", "__rust_alloc_zeroed", "__rust_realloc", "__rust_dealloc"]
992+
.contains(&link_name.as_str())
993+
{
994+
let attrs = self.eval_context_ref().tcx.codegen_fn_attrs(instance.def_id());
995+
if attrs
996+
.linkage
997+
.map_or(false, |linkage| linkage == rustc_middle::mir::mono::Linkage::WeakAny)
998+
&& attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
999+
{
1000+
// We intentionally intercept the allocator methods even though libstd provides
1001+
// default implementations.
1002+
return interp_ok(());
1003+
}
1004+
}
1005+
9911006
throw_machine_stop!(TerminationInfo::SymbolShimClashing {
9921007
link_name,
9931008
span: body.span.data(),

src/tools/miri/src/shims/alloc.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_abi::{Align, Size};
2+
use rustc_ast::expand::allocator::AllocatorKind;
23

34
use crate::*;
45

@@ -53,6 +54,34 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
5354
Align::from_bytes(prev_power_of_two(size)).unwrap()
5455
}
5556

57+
/// Emulates calling the internal __rust_* allocator functions
58+
fn emulate_allocator(
59+
&mut self,
60+
default: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx>,
61+
) -> InterpResult<'tcx, EmulateItemResult> {
62+
let this = self.eval_context_mut();
63+
64+
let Some(allocator_kind) = this.tcx.allocator_kind(()) else {
65+
// in real code, this symbol does not exist without an allocator
66+
return interp_ok(EmulateItemResult::NotSupported);
67+
};
68+
69+
match allocator_kind {
70+
AllocatorKind::Global => {
71+
// When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion
72+
// of this attribute. As such we have to call an exported Rust function,
73+
// and not execute any Miri shim. Somewhat unintuitively doing so is done
74+
// by returning `NotSupported`, which triggers the `lookup_exported_symbol`
75+
// fallback case in `emulate_foreign_item`.
76+
interp_ok(EmulateItemResult::NotSupported)
77+
}
78+
AllocatorKind::Default => {
79+
default(this)?;
80+
interp_ok(EmulateItemResult::NeedsReturn)
81+
}
82+
}
83+
}
84+
5685
fn malloc(&mut self, size: u64, init: AllocInit) -> InterpResult<'tcx, Pointer> {
5786
let this = self.eval_context_mut();
5887
let align = this.malloc_align(size);

src/tools/miri/src/shims/foreign_items.rs

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::hash_map::Entry;
22
use std::io::Write;
3+
use std::iter;
34
use std::path::Path;
45

56
use rustc_abi::{Align, AlignFromBytesError, CanonAbi, Size};
@@ -501,49 +502,127 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
501502
}
502503

503504
// Rust allocation
504-
"miri_alloc" => {
505+
"__rust_alloc" | "miri_alloc" => {
505506
let default = |ecx: &mut MiriInterpCx<'tcx>| {
506507
// Only call `check_shim` when `#[global_allocator]` isn't used. When that
507508
// macro is used, we act like no shim exists, so that the exported function can run.
508-
let [size, align] = ecx.check_shim(abi, CanonAbi::Rust, link_name, args)?;
509+
let [size, align] = ecx.check_shim(abi, Conv::Rust, link_name, args)?;
509510
let size = ecx.read_target_usize(size)?;
510511
let align = ecx.read_target_usize(align)?;
511512

512-
this.check_rustc_alloc_request(size, align)?;
513+
ecx.check_rustc_alloc_request(size, align)?;
514+
515+
let memory_kind = match link_name.as_str() {
516+
"__rust_alloc" => MiriMemoryKind::Rust,
517+
"miri_alloc" => MiriMemoryKind::Miri,
518+
_ => unreachable!(),
519+
};
513520

514521
let ptr = ecx.allocate_ptr(
515522
Size::from_bytes(size),
516523
Align::from_bytes(align).unwrap(),
517-
MiriMemoryKind::Miri.into(),
524+
memory_kind.into(),
518525
AllocInit::Uninit,
519526
)?;
520527

521528
ecx.write_pointer(ptr, dest)
522529
};
523530

524-
default(this)?;
525-
return interp_ok(EmulateItemResult::NeedsReturn);
531+
match link_name.as_str() {
532+
"__rust_alloc" => return this.emulate_allocator(default),
533+
"miri_alloc" => {
534+
default(this)?;
535+
return interp_ok(EmulateItemResult::NeedsReturn);
536+
}
537+
_ => unreachable!(),
538+
}
526539
}
527-
"miri_dealloc" => {
540+
"__rust_alloc_zeroed" => {
541+
return this.emulate_allocator(|this| {
542+
// See the comment for `__rust_alloc` why `check_shim` is only called in the
543+
// default case.
544+
let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
545+
let size = this.read_target_usize(size)?;
546+
let align = this.read_target_usize(align)?;
547+
548+
this.check_rustc_alloc_request(size, align)?;
549+
550+
let ptr = this.allocate_ptr(
551+
Size::from_bytes(size),
552+
Align::from_bytes(align).unwrap(),
553+
MiriMemoryKind::Rust.into(),
554+
AllocInit::Zero,
555+
)?;
556+
557+
// We just allocated this, the access is definitely in-bounds.
558+
this.write_bytes_ptr(
559+
ptr.into(),
560+
iter::repeat(0u8).take(usize::try_from(size).unwrap()),
561+
)
562+
.unwrap();
563+
this.write_pointer(ptr, dest)
564+
});
565+
}
566+
"__rust_dealloc" | "miri_dealloc" => {
528567
let default = |ecx: &mut MiriInterpCx<'tcx>| {
529568
// See the comment for `__rust_alloc` why `check_shim` is only called in the
530569
// default case.
531570
let [ptr, old_size, align] =
532-
ecx.check_shim(abi, CanonAbi::Rust, link_name, args)?;
571+
ecx.check_shim(abi, Conv::Rust, link_name, args)?;
533572
let ptr = ecx.read_pointer(ptr)?;
534573
let old_size = ecx.read_target_usize(old_size)?;
535574
let align = ecx.read_target_usize(align)?;
536575

576+
let memory_kind = match link_name.as_str() {
577+
"__rust_dealloc" => MiriMemoryKind::Rust,
578+
"miri_dealloc" => MiriMemoryKind::Miri,
579+
_ => unreachable!(),
580+
};
581+
537582
// No need to check old_size/align; we anyway check that they match the allocation.
538583
ecx.deallocate_ptr(
539584
ptr,
540585
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
541-
MiriMemoryKind::Miri.into(),
586+
memory_kind.into(),
542587
)
543588
};
544589

545-
default(this)?;
546-
return interp_ok(EmulateItemResult::NeedsReturn);
590+
match link_name.as_str() {
591+
"__rust_dealloc" => {
592+
return this.emulate_allocator(default);
593+
}
594+
"miri_dealloc" => {
595+
default(this)?;
596+
return interp_ok(EmulateItemResult::NeedsReturn);
597+
}
598+
_ => unreachable!(),
599+
}
600+
}
601+
"__rust_realloc" => {
602+
return this.emulate_allocator(|this| {
603+
// See the comment for `__rust_alloc` why `check_shim` is only called in the
604+
// default case.
605+
let [ptr, old_size, align, new_size] =
606+
this.check_shim(abi, Conv::Rust, link_name, args)?;
607+
let ptr = this.read_pointer(ptr)?;
608+
let old_size = this.read_target_usize(old_size)?;
609+
let align = this.read_target_usize(align)?;
610+
let new_size = this.read_target_usize(new_size)?;
611+
// No need to check old_size; we anyway check that they match the allocation.
612+
613+
this.check_rustc_alloc_request(new_size, align)?;
614+
615+
let align = Align::from_bytes(align).unwrap();
616+
let new_ptr = this.reallocate_ptr(
617+
ptr,
618+
Some((Size::from_bytes(old_size), align)),
619+
Size::from_bytes(new_size),
620+
align,
621+
MiriMemoryKind::Rust.into(),
622+
AllocInit::Uninit,
623+
)?;
624+
this.write_pointer(new_ptr, dest)
625+
});
547626
}
548627

549628
// C memory handling functions

src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | ABORT()
99
= note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
1010
= note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC
1111
= note: inside `std::alloc::rust_oom` at RUSTLIB/std/src/alloc.rs:LL:CC
12-
= note: inside `std::alloc::_::__rg_oom` at RUSTLIB/std/src/alloc.rs:LL:CC
12+
= note: inside `std::alloc::_::__rust_alloc_error_handler` at RUSTLIB/std/src/alloc.rs:LL:CC
1313
= note: inside `std::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1414
= note: inside `std::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1515
note: inside `main`

src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | core::intrinsics::abort();
77
|
88
= note: BACKTRACE:
99
= note: inside `alloc_error_handler` at tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC
10-
note: inside `_::__rg_oom`
10+
note: inside `_::__rust_alloc_error_handler`
1111
--> tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC
1212
|
1313
LL | #[alloc_error_handler]

src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | core::intrinsics::abort();
99
|
1010
= note: BACKTRACE:
1111
= note: inside `panic_handler` at tests/fail/alloc/alloc_error_handler_no_std.rs:LL:CC
12-
= note: inside `alloc::alloc::__alloc_error_handler::__rdl_oom` at RUSTLIB/alloc/src/alloc.rs:LL:CC
12+
= note: inside `alloc::alloc::__alloc_error_handler::__rust_alloc_error_handler` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1313
= note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1414
= note: inside `alloc::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1515
note: inside `miri_start`

0 commit comments

Comments
 (0)