Add intrinsics::const_deallocate

This commit is contained in:
woppopo 2021-12-25 22:35:11 +09:00
parent 10c4c4afec
commit aa6795e2d4
11 changed files with 156 additions and 0 deletions

View file

@ -347,6 +347,23 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
)?;
ecx.write_pointer(ptr, dest)?;
}
sym::const_deallocate => {
let ptr = ecx.read_pointer(&args[0])?;
let size = ecx.read_scalar(&args[1])?.to_machine_usize(ecx)?;
let align = ecx.read_scalar(&args[2])?.to_machine_usize(ecx)?;
let size = Size::from_bytes(size);
let align = match Align::from_bytes(align) {
Ok(a) => a,
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),
)?;
}
_ => {
return Err(ConstEvalErrKind::NeedsRfc(format!(
"calling intrinsic `{}`",

View file

@ -460,6 +460,7 @@ symbols! {
const_async_blocks,
const_compare_raw_pointers,
const_constructor,
const_deallocate,
const_eval_limit,
const_eval_select,
const_eval_select_ct,

View file

@ -297,6 +297,11 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::const_allocate => {
(0, vec![tcx.types.usize, tcx.types.usize], tcx.mk_mut_ptr(tcx.types.u8))
}
sym::const_deallocate => (
0,
vec![tcx.mk_mut_ptr(tcx.types.u8), tcx.types.usize, tcx.types.usize],
tcx.mk_unit(),
),
sym::ptr_offset_from => {
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)

View file

@ -1918,6 +1918,12 @@ extern "rust-intrinsic" {
#[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.
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
#[cfg(not(bootstrap))]
pub fn const_deallocate(ptr: *mut u8, size: usize, align: usize);
/// Determines whether the raw bytes of the two values are equal.
///
/// This is particularly handy for arrays, since it allows things like just

View file

@ -0,0 +1,12 @@
// run-pass
#![feature(core_intrinsics)]
#![feature(const_heap)]
use std::intrinsics;
const _X: () = unsafe {
let ptr = intrinsics::const_allocate(4, 4);
intrinsics::const_deallocate(ptr, 4, 4);
};
fn main() {}

View file

@ -0,0 +1,22 @@
#![feature(core_intrinsics)]
#![feature(const_heap)]
#![feature(const_mut_refs)]
use std::intrinsics;
const _X: &'static u8 = unsafe {
let ptr = intrinsics::const_allocate(4, 4);
intrinsics::const_deallocate(ptr, 4, 4);
&*ptr
//~^ error: evaluation of constant value failed
};
const _Y: u8 = unsafe {
let ptr = intrinsics::const_allocate(4, 4);
let reference = &*ptr;
intrinsics::const_deallocate(ptr, 4, 4);
*reference
//~^ error: evaluation of constant value failed
};
fn main() {}

View file

@ -0,0 +1,15 @@
error[E0080]: evaluation of constant value failed
--> $DIR/dealloc_intrinsic_dangling.rs:10:5
|
LL | &*ptr
| ^^^^^ pointer to alloc2 was dereferenced after this allocation got freed
error[E0080]: evaluation of constant value failed
--> $DIR/dealloc_intrinsic_dangling.rs:18:5
|
LL | *reference
| ^^^^^^^^^^ pointer to alloc4 was dereferenced after this allocation got freed
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.

View file

@ -0,0 +1,13 @@
#![feature(core_intrinsics)]
#![feature(const_heap)]
use std::intrinsics;
const _X: () = unsafe {
let ptr = intrinsics::const_allocate(4, 4);
intrinsics::const_deallocate(ptr, 4, 4);
intrinsics::const_deallocate(ptr, 4, 4);
//~^ error: evaluation of constant value failed
};
fn main() {}

View file

@ -0,0 +1,9 @@
error[E0080]: evaluation of constant value failed
--> $DIR/dealloc_intrinsic_duplicate.rs:9:5
|
LL | intrinsics::const_deallocate(ptr, 4, 4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pointer to alloc2 was dereferenced after this allocation got freed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0080`.

View file

@ -0,0 +1,29 @@
#![feature(core_intrinsics)]
#![feature(const_heap)]
use std::intrinsics;
const _X: () = unsafe {
let ptr = intrinsics::const_allocate(4, 4);
intrinsics::const_deallocate(ptr, 4, 2);
//~^ error: evaluation of constant value failed
};
const _Y: () = unsafe {
let ptr = intrinsics::const_allocate(4, 4);
intrinsics::const_deallocate(ptr, 2, 4);
//~^ error: evaluation of constant value failed
};
const _Z: () = unsafe {
let ptr = intrinsics::const_allocate(4, 4);
intrinsics::const_deallocate(ptr, 3, 4);
//~^ error: evaluation of constant value failed
};
const _W: () = unsafe {
let ptr = intrinsics::const_allocate(4, 4);
intrinsics::const_deallocate(ptr, 4, 3);
//~^ error: evaluation of constant value failed
};
fn main() {}

View file

@ -0,0 +1,27 @@
error[E0080]: evaluation of constant value failed
--> $DIR/dealloc_intrinsic_incorrect_layout.rs:8:5
|
LL | intrinsics::const_deallocate(ptr, 4, 2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc2 has size 4 and alignment 4, but gave size 4 and alignment 2
error[E0080]: evaluation of constant value failed
--> $DIR/dealloc_intrinsic_incorrect_layout.rs:13:5
|
LL | intrinsics::const_deallocate(ptr, 2, 4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc4 has size 4 and alignment 4, but gave size 2 and alignment 4
error[E0080]: evaluation of constant value failed
--> $DIR/dealloc_intrinsic_incorrect_layout.rs:19:5
|
LL | intrinsics::const_deallocate(ptr, 3, 4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc6 has size 4 and alignment 4, but gave size 3 and alignment 4
error[E0080]: evaluation of constant value failed
--> $DIR/dealloc_intrinsic_incorrect_layout.rs:25:5
|
LL | intrinsics::const_deallocate(ptr, 4, 3);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ align has to be a power of 2, `3` is not a power of 2
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.