const_deallocate
: Don't deallocate memory allocated in an another const. Does nothing at runtime.
`const_allocate`: Returns a null pointer at runtime.
This commit is contained in:
parent
aa6795e2d4
commit
29932db09b
8 changed files with 69 additions and 11 deletions
|
@ -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:
|
// This requires that atomic intrinsics follow a specific naming pattern:
|
||||||
// "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
|
// "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
|
||||||
name if name_str.starts_with("atomic_") => {
|
name if name_str.starts_with("atomic_") => {
|
||||||
|
|
|
@ -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),
|
Err(err) => throw_ub_format!("align has to be a power of 2, {}", err),
|
||||||
};
|
};
|
||||||
|
|
||||||
ecx.memory.deallocate(
|
// If an allocation is created in an another const,
|
||||||
ptr,
|
// we don't deallocate it.
|
||||||
Some((size, align)),
|
let (alloc_id, _, _) = ecx.memory.ptr_get_alloc(ptr)?;
|
||||||
interpret::MemoryKind::Machine(MemoryKind::Heap),
|
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!(
|
return Err(ConstEvalErrKind::NeedsRfc(format!(
|
||||||
|
|
|
@ -1914,12 +1914,13 @@ extern "rust-intrinsic" {
|
||||||
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
|
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")]
|
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
|
||||||
pub fn const_allocate(size: usize, align: usize) -> *mut u8;
|
pub fn const_allocate(size: usize, align: usize) -> *mut u8;
|
||||||
|
|
||||||
/// Deallocate a memory which allocated by `intrinsics::const_allocate` at compile time.
|
/// 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")]
|
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
|
||||||
#[cfg(not(bootstrap))]
|
#[cfg(not(bootstrap))]
|
||||||
pub fn const_deallocate(ptr: *mut u8, size: usize, align: usize);
|
pub fn const_deallocate(ptr: *mut u8, size: usize, align: usize);
|
||||||
|
|
|
@ -80,3 +80,16 @@ fn test_hints_in_const_contexts() {
|
||||||
assert!(42u32 == core::hint::black_box(42u32));
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#![feature(const_bool_to_option)]
|
#![feature(const_bool_to_option)]
|
||||||
#![feature(const_cell_into_inner)]
|
#![feature(const_cell_into_inner)]
|
||||||
#![feature(const_convert)]
|
#![feature(const_convert)]
|
||||||
|
#![feature(const_heap)]
|
||||||
#![feature(const_maybe_uninit_as_mut_ptr)]
|
#![feature(const_maybe_uninit_as_mut_ptr)]
|
||||||
#![feature(const_maybe_uninit_assume_init)]
|
#![feature(const_maybe_uninit_assume_init)]
|
||||||
#![feature(const_maybe_uninit_assume_init_read)]
|
#![feature(const_maybe_uninit_assume_init_read)]
|
||||||
|
|
|
@ -6,11 +6,10 @@ use std::intrinsics;
|
||||||
const FOO: i32 = foo();
|
const FOO: i32 = foo();
|
||||||
const fn foo() -> i32 {
|
const fn foo() -> i32 {
|
||||||
unsafe {
|
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
|
//~^ error: evaluation of constant value failed
|
||||||
}
|
}
|
||||||
1
|
1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed
|
||||||
LL | const FOO: i32 = foo();
|
LL | const FOO: i32 = foo();
|
||||||
| ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:6:18
|
| ----- 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
|
| align has to be a power of 2, `3` is not a power of 2
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
|
#![feature(const_mut_refs)]
|
||||||
|
|
||||||
use std::intrinsics;
|
use std::intrinsics;
|
||||||
|
|
||||||
|
@ -9,4 +10,27 @@ const _X: () = unsafe {
|
||||||
intrinsics::const_deallocate(ptr, 4, 4);
|
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);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue