Skip to content

Commit bbc1109

Browse files
authored
Rollup merge of rust-lang#114587 - ouz-a:smir_allocation, r=oli-obk
Convert Const to Allocation in smir Continuation of previous pr rust-lang#114466 cc rust-lang/project-stable-mir#15 r? `@oli-obk`
2 parents 90c0371 + 8f1ea57 commit bbc1109

File tree

4 files changed

+186
-27
lines changed

4 files changed

+186
-27
lines changed

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

+3
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
329329

330330
/// Try to create an Allocation of `size` bytes, panics if there is not enough memory
331331
/// available to the compiler to do so.
332+
///
333+
/// Example use case: To obtain an Allocation filled with specific data,
334+
/// first call this function and then call write_scalar to fill in the right data.
332335
pub fn uninit(size: Size, align: Align) -> Self {
333336
match Self::uninit_inner(size, align, || {
334337
panic!("Allocation::uninit called with panic_on_fail had allocation failure");

compiler/rustc_smir/src/rustc_internal/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ impl<'tcx> Tables<'tcx> {
112112
stable_mir::ty::TraitDef(self.create_def_id(did))
113113
}
114114

115+
pub fn const_def(&mut self, did: DefId) -> stable_mir::ty::ConstDef {
116+
stable_mir::ty::ConstDef(self.create_def_id(did))
117+
}
118+
115119
fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
116120
// FIXME: this becomes inefficient when we have too many ids
117121
for (i, &d) in self.def_ids.iter().enumerate() {

compiler/rustc_smir/src/rustc_smir/mod.rs

+33-26
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
1010
use crate::rustc_internal::{self, opaque};
1111
use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx};
12-
use crate::stable_mir::ty::{FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy};
12+
use crate::stable_mir::ty::{
13+
allocation_filter, new_allocation, FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy,
14+
};
1315
use crate::stable_mir::{self, Context};
1416
use rustc_hir as hir;
1517
use rustc_middle::mir::coverage::CodeRegion;
16-
use rustc_middle::mir::{self};
18+
use rustc_middle::mir::interpret::alloc_range;
19+
use rustc_middle::mir::{self, ConstantKind};
1720
use rustc_middle::ty::{self, Ty, TyCtxt, Variance};
1821
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
1922
use rustc_target::abi::FieldIdx;
@@ -1082,30 +1085,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
10821085
type T = stable_mir::ty::Allocation;
10831086

10841087
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1085-
let size = self.size();
1086-
let mut bytes: Vec<Option<u8>> = self
1087-
.inspect_with_uninit_and_ptr_outside_interpreter(0..size.bytes_usize())
1088-
.iter()
1089-
.copied()
1090-
.map(Some)
1091-
.collect();
1092-
for (i, b) in bytes.iter_mut().enumerate() {
1093-
if !self.init_mask().get(rustc_target::abi::Size::from_bytes(i)) {
1094-
*b = None;
1095-
}
1096-
}
1097-
stable_mir::ty::Allocation {
1098-
bytes: bytes,
1099-
provenance: {
1100-
let mut ptrs = Vec::new();
1101-
for (size, prov) in self.provenance().ptrs().iter() {
1102-
ptrs.push((size.bytes_usize(), opaque(prov)));
1103-
}
1104-
stable_mir::ty::ProvenanceMap { ptrs }
1105-
},
1106-
align: self.align.bytes(),
1107-
mutability: self.mutability.stable(tables),
1108-
}
1088+
allocation_filter(self, alloc_range(rustc_target::abi::Size::ZERO, self.size()), tables)
11091089
}
11101090
}
11111091

@@ -1147,3 +1127,30 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef {
11471127
}
11481128
}
11491129
}
1130+
1131+
impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
1132+
type T = stable_mir::ty::ConstantKind;
1133+
1134+
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1135+
match self {
1136+
ConstantKind::Ty(c) => match c.kind() {
1137+
ty::Value(val) => {
1138+
let const_val = tables.tcx.valtree_to_const_val((c.ty(), val));
1139+
stable_mir::ty::ConstantKind::Allocated(new_allocation(self, const_val, tables))
1140+
}
1141+
_ => todo!(),
1142+
},
1143+
ConstantKind::Unevaluated(unev_const, ty) => {
1144+
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
1145+
ty: tables.intern_ty(*ty),
1146+
def: tables.const_def(unev_const.def),
1147+
args: unev_const.args.stable(tables),
1148+
promoted: unev_const.promoted.map(|u| u.as_u32()),
1149+
})
1150+
}
1151+
ConstantKind::Val(val, _) => {
1152+
stable_mir::ty::ConstantKind::Allocated(new_allocation(self, *val, tables))
1153+
}
1154+
}
1155+
}
1156+
}

compiler/rustc_smir/src/stable_mir/ty.rs

+146-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer};
2+
13
use super::{mir::Mutability, mir::Safety, with, DefId};
2-
use crate::rustc_internal::Opaque;
4+
use crate::{
5+
rustc_internal::{opaque, Opaque},
6+
rustc_smir::{Stable, Tables},
7+
};
38

