Skip to content

Commit afb57ca

Browse files
authored
Rollup merge of rust-lang#141513 - nia-e:allocbytes-extend, r=RalfJung
interpret: add allocation parameters to `AllocBytes` Necessary for a better implementation of [rust-lang/miri#4343](rust-lang/miri#4343). Also included here is the code from that PR, adapted to this new interface for the sake of example and so that CI can run on them; the Miri changes can be reverted and merged separately, though. r? `@RalfJung`
2 parents be778ed + e388a3e commit afb57ca

File tree

16 files changed

+81
-34
lines changed

16 files changed

+81
-34
lines changed

compiler/rustc_const_eval/src/const_eval/dummy_machine.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,9 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
197197
) -> &'a mut Vec<interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>> {
198198
unimplemented!()
199199
}
200+
201+
fn get_default_alloc_params(
202+
&self,
203+
) -> <Self::Bytes as rustc_middle::mir::interpret::AllocBytes>::AllocParams {
204+
}
200205
}

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,9 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
735735
Cow::Owned(compute_range())
736736
}
737737
}
738+
739+
fn get_default_alloc_params(&self) -> <Self::Bytes as mir::interpret::AllocBytes>::AllocParams {
740+
}
738741
}
739742

740743
// Please do not add any code below the above `Machine` trait impl. I (oli-obk) plan more cleanups

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::fluent_generated as fluent;
2626
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
2727
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
2828
let path = crate::util::type_name(tcx, ty);
29-
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
29+
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes(), ());
3030
tcx.mk_const_alloc(alloc)
3131
}
3232

compiler/rustc_const_eval/src/interpret/machine.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,10 @@ pub trait Machine<'tcx>: Sized {
626626
// Default to no caching.
627627
Cow::Owned(compute_range())
628628
}
629+
630+
/// Compute the value passed to the constructors of the `AllocBytes` type for
631+
/// abstract machine allocations.
632+
fn get_default_alloc_params(&self) -> <Self::Bytes as AllocBytes>::AllocParams;
629633
}
630634

631635
/// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines

compiler/rustc_const_eval/src/interpret/memory.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
233233
kind: MemoryKind<M::MemoryKind>,
234234
init: AllocInit,
235235
) -> InterpResult<'tcx, Pointer<M::Provenance>> {
236+
let params = self.machine.get_default_alloc_params();
236237
let alloc = if M::PANIC_ON_ALLOC_FAIL {
237-
Allocation::new(size, align, init)
238+
Allocation::new(size, align, init, params)
238239
} else {
239-
Allocation::try_new(size, align, init)?
240+
Allocation::try_new(size, align, init, params)?
240241
};
241242
self.insert_allocation(alloc, kind)
242243
}
@@ -248,7 +249,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
248249
kind: MemoryKind<M::MemoryKind>,
249250
mutability: Mutability,
250251
) -> InterpResult<'tcx, Pointer<M::Provenance>> {
251-
let alloc = Allocation::from_bytes(bytes, align, mutability);
252+
let params = self.machine.get_default_alloc_params();
253+
let alloc = Allocation::from_bytes(bytes, align, mutability, params);
252254
self.insert_allocation(alloc, kind)
253255
}
254256

compiler/rustc_const_eval/src/interpret/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub(crate) fn create_static_alloc<'tcx>(
3838
static_def_id: LocalDefId,
3939
layout: TyAndLayout<'tcx>,
4040
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
41-
let alloc = Allocation::try_new(layout.size, layout.align.abi, AllocInit::Uninit)?;
41+
let alloc = Allocation::try_new(layout.size, layout.align.abi, AllocInit::Uninit, ())?;
4242
let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id.into());
4343
assert_eq!(ecx.machine.static_root_ids, None);
4444
ecx.machine.static_root_ids = Some((alloc_id, static_def_id));

compiler/rustc_middle/src/mir/interpret/allocation.rs

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,21 @@ use crate::ty;
2727

