about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/miri/README.md9
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs5
-rw-r--r--src/tools/miri/src/machine.rs5
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs46
-rw-r--r--src/tools/miri/tests/pass/miri-alloc.rs29
5 files changed, 84 insertions, 10 deletions
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 7ca58cb3f80..939d7b19fa9 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -568,6 +568,15 @@ extern "Rust" {
     /// program) the contents of a section of program memory, as bytes. Bytes
     /// written using this function will emerge from the interpreter's stderr.
     fn miri_write_to_stderr(bytes: &[u8]);
+
+    /// Miri-provided extern function to allocate memory from the interpreter.
+    /// 
+    /// This is useful when no fundamental way of allocating memory is
+    /// available, e.g. when using `no_std` + `alloc`.
+    fn miri_alloc(size: usize, align: usize) -> *mut u8;
+
+    /// Miri-provided extern function to deallocate memory.
+    fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
 }
 ```
 
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index 69514395bc9..b0f76646212 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -686,7 +686,10 @@ impl VClockAlloc {
         let (alloc_timestamp, alloc_index) = match kind {
             // User allocated and stack memory should track allocation.
             MemoryKind::Machine(
-                MiriMemoryKind::Rust | MiriMemoryKind::C | MiriMemoryKind::WinHeap,
+                MiriMemoryKind::Rust
+                | MiriMemoryKind::Miri
+                | MiriMemoryKind::C
+                | MiriMemoryKind::WinHeap,
             )
             | MemoryKind::Stack => {
                 let (alloc_index, clocks) = global.current_thread_state(thread_mgr);
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 231a99c1d03..9a822bb0849 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -77,6 +77,8 @@ impl VisitTags for FrameData<'_> {
 pub enum MiriMemoryKind {
     /// `__rust_alloc` memory.
     Rust,
+    /// `miri_alloc` memory.
+    Miri,
     /// `malloc` memory.
     C,
     /// Windows `HeapAlloc` memory.
@@ -110,7 +112,7 @@ impl MayLeak for MiriMemoryKind {
     fn may_leak(self) -> bool {
         use self::MiriMemoryKind::*;
         match self {
-            Rust | C | WinHeap | Runtime => false,
+            Rust | Miri | C | WinHeap | Runtime => false,
             Machine | Global | ExternStatic | Tls => true,
         }
     }
@@ -121,6 +123,7 @@ impl fmt::Display for MiriMemoryKind {
         use self::MiriMemoryKind::*;
         match self {
             Rust => write!(f, "Rust heap"),
+            Miri => write!(f, "Miri bare-metal heap"),
             C => write!(f, "C heap"),
             WinHeap => write!(f, "Windows heap"),
             Machine => write!(f, "machine-managed memory"),
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 1b3205aabc9..058f730833b 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -513,22 +513,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
 
             // Rust allocation
-            "__rust_alloc" => {
+            "__rust_alloc" | "miri_alloc" => {
                 let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
                 let size = this.read_scalar(size)?.to_machine_usize(this)?;
                 let align = this.read_scalar(align)?.to_machine_usize(this)?;
 
-                return this.emulate_allocator(Symbol::intern("__rg_alloc"), |this| {
+                let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
                     Self::check_alloc_request(size, align)?;
 
+                    let memory_kind = match link_name.as_str() {
+                        "__rust_alloc" => MiriMemoryKind::Rust,
+                        "miri_alloc" => MiriMemoryKind::Miri,
+                        _ => unreachable!(),
+                    };
+
                     let ptr = this.allocate_ptr(
                         Size::from_bytes(size),
                         Align::from_bytes(align).unwrap(),
-                        MiriMemoryKind::Rust.into(),
+                        memory_kind.into(),
                     )?;
 
                     this.write_pointer(ptr, dest)
-                });
+                };
+
+                match link_name.as_str() {
+                    "__rust_alloc" => return this.emulate_allocator(Symbol::intern("__rg_alloc"), default),
+                    "miri_alloc" => {
+                        default(this)?;
+                        return Ok(EmulateByNameResult::NeedsJumping);
+                    },
+                    _ => unreachable!(),
+                }
             }
             "__rust_alloc_zeroed" => {
                 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> {
                     this.write_pointer(ptr, dest)
                 });
             }
-            "__rust_dealloc" => {
+            "__rust_dealloc" | "miri_dealloc" => {
                 let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
                 let old_size = this.read_scalar(old_size)?.to_machine_usize(this)?;
                 let align = this.read_scalar(align)?.to_machine_usize(this)?;
 
-                return this.emulate_allocator(Symbol::intern("__rg_dealloc"), |this| {
+                let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
+                    let memory_kind = match link_name.as_str() {
+                        "__rust_dealloc" => MiriMemoryKind::Rust,
+                        "miri_dealloc" => MiriMemoryKind::Miri,
+                        _ => unreachable!(),
+                    };
+
                     // No need to check old_size/align; we anyway check that they match the allocation.
                     this.deallocate_ptr(
                         ptr,
                         Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())),
-                        MiriMemoryKind::Rust.into(),
+                        memory_kind.into(),
                     )
-                });
+                };
+
+                match link_name.as_str() {
+                    "__rust_dealloc" => return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default),
+                    "miri_dealloc" => {
+                        default(this)?;
+                        return Ok(EmulateByNameResult::NeedsJumping);
+                    }
+                    _ => unreachable!(),
+                }
             }
             "__rust_realloc" => {
                 let [ptr, old_size, align, new_size] = this.check_shim(abi, Abi::Rust, link_name, args)?;
diff --git a/src/tools/miri/tests/pass/miri-alloc.rs b/src/tools/miri/tests/pass/miri-alloc.rs
new file mode 100644
index 00000000000..f6464b5bd01
--- /dev/null
+++ b/src/tools/miri/tests/pass/miri-alloc.rs
@@ -0,0 +1,29 @@
+#![feature(lang_items, start)]
+#![no_std]
+// windows tls dtors go through libstd right now, thus this test
+// cannot pass. When windows tls dtors go through the special magic
+// windows linker section, we can run this test on windows again.
+//@ignore-target-windows: no-std not supported on Windows
+
+extern "Rust" {
+    fn miri_alloc(size: usize, align: usize) -> *mut u8;
+    fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    unsafe {
+        let ptr = miri_alloc(123, 1);
+        core::ptr::write_bytes(ptr, 0u8, 123);
+        miri_dealloc(ptr, 123, 1);
+    }
+    0
+}
+
+#[panic_handler]
+fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[lang = "eh_personality"]
+fn eh_personality() {}