Skip to content

Commit 1c5d06e

Browse files
committed
Auto merge of rust-lang#2657 - mkroening:miri-alloc, r=RalfJung
Add miri_alloc, miri_dealloc `miri_alloc` and `miri_dealloc` are basically the same as `__rust_alloc` and `__rust_dealloc` respectively, but without the check for a global allocator. This should allow bootstrapping an allocator in environments, where no fundamental way of allocating memory is available (`no_std` + `alloc` in Miri).
2 parents a5e40f0 + 1e4a73c commit 1c5d06e

File tree

5 files changed

+84
-10
lines changed

5 files changed

+84
-10
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,15 @@ extern "Rust" {
568568
/// program) the contents of a section of program memory, as bytes. Bytes
569569
/// written using this function will emerge from the interpreter's stderr.
570570
fn miri_write_to_stderr(bytes: &[u8]);
571+
572+
/// Miri-provided extern function to allocate memory from the interpreter.
573+
///
574+
/// This is useful when no fundamental way of allocating memory is
575+
/// available, e.g. when using `no_std` + `alloc`.
576+
fn miri_alloc(size: usize, align: usize) -> *mut u8;
577+
578+
/// Miri-provided extern function to deallocate memory.
579+
fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
571580
}
572581
```
573582

src/concurrency/data_race.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,10 @@ impl VClockAlloc {
686686
let (alloc_timestamp, alloc_index) = match kind {
687687
// User allocated and stack memory should track allocation.
688688
MemoryKind::Machine(
689-
MiriMemoryKind::Rust | MiriMemoryKind::C | MiriMemoryKind::WinHeap,
689+
MiriMemoryKind::Rust
690+
| MiriMemoryKind::Miri
691+
| MiriMemoryKind::C
692+
| MiriMemoryKind::WinHeap,
690693
)
691694
| MemoryKind::Stack => {
692695
let (alloc_index, clocks) = global.current_thread_state(thread_mgr);

src/machine.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ impl VisitTags for FrameData<'_> {
7777
pub enum MiriMemoryKind {
7878
/// `__rust_alloc` memory.
7979
Rust,
80+
/// `miri_alloc` memory.
81+
Miri,
8082
/// `malloc` memory.
8183
C,
8284
/// Windows `HeapAlloc` memory.
@@ -110,7 +112,7 @@ impl MayLeak for MiriMemoryKind {
110112
fn may_leak(self) -> bool {
111113
use self::MiriMemoryKind::*;
112114
match self {
113-
Rust | C | WinHeap | Runtime => false,
115+
Rust | Miri | C | WinHeap | Runtime => false,
114116
Machine | Global | ExternStatic | Tls => true,
115117
}
116118
}
@@ -121,6 +123,7 @@ impl fmt::Display for MiriMemoryKind {
121123
use self::MiriMemoryKind::*;
122124
match self {
123125
Rust => write!(f, "Rust heap"),
126+
Miri => write!(f, "Miri bare-metal heap"),
124127
C => write!(f, "C heap"),
125128
WinHeap => write!(f, "Windows heap"),
126129
Machine => write!(f, "machine-managed memory"),

src/shims/foreign_items.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -513,22 +513,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
513513
}
514514

515515
// Rust allocation
516-
"__rust_alloc" => {
516+
"__rust_alloc" | "miri_alloc" => {
517517
let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
518518
let size = this.read_scalar(size)?.to_machine_usize(this)?;
519519
let align = this.read_scalar(align)?.to_machine_usize(this)?;
520520

521-
return this.emulate_allocator(Symbol::intern("__rg_alloc"), |this| {
521+
let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
522522
Self::check_alloc_request(size, align)?;
523523

524+
let memory_kind = match link_name.as_str() {
525+
"__rust_alloc" => MiriMemoryKind::Rust,
526+
"miri_alloc" => MiriMemoryKind::Miri,
527+
_ => unreachable!(),
528+
};
529+
524530
let ptr = this.allocate_ptr(
525531
Size::from_bytes(size),
526532
Align::from_bytes(align).unwrap(),
527-
MiriMemoryKind::Rust.into(),
533+
memory_kind.into(),
528534
)?;
529535

530536
this.write_pointer(ptr, dest)
531-
});
537+
};
538+
539+
match link_name.as_str() {
540+
"__rust_alloc" => return this.emulate_allocator(Symbol::intern("__rg_alloc"), default),
541+
"miri_alloc" => {
542+
default(this)?;
543+
return Ok(EmulateByNameResult::NeedsJumping);
544+
},
545+
_ => unreachable!(),
546+
}
532547
}
533548
"__rust_alloc_zeroed" => {
534549
let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
@@ -549,20 +564,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
549564
this.write_pointer(ptr, dest)
550565
});
551566
}
552-
"__rust_dealloc" => {
567+
"__rust_dealloc" | "miri_dealloc" => {
553568
let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
554569
let ptr = this.read_pointer(ptr)?;
555570
let old_size = this.read_scalar(old_size)?.to_machine_usize(this)?;
556571
let align = this.read_scalar(align)?.to_machine_usize(this)?;
557572

558-
return this.emulate_allocator(Symbol::intern("__rg_dealloc"), |this| {
573+
let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
574+
let memory_kind = match link_name.as_str() {
575+
"__rust_dealloc" => MiriMemoryKind::Rust,
576+
"miri_dealloc" => MiriMemoryKind::Miri,
577+
_ => unreachable!(),
578+
};
579+
559580
// No need to check old_size/align; we anyway check that they match the allocation.
560581
this.deallocate_ptr(
561582
ptr,
562583
Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
563-
MiriMemoryKind::Rust.into(),
584+
memory_kind.into(),
564585
)
565-
});
586+
};
587+
588+
match link_name.as_str() {
589+
"__rust_dealloc" => return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default),
590+
"miri_dealloc" => {
591+
default(this)?;
592+
return Ok(EmulateByNameResult::NeedsJumping);
593+
}
594+
_ => unreachable!(),
595+
}
566596
}
567597
"__rust_realloc" => {
568598
let [ptr, old_size, align, new_size] = this.check_shim(abi, Abi::Rust, link_name, args)?;

tests/pass/miri-alloc.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#![feature(lang_items, start)]
2+
#![no_std]
3+
// windows tls dtors go through libstd right now, thus this test
4+
// cannot pass. When windows tls dtors go through the special magic
5+
// windows linker section, we can run this test on windows again.
6+
//@ignore-target-windows: no-std not supported on Windows
7+
8+
extern "Rust" {
9+
fn miri_alloc(size: usize, align: usize) -> *mut u8;
10+
fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
11+
}
12+
13+
#[start]
14+
fn start(_: isize, _: *const *const u8) -> isize {
15+
unsafe {
16+
let ptr = miri_alloc(123, 1);
17+
core::ptr::write_bytes(ptr, 0u8, 123);
18+
miri_dealloc(ptr, 123, 1);
19+
}
20+
0
21+
}
22+
23+
#[panic_handler]
24+
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
25+
loop {}
26+
}
27+
28+
#[lang = "eh_personality"]
29+
fn eh_personality() {}

0 commit comments

Comments
 (0)