2828
/// Functionality required for the bytes of an `Allocation`.
2929
pub trait AllocBytes: Clone + fmt::Debug + Deref<Target = [u8]> + DerefMut<Target = [u8]> {
30+
/// The type of extra parameters passed in when creating an allocation.
31+
/// Can be used by `interpret::Machine` instances to make runtime-configuration-dependent
32+
/// decisions about the allocation strategy.
33+
type AllocParams;
34+
3035
/// Create an `AllocBytes` from a slice of `u8`.
31-
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self;
36+
fn from_bytes<'a>(
37+
slice: impl Into<Cow<'a, [u8]>>,
38+
_align: Align,
39+
_params: Self::AllocParams,
40+
) -> Self;
3241

3342
/// Create a zeroed `AllocBytes` of the specified size and alignment.
3443
/// Returns `None` if we ran out of memory on the host.
35-
fn zeroed(size: Size, _align: Align) -> Option<Self>;
44+
fn zeroed(size: Size, _align: Align, _params: Self::AllocParams) -> Option<Self>;
3645

3746
/// Gives direct access to the raw underlying storage.
3847
///
@@ -51,11 +60,13 @@ pub trait AllocBytes: Clone + fmt::Debug + Deref<Target = [u8]> + DerefMut<Targe
5160

5261
/// Default `bytes` for `Allocation` is a `Box<u8>`.
5362
impl AllocBytes for Box<[u8]> {
54-
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self {
63+
type AllocParams = ();
64+
65+
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align, _params: ()) -> Self {
5566
Box::<[u8]>::from(slice.into())
5667
}
5768

58-
fn zeroed(size: Size, _align: Align) -> Option<Self> {
69+
fn zeroed(size: Size, _align: Align, _params: ()) -> Option<Self> {
5970
let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes().try_into().ok()?).ok()?;
6071
// SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
6172
let bytes = unsafe { bytes.assume_init() };
@@ -172,9 +183,8 @@ fn all_zero(buf: &[u8]) -> bool {
172183
}
173184

174185
/// Custom encoder for [`Allocation`] to more efficiently represent the case where all bytes are 0.
175-
impl<Prov: Provenance, Extra, Bytes, E: Encoder> Encodable<E> for Allocation<Prov, Extra, Bytes>
186+
impl<Prov: Provenance, Extra, E: Encoder> Encodable<E> for Allocation<Prov, Extra, Box<[u8]>>
176187
where
177-
Bytes: AllocBytes,
178188
ProvenanceMap<Prov>: Encodable<E>,
179189
Extra: Encodable<E>,
180190
{
@@ -192,9 +202,8 @@ where
192202
}
193203
}
194204

195-
impl<Prov: Provenance, Extra, Bytes, D: Decoder> Decodable<D> for Allocation<Prov, Extra, Bytes>
205+
impl<Prov: Provenance, Extra, D: Decoder> Decodable<D> for Allocation<Prov, Extra, Box<[u8]>>
196206
where
197-
Bytes: AllocBytes,
198207
ProvenanceMap<Prov>: Decodable<D>,
199208
Extra: Decodable<D>,
200209
{
@@ -203,7 +212,7 @@ where
203212

204213
let len = decoder.read_usize();
205214
let bytes = if all_zero { vec![0u8; len] } else { decoder.read_raw_bytes(len).to_vec() };
206-
let bytes = Bytes::from_bytes(bytes, align);
215+
let bytes = <Box<[u8]> as AllocBytes>::from_bytes(bytes, align, ());
207216

208217
let provenance = Decodable::decode(decoder);
209218
let init_mask = Decodable::decode(decoder);
@@ -395,8 +404,9 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
395404
slice: impl Into<Cow<'a, [u8]>>,
396405
align: Align,
397406
mutability: Mutability,
407+
params: <Bytes as AllocBytes>::AllocParams,
398408
) -> Self {
399-
let bytes = Bytes::from_bytes(slice, align);
409+
let bytes = Bytes::from_bytes(slice, align, params);
400410
let size = Size::from_bytes(bytes.len());
401411
Self {
402412
bytes,
@@ -408,14 +418,18 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
408418
}
409419
}
410420

411-
pub fn from_bytes_byte_aligned_immutable<'a>(slice: impl Into<Cow<'a, [u8]>>) -> Self {
412-
Allocation::from_bytes(slice, Align::ONE, Mutability::Not)
421+
pub fn from_bytes_byte_aligned_immutable<'a>(
422+
slice: impl Into<Cow<'a, [u8]>>,
423+
params: <Bytes as AllocBytes>::AllocParams,
424+
) -> Self {
425+
Allocation::from_bytes(slice, Align::ONE, Mutability::Not, params)
413426
}
414427