49
#[derive(Copy, Clone, Debug)]
510
pub struct Ty(pub usize);
@@ -105,6 +110,9 @@ pub struct AliasDef(pub(crate) DefId);
105110
#[derive(Clone, PartialEq, Eq, Debug)]
106111
pub struct TraitDef(pub(crate) DefId);
107112

113+
#[derive(Clone, PartialEq, Eq, Debug)]
114+
pub struct ConstDef(pub(crate) DefId);
115+
108116
impl TraitDef {
109117
pub fn trait_decl(&self) -> TraitDecl {
110118
with(|cx| cx.trait_decl(self))
@@ -250,6 +258,7 @@ pub type Bytes = Vec<Option<u8>>;
250258
pub type Size = usize;
251259
pub type Prov = Opaque;
252260
pub type Align = u64;
261+
pub type Promoted = u32;
253262
pub type InitMaskMaterialized = Vec<u64>;
254263

255264
/// Stores the provenance information of pointers stored in memory.
@@ -268,6 +277,142 @@ pub struct Allocation {
268277
pub mutability: Mutability,
269278
}
270279

280+
impl Allocation {
281+
/// Creates new empty `Allocation` from given `Align`.
282+
fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
283+
Allocation {
284+
bytes: Vec::new(),
285+
provenance: ProvenanceMap { ptrs: Vec::new() },
286+
align: align.bytes(),
287+
mutability: Mutability::Not,
288+
}
289+
}
290+
}
291+
292+
// We need this method instead of a Stable implementation
293+
// because we need to get `Ty` of the const we are trying to create, to do that
294+
// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
295+
pub fn new_allocation<'tcx>(
296+
const_kind: &rustc_middle::mir::ConstantKind<'tcx>,
297+
const_value: ConstValue<'tcx>,
298+
tables: &mut Tables<'tcx>,
299+
) -> Allocation {
300+
match const_value {
301+
ConstValue::Scalar(scalar) => {
302+
let size = scalar.size();
303+
let align = tables
304+
.tcx
305+
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
306+
.unwrap()
307+
.align;
308+
let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
309+
allocation
310+
.write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
311+
.unwrap();
312+
allocation.stable(tables)
313+
}
314+
ConstValue::ZeroSized => {
315+
let align = tables
316+
.tcx
317+
.layout_of(rustc_middle::ty::ParamEnv::empty().and(const_kind.ty()))
318+
.unwrap()
319+
.align;
320+
Allocation::new_empty_allocation(align.abi)
321+
}
322+
ConstValue::Slice { data, start, end } => {
323+
let alloc_id = tables.tcx.create_memory_alloc(data);
324+
let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start));
325+
let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
326+
let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize(
327+
(end - start) as u64,
328+
&tables.tcx,
329+
);
330+
let layout = tables
331+
.tcx
332+
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
333+
.unwrap();
334+
let mut allocation =
335+
rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
336+
allocation
337+
.write_scalar(
338+
&tables.tcx,
339+
alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
340+
scalar_ptr,
341+
)
342+
.unwrap();
343+
allocation
344+
.write_scalar(
345+
&tables.tcx,
346+
alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()),
347+
scalar_len,
348+
)
349+
.unwrap();
350+
allocation.stable(tables)
351+
}
352+
ConstValue::ByRef { alloc, offset } => {
353+
let ty_size = tables
354+
.tcx
355+
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
356+
.unwrap()
357+
.size;
358+
allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
359+
}
360+
}
361+
}
362+
363+
/// Creates an `Allocation` only from information within the `AllocRange`.
364+
pub fn allocation_filter<'tcx>(
365+
alloc: &rustc_middle::mir::interpret::Allocation,
366+
alloc_range: AllocRange,
367+
tables: &mut Tables<'tcx>,
368+
) -> Allocation {
369+
let mut bytes: Vec<Option<u8>> = alloc
370+
.inspect_with_uninit_and_ptr_outside_interpreter(
371+
alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
372+
)
373+
.iter()
374+
.copied()
375+
.map(Some)
376+
.collect();
377+
for (i, b) in bytes.iter_mut().enumerate() {
378+
if !alloc
379+
.init_mask()
380+
.get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize()))
381+
{
382+
*b = None;
383+
}
384+
}
385+
let mut ptrs = Vec::new();
386+
for (offset, prov) in alloc
387+
.provenance()
388+
.ptrs()
389+
.iter()
390+
.filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
391+
{
392+
ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), opaque(prov)));
393+
}
394+
Allocation {
395+
bytes: bytes,
396+
provenance: ProvenanceMap { ptrs },
397+
align: alloc.align.bytes(),
398+
mutability: alloc.mutability.stable(tables),
399+
}
400+
}
401+
402+
#[derive(Clone, Debug)]
403+
pub enum ConstantKind {
404+
Allocated(Allocation),
405+
Unevaluated(UnevaluatedConst),
406+
}
407+
408+
#[derive(Clone, Debug)]
409+
pub struct UnevaluatedConst {
410+
pub ty: Ty,
411+
pub def: ConstDef,
412+
pub args: GenericArgs,
413+
pub promoted: Option<Promoted>,
414+
}
415+
271416
pub enum TraitSpecializationKind {
272417
None,
273418
Marker,

0 commit comments

Comments
 (0)