Skip to content

Commit c41339a

Browse files
committed
Convert Const to Allocation in smir
1 parent 63a81b0 commit c41339a

File tree

4 files changed

+149
-3
lines changed

4 files changed

+149
-3
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

+29-2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
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::{new_allocation, FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy};
1313
use crate::stable_mir::{self, Context};
1414
use rustc_hir as hir;
1515
use rustc_middle::mir::coverage::CodeRegion;
16-
use rustc_middle::mir::{self};
16+
use rustc_middle::mir::{self, ConstantKind};
1717
use rustc_middle::ty::{self, Ty, TyCtxt, Variance};
1818
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
1919
use rustc_target::abi::FieldIdx;
@@ -1145,3 +1145,30 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef {
11451145
}
11461146
}
11471147
}
1148+
1149+
impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
1150+
type T = stable_mir::ty::ConstantKind;
1151+
1152+
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1153+
match self {
1154+
ConstantKind::Ty(c) => match c.kind() {
1155+
ty::Value(val) => {
1156+
let const_val = tables.tcx.valtree_to_const_val((c.ty(), val));
1157+
stable_mir::ty::ConstantKind::Allocated(new_allocation(self, const_val, tables))
1158+
}
1159+
_ => todo!(),
1160+
},
1161+
ConstantKind::Unevaluated(unev_const, ty) => {
1162+
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
1163+
ty: tables.intern_ty(*ty),
1164+
def: tables.const_def(unev_const.def),
1165+
args: unev_const.args.stable(tables),
1166+
promoted: unev_const.promoted.map(|u| u.as_u32()),
1167+
})
1168+
}
1169+
ConstantKind::Val(val, _) => {
1170+
stable_mir::ty::ConstantKind::Allocated(new_allocation(self, *val, tables))
1171+
}
1172+
}
1173+
}
1174+
}

compiler/rustc_smir/src/stable_mir/ty.rs

+113-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
use rustc_middle::mir::interpret::{alloc_range, 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,
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))
@@ -248,6 +256,7 @@ pub type Bytes = Vec<Option<u8>>;
248256
pub type Size = usize;
249257
pub type Prov = Opaque;
250258
pub type Align = u64;
259+
pub type Promoted = u32;
251260
pub type InitMaskMaterialized = Vec<u64>;
252261

253262
/// Stores the provenance information of pointers stored in memory.
@@ -266,6 +275,109 @@ pub struct Allocation {
266275
pub mutability: Mutability,
267276
}
268277

278+
impl Allocation {
279+
/// Creates new empty `Allocation` from given `Align`.
280+
fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
281+
Allocation {
282+
bytes: Vec::new(),
283+
provenance: ProvenanceMap { ptrs: Vec::new() },
284+
align: align.bytes(),
285+
mutability: Mutability::Not,
286+
}
287+
}
288+
}
289+
290+
// We need this method instead of a Stable implementation
291+
// because we need to get `Ty` of the const we are trying to create, to do that
292+
// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
293+
pub fn new_allocation<'tcx>(
294+
const_kind: &rustc_middle::mir::ConstantKind<'tcx>,
295+
const_value: ConstValue<'tcx>,
296+
tables: &mut Tables<'tcx>,
297+
) -> Allocation {
298+
match const_value {
299+
ConstValue::Scalar(scalar) => {
300+
let size = scalar.size();
301+
let align = tables
302+
.tcx
303+
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
304+
.unwrap()
305+
.align;
306+
let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
307+
allocation
308+
.write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
309+
.unwrap();
310+
allocation.stable(tables)
311+
}
312+
ConstValue::ZeroSized => {
313+
let align = tables
314+
.tcx
315+
.layout_of(rustc_middle::ty::ParamEnv::empty().and(const_kind.ty()))
316+
.unwrap()
317+
.align;
318+
Allocation::new_empty_allocation(align.abi)
319+
}
320+
ConstValue::Slice { data, start, end } => {
321+
let alloc_id = tables.tcx.create_memory_alloc(data);
322+
let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start));
323+
let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
324+
let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize(
325+
(end - start) as u64,
326+
&tables.tcx,
327+
);
328+
let layout = tables
329+
.tcx
330+
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
331+
.unwrap();
332+
let mut allocation =
333+
rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
334+
allocation
335+
.write_scalar(
336+
&tables.tcx,
337+
alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
338+
scalar_ptr,
339+
)
340+
.unwrap();
341+
allocation
342+
.write_scalar(
343+
&tables.tcx,
344+
alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()),
345+
scalar_len,
346+
)
347+
.unwrap();
348+
allocation.stable(tables)
349+
}
350+
ConstValue::ByRef { alloc, offset } => {
351+
let ty_size = tables
352+
.tcx
353+
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
354+
.unwrap()
355+
.size;
356+
let bytes = alloc.0.get_bytes_unchecked(alloc_range(offset, ty_size));
357+
let offset_allocation = rustc_middle::mir::interpret::Allocation::from_bytes(
358+
bytes,
359+
alloc.0.align,
360+
alloc.0.mutability,
361+
);
362+
offset_allocation.stable(tables)
363+
}
364+
}
365+
}
366+
367+
#[derive(Clone, Debug)]
368+
pub enum ConstantKind {
369+
Allocated(Allocation),
370+
Unevaluated(UnevaluatedConst),
371+
}
372+
373+
#[derive(Clone, Debug)]
374+
pub struct UnevaluatedConst {
375+
pub ty: Ty,
376+
pub def: ConstDef,
377+
pub args: GenericArgs,
378+
pub promoted: Option<Promoted>,
379+
}
380+
269381
pub enum TraitSpecializationKind {
270382
None,
271383
Marker,

0 commit comments

Comments
 (0)