about summary refs log tree commit diff
diff options
context:
space:
mode:
authorwoppopo <woppopo@protonmail.com>2022-01-26 13:06:09 +0900
committerwoppopo <woppopo@protonmail.com>2022-01-26 13:06:09 +0900
commit29932db09bb985072dc68d9d4e4acab09e69562a (patch)
tree6f0e8d2b0a52aabfc67996bc5ed4fe0ef9bd162b
parentaa6795e2d4cdae6af2ea854744c3bec2eb30d16e (diff)
downloadrust-29932db09bb985072dc68d9d4e4acab09e69562a.tar.gz
rust-29932db09bb985072dc68d9d4e4acab09e69562a.zip
`const_deallocate`: Don't deallocate memory allocated in an another const. Does nothing at runtime.
`const_allocate`:  Returns a null pointer at runtime.
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs10
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs20
-rw-r--r--library/core/src/intrinsics.rs5
-rw-r--r--library/core/tests/intrinsics.rs13
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs3
-rw-r--r--src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr2
-rw-r--r--src/test/ui/consts/const-eval/heap/dealloc_intrinsic.rs26
8 files changed, 69 insertions, 11 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 3657f80c2de..c654232c10a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -369,6 +369,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
 
+            sym::const_allocate => {
+                // returns a null pointer at runtime.
+                bx.const_null(bx.type_i8p())
+            }
+
+            sym::const_deallocate => {
+                // nop at runtime.
+                return;
+            }
+
             // This requires that atomic intrinsics follow a specific naming pattern:
             // "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
             name if name_str.starts_with("atomic_") => {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 62eaf333340..89717b75f12 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -358,11 +358,21 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
                     Err(err) => throw_ub_format!("align has to be a power of 2, {}", err),
                 };
 
-                ecx.memory.deallocate(
-                    ptr,
-                    Some((size, align)),
-                    interpret::MemoryKind::Machine(MemoryKind::Heap),
-                )?;
+                // If an allocation is created in an another const,
+                // we don't deallocate it.
+                let (alloc_id, _, _) = ecx.memory.ptr_get_alloc(ptr)?;
+                let is_allocated_in_another_const = matches!(
+                    ecx.tcx.get_global_alloc(alloc_id),
+                    Some(interpret::GlobalAlloc::Memory(_))
+                );
+
+                if !is_allocated_in_another_const {
+                    ecx.memory.deallocate(
+                        ptr,
+                        Some((size, align)),
+                        interpret::MemoryKind::Machine(MemoryKind::Heap),
+                    )?;
+                }
             }
             _ => {
                 return Err(ConstEvalErrKind::NeedsRfc(format!(
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 10b5e06fc50..b03f1268e36 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1914,12 +1914,13 @@ extern "rust-intrinsic" {
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
 
-    /// Allocate at compile time. Should not be called at runtime.
+    /// Allocate at compile time.
+    /// Returns a null pointer at runtime.
     #[rustc_const_unstable(feature = "const_heap", issue = "79597")]
     pub fn const_allocate(size: usize, align: usize) -> *mut u8;
 
     /// Deallocate a memory which allocated by `intrinsics::const_allocate` at compile time.
-    /// Should not be called at runtime.
+    /// Does nothing at runtime.
     #[rustc_const_unstable(feature = "const_heap", issue = "79597")]
     #[cfg(not(bootstrap))]
     pub fn const_deallocate(ptr: *mut u8, size: usize, align: usize);
diff --git a/library/core/tests/intrinsics.rs b/library/core/tests/intrinsics.rs
index 7a2e4e29065..e5b6fa7f732 100644
--- a/library/core/tests/intrinsics.rs
+++ b/library/core/tests/intrinsics.rs
@@ -80,3 +80,16 @@ fn test_hints_in_const_contexts() {
         assert!(42u32 == core::hint::black_box(42u32));
     }
 }
+
+#[cfg(not(bootstrap))]
+#[test]
+fn test_const_dealocate_at_runtime() {
+    use core::intrinsics::const_deallocate;
+    const X: &u32 = &42u32;
+    let x = &0u32;
+    unsafe {
+        const_deallocate(X as *const _ as *mut u8, 4, 4); // nop
+        const_deallocate(x as *const _ as *mut u8, 4, 4); // nop
+        const_deallocate(core::ptr::null_mut(), 1, 1); // nop
+    }
+}
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 841c114063d..1d49d7e47cb 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -13,6 +13,7 @@
 #![feature(const_bool_to_option)]
 #![feature(const_cell_into_inner)]
 #![feature(const_convert)]
+#![feature(const_heap)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_assume_init)]
 #![feature(const_maybe_uninit_assume_init_read)]
diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs
index 1a1d9a6d540..ac9e8b64b48 100644
--- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs
+++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs
@@ -6,11 +6,10 @@ use std::intrinsics;
 const FOO: i32 = foo();
 const fn foo() -> i32 {
     unsafe {
-        let _ = intrinsics::const_allocate(4, 3) as * mut i32;
+        let _ = intrinsics::const_allocate(4, 3) as *mut i32;
         //~^ error: evaluation of constant value failed
     }
     1
-
 }
 
 fn main() {}
diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
index 74fb65ca1a6..2628a78455c 100644
--- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
+++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
@@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed
 LL | const FOO: i32 = foo();
    |                  ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:6:18
 ...
-LL |         let _ = intrinsics::const_allocate(4, 3) as * mut i32;
+LL |         let _ = intrinsics::const_allocate(4, 3) as *mut i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                 |
    |                 align has to be a power of 2, `3` is not a power of 2
diff --git a/src/test/ui/consts/const-eval/heap/dealloc_intrinsic.rs b/src/test/ui/consts/const-eval/heap/dealloc_intrinsic.rs
index b7c2b752644..aac90cd54cc 100644
--- a/src/test/ui/consts/const-eval/heap/dealloc_intrinsic.rs
+++ b/src/test/ui/consts/const-eval/heap/dealloc_intrinsic.rs
@@ -1,6 +1,7 @@
 // run-pass
 #![feature(core_intrinsics)]
 #![feature(const_heap)]
+#![feature(const_mut_refs)]
 
 use std::intrinsics;
 
@@ -9,4 +10,27 @@ const _X: () = unsafe {
     intrinsics::const_deallocate(ptr, 4, 4);
 };
 
-fn main() {}
+const Y: &u32 = unsafe {
+    let ptr = intrinsics::const_allocate(4, 4) as *mut u32;
+    *ptr = 42;
+    &*ptr
+};
+
+const Z: &u32 = &42;
+
+const _Z: () = unsafe {
+    let ptr1 = Y as *const _ as *mut u8;
+    intrinsics::const_deallocate(ptr1, 4, 4); // nop
+    intrinsics::const_deallocate(ptr1, 2, 4); // nop
+    intrinsics::const_deallocate(ptr1, 4, 2); // nop
+
+    let ptr2 = Z as *const _ as *mut u8;
+    intrinsics::const_deallocate(ptr2, 4, 4); // nop
+    intrinsics::const_deallocate(ptr2, 2, 4); // nop
+    intrinsics::const_deallocate(ptr2, 4, 2); // nop
+};
+
+fn main() {
+    assert_eq!(*Y, 42);
+    assert_eq!(*Z, 42);
+}