Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 528355c

Browse files
committed
add const_allocate intrisic
1 parent b7ebc6b commit 528355c

File tree

13 files changed

+111
-3
lines changed

13 files changed

+111
-3
lines changed

compiler/rustc_mir/src/interpret/intern.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
104104
// This match is just a canary for future changes to `MemoryKind`, which most likely need
105105
// changes in this function.
106106
match kind {
107-
MemoryKind::Stack | MemoryKind::Vtable | MemoryKind::CallerLocation => {}
107+
MemoryKind::Stack | MemoryKind::Heap | MemoryKind::Vtable | MemoryKind::CallerLocation => {}
108108
}
109109
// Set allocation mutability as appropriate. This is used by LLVM to put things into
110110
// read-only memory, and also by Miri when evaluating other globals that

compiler/rustc_mir/src/interpret/intrinsics.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ use rustc_middle::ty;
1414
use rustc_middle::ty::subst::SubstsRef;
1515
use rustc_middle::ty::{Ty, TyCtxt};
1616
use rustc_span::symbol::{sym, Symbol};
17-
use rustc_target::abi::{Abi, LayoutOf as _, Primitive, Size};
17+
use rustc_target::abi::{Abi, Align, LayoutOf as _, Primitive, Size};
1818

1919
use super::{
20-
util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
20+
util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, MemoryKind, OpTy,
21+
PlaceTy,
2122
};
2223

2324
mod caller_location;
@@ -337,6 +338,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
337338
let result = Scalar::from_uint(truncated_bits, layout.size);
338339
self.write_scalar(result, dest)?;
339340
}
341+
sym::const_allocate => {
342+
let size = self.read_scalar(args[0])?.to_machine_usize(self)?;
343+
let align = self.read_scalar(args[1])?.to_machine_usize(self)?;
344+
345+
let align = match Align::from_bytes(align) {
346+
Ok(a) => a,
347+
Err(err) => bug!("align has to power of 2, {}", err),
348+
};
349+
350+
let ptr =
351+
self.memory.allocate(Size::from_bytes(size as u64), align, MemoryKind::Heap);
352+
self.write_scalar(Scalar::Ptr(ptr), dest)?;
353+
}
340354
sym::offset => {
341355
let ptr = self.read_scalar(args[0])?.check_init()?;
342356
let offset_count = self.read_scalar(args[1])?.to_machine_isize(self)?;

compiler/rustc_mir/src/interpret/memory.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ use crate::util::pretty;
2727
pub enum MemoryKind<T> {
2828
/// Stack memory. Error if deallocated except during a stack pop.
2929
Stack,
30+
/// Heap memory.
31+
Heap,
3032
/// Memory backing vtables. Error if ever deallocated.
3133
Vtable,
3234
/// Memory allocated by `caller_location` intrinsic. Error if ever deallocated.
@@ -40,6 +42,7 @@ impl<T: MayLeak> MayLeak for MemoryKind<T> {
4042
fn may_leak(self) -> bool {
4143
match self {
4244
MemoryKind::Stack => false,
45+
MemoryKind::Heap => true,
4346
MemoryKind::Vtable => true,
4447
MemoryKind::CallerLocation => true,
4548
MemoryKind::Machine(k) => k.may_leak(),
@@ -51,6 +54,7 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
5154
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5255
match self {
5356
MemoryKind::Stack => write!(f, "stack variable"),
57+
MemoryKind::Heap => write!(f, "heap variable"),
5458
MemoryKind::Vtable => write!(f, "vtable"),
5559
MemoryKind::CallerLocation => write!(f, "caller location"),
5660
MemoryKind::Machine(m) => write!(f, "{}", m),

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ symbols! {
356356
concat_idents,
357357
conservative_impl_trait,
358358
console,
359+
const_allocate,
359360
const_compare_raw_pointers,
360361
const_constructor,
361362
const_eval_limit,

compiler/rustc_typeck/src/check/intrinsic.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
286286
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool)
287287
}
288288

289+
sym::const_allocate => {
290+
(0, vec![tcx.types.usize, tcx.types.usize], tcx.mk_mut_ptr(tcx.types.u8))
291+
}
292+
289293
sym::ptr_offset_from => {
290294
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
291295
}

library/core/src/intrinsics.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,11 @@ extern "rust-intrinsic" {
17321732
/// See documentation of `<*const T>::guaranteed_ne` for details.
17331733
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
17341734
pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
1735+
1736+
/// Allocate at compile time. Should not be called at runtime.
1737+
#[rustc_const_unstable(feature = "const_heap", issue = "none")]
1738+
#[cfg(not(bootstrap))]
1739+
pub fn const_allocate(size: usize, align: usize) -> *mut u8;
17351740
}
17361741

17371742
// Some functions are defined here because they accidentally got made

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#![feature(arbitrary_self_types)]
6969
#![feature(asm)]
7070
#![feature(cfg_target_has_atomic)]
71+
#![cfg_attr(not(bootstrap), feature(const_heap))]
7172
#![feature(const_alloc_layout)]
7273
#![feature(const_discriminant)]
7374
#![feature(const_cell_into_inner)]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// run-pass
2+
#![feature(core_intrinsics)]
3+
#![feature(const_heap)]
4+
#![feature(const_raw_ptr_deref)]
5+
#![feature(const_mut_refs)]
6+
use std::intrinsics;
7+
8+
const FOO: *const i32 = foo();
9+
10+
const fn foo() -> &'static i32 {
11+
let t = unsafe {
12+
let i = intrinsics::const_allocate(4, 4) as * mut i32;
13+
*i = 20;
14+
i
15+
};
16+
unsafe { &*t }
17+
}
18+
fn main() {
19+
assert_eq!(unsafe { *FOO }, 20)
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// run-pass
2+
#![feature(core_intrinsics)]
3+
#![feature(const_heap)]
4+
#![feature(const_raw_ptr_deref)]
5+
#![feature(const_mut_refs)]
6+
use std::intrinsics;
7+
8+
const FOO: i32 = foo();
9+
10+
const fn foo() -> i32 {
11+
let t = unsafe {
12+
let i = intrinsics::const_allocate(4, 4) as * mut i32;
13+
*i = 20;
14+
i
15+
};
16+
unsafe { *t }
17+
}
18+
fn main() {
19+
assert_eq!(FOO, 20);
20+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// compile-test
2+
#![feature(core_intrinsics)]
3+
#![feature(const_heap)]
4+
#![feature(const_raw_ptr_deref)]
5+
#![feature(const_mut_refs)]
6+
use std::intrinsics;
7+
8+
const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) };
9+
//~^ error: it is undefined behavior to use this value
10+
fn main() {}

0 commit comments

Comments
 (0)