415428
fn new_inner<R>(
416429
size: Size,
417430
align: Align,
418431
init: AllocInit,
432+
params: <Bytes as AllocBytes>::AllocParams,
419433
fail: impl FnOnce() -> R,
420434
) -> Result<Self, R> {
421435
// We raise an error if we cannot create the allocation on the host.
@@ -424,7 +438,7 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
424438
// deterministic. However, we can be non-deterministic here because all uses of const
425439
// evaluation (including ConstProp!) will make compilation fail (via hard error
426440
// or ICE) upon encountering a `MemoryExhausted` error.
427-
let bytes = Bytes::zeroed(size, align).ok_or_else(fail)?;
441+
let bytes = Bytes::zeroed(size, align, params).ok_or_else(fail)?;
428442

429443
Ok(Allocation {
430444
bytes,
@@ -444,8 +458,13 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
444458

445459
/// Try to create an Allocation of `size` bytes, failing if there is not enough memory
446460
/// available to the compiler to do so.
447-
pub fn try_new<'tcx>(size: Size, align: Align, init: AllocInit) -> InterpResult<'tcx, Self> {
448-
Self::new_inner(size, align, init, || {
461+
pub fn try_new<'tcx>(
462+
size: Size,
463+
align: Align,
464+
init: AllocInit,
465+
params: <Bytes as AllocBytes>::AllocParams,
466+
) -> InterpResult<'tcx, Self> {
467+
Self::new_inner(size, align, init, params, || {
449468
ty::tls::with(|tcx| tcx.dcx().delayed_bug("exhausted memory during interpretation"));
450469
InterpErrorKind::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
451470
})
@@ -457,8 +476,13 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
457476
///
458477
/// Example use case: To obtain an Allocation filled with specific data,
459478
/// first call this function and then call write_scalar to fill in the right data.
460-
pub fn new(size: Size, align: Align, init: AllocInit) -> Self {
461-
match Self::new_inner(size, align, init, || {
479+
pub fn new(
480+
size: Size,
481+
align: Align,
482+
init: AllocInit,
483+
params: <Bytes as AllocBytes>::AllocParams,
484+
) -> Self {
485+
match Self::new_inner(size, align, init, params, || {
462486
panic!(
463487
"interpreter ran out of memory: cannot create allocation of {} bytes",
464488
size.bytes()

compiler/rustc_middle/src/ty/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1582,7 +1582,7 @@ impl<'tcx> TyCtxt<'tcx> {
15821582
/// Returns the same `AllocId` if called again with the same bytes.
15831583
pub fn allocate_bytes_dedup(self, bytes: &[u8], salt: usize) -> interpret::AllocId {
15841584
// Create an allocation that just contains these bytes.
1585-
let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes);
1585+
let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes, ());
15861586
let alloc = self.mk_const_alloc(alloc);
15871587
self.reserve_and_set_memory_dedup(alloc, salt)
15881588
}

compiler/rustc_middle/src/ty/vtable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
110110
let ptr_align = tcx.data_layout.pointer_align.abi;
111111

112112
let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
113-
let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit);
113+
let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit, ());
114114

115115
// No need to do any alignment checks on the memory accesses below, because we know the
116116
// allocation is correctly aligned as we created it above. Also we're only offsetting by

compiler/rustc_mir_build/src/builder/expr/as_constant.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,14 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
121121
let value = match (lit, lit_ty.kind()) {
122122
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
123123
let s = s.as_str();
124-
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
124+
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes(), ());
125125
let allocation = tcx.mk_const_alloc(allocation);
126126
ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
127127
}
128128
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
129129
if matches!(inner_ty.kind(), ty::Slice(_)) =>
130130
{
131-
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
131+
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8], ());
132132
let allocation = tcx.mk_const_alloc(allocation);
133133
ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
134134
}
@@ -138,7 +138,7 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
138138
}
139139
(ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
140140
{
141-
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
141+
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8], ());
142142
let allocation = tcx.mk_const_alloc(allocation);
143143
ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
144144
}

0 commit comments

Comments
 (0)