Skip to content

Commit 2bd8131

Browse files
committed
Auto merge of #115346 - oli-obk:smir_const, r=spastorino
Some SMIR Const cleanups Only e1def3bd41b021ce87a5d639b10cdf4a7df1d0b5 is new logic, everywhere else I just used the implementations that y'all had already written. r? `@spastorino` cc `@ouz-a`
2 parents dca2d1f + 92cfd20 commit 2bd8131

File tree

3 files changed

+166
-152
lines changed

3 files changed

+166
-152
lines changed
+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer};
2+
3+
use crate::{
4+
rustc_internal::opaque,
5+
rustc_smir::{Stable, Tables},
6+
stable_mir::mir::Mutability,
7+
stable_mir::ty::{Allocation, ProvenanceMap},
8+
};
9+
10+
/// Creates new empty `Allocation` from given `Align`.
11+
fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
12+
Allocation {
13+
bytes: Vec::new(),
14+
provenance: ProvenanceMap { ptrs: Vec::new() },
15+
align: align.bytes(),
16+
mutability: Mutability::Not,
17+
}
18+
}
19+
20+
// We need this method instead of a Stable implementation
21+
// because we need to get `Ty` of the const we are trying to create, to do that
22+
// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
23+
#[allow(rustc::usage_of_qualified_ty)]
24+
pub fn new_allocation<'tcx>(
25+
ty: rustc_middle::ty::Ty<'tcx>,
26+
const_value: ConstValue<'tcx>,
27+
tables: &mut Tables<'tcx>,
28+
) -> Allocation {
29+
match const_value {
30+
ConstValue::Scalar(scalar) => {
31+
let size = scalar.size();
32+
let align = tables
33+
.tcx
34+
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
35+
.unwrap()
36+
.align;
37+
let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
38+
allocation
39+
.write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
40+
.unwrap();
41+
allocation.stable(tables)
42+
}
43+
ConstValue::ZeroSized => {
44+
let align =
45+
tables.tcx.layout_of(rustc_middle::ty::ParamEnv::empty().and(ty)).unwrap().align;
46+
new_empty_allocation(align.abi)
47+
}
48+
ConstValue::Slice { data, start, end } => {
49+
let alloc_id = tables.tcx.create_memory_alloc(data);
50+
let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start));
51+
let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
52+
let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize(
53+
(end - start) as u64,
54+
&tables.tcx,
55+
);
56+
let layout =
57+
tables.tcx.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)).unwrap();
58+
let mut allocation =
59+
rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
60+
allocation
61+
.write_scalar(
62+
&tables.tcx,
63+
alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
64+
scalar_ptr,
65+
)
66+
.unwrap();
67+
allocation
68+
.write_scalar(
69+
&tables.tcx,
70+
alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()),
71+
scalar_len,
72+
)
73+
.unwrap();
74+
allocation.stable(tables)
75+
}
76+
ConstValue::ByRef { alloc, offset } => {
77+
let ty_size = tables
78+
.tcx
79+
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
80+
.unwrap()
81+
.size;
82+
allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
83+
}
84+
}
85+
}
86+
87+
/// Creates an `Allocation` only from information within the `AllocRange`.
88+
pub(super) fn allocation_filter<'tcx>(
89+
alloc: &rustc_middle::mir::interpret::Allocation,
90+
alloc_range: AllocRange,
91+
tables: &mut Tables<'tcx>,
92+
) -> Allocation {
93+
let mut bytes: Vec<Option<u8>> = alloc
94+
.inspect_with_uninit_and_ptr_outside_interpreter(
95+
alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
96+
)
97+
.iter()
98+
.copied()
99+
.map(Some)
100+
.collect();
101+
for (i, b) in bytes.iter_mut().enumerate() {
102+
if !alloc
103+
.init_mask()
104+
.get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize()))
105+
{
106+
*b = None;
107+
}
108+
}
109+
let mut ptrs = Vec::new();
110+
for (offset, prov) in alloc
111+
.provenance()
112+
.ptrs()
113+
.iter()
114+
.filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
115+
{
116+
ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), opaque(prov)));
117+
}
118+
Allocation {
119+
bytes: bytes,
120+
provenance: ProvenanceMap { ptrs },
121+
align: alloc.align.bytes(),
122+
mutability: alloc.mutability.stable(tables),
123+
}
124+
}

compiler/rustc_smir/src/rustc_smir/mod.rs

+41-24
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99
1010
use crate::rustc_internal::{self, opaque};
1111
use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx};
12-
use crate::stable_mir::ty::{
13-
allocation_filter, new_allocation, Const, FloatTy, GenericParamDef, IntTy, Movability, RigidTy,
14-
TyKind, UintTy,
15-
};
12+
use crate::stable_mir::ty::{FloatTy, GenericParamDef, IntTy, Movability, RigidTy, TyKind, UintTy};
1613
use crate::stable_mir::{self, Context};
1714
use rustc_hir as hir;
1815
use rustc_middle::mir::interpret::alloc_range;
@@ -22,6 +19,8 @@ use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
2219
use rustc_target::abi::FieldIdx;
2320
use tracing::debug;
2421

22+
mod alloc;
23+
2524
impl<'tcx> Context for Tables<'tcx> {
2625
fn local_crate(&self) -> stable_mir::Crate {
2726
smir_crate(self.tcx, LOCAL_CRATE)
@@ -205,8 +204,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
205204
match self {
206205
Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)),
207206
Repeat(op, len) => {
208-
let cnst = ConstantKind::from_const(*len, tables.tcx);
209-
let len = Const { literal: cnst.stable(tables) };
207+
let len = len.stable(tables);
210208
stable_mir::mir::Rvalue::Repeat(op.stable(tables), len)
211209
}
212210
Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref(
@@ -394,8 +392,7 @@ impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
394392
match self {
395393
ty::TermKind::Ty(ty) => TermKind::Type(tables.intern_ty(*ty)),
396394
ty::TermKind::Const(cnst) => {
397-
let cnst = ConstantKind::from_const(*cnst, tables.tcx);
398-
let cnst = Const { literal: cnst.stable(tables) };
395+
let cnst = cnst.stable(tables);
399396
TermKind::Const(cnst)
400397
}
401398
}
@@ -1083,8 +1080,32 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
10831080
type T = stable_mir::ty::Const;
10841081

10851082
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1086-
let cnst = ConstantKind::from_const(*self, tables.tcx);
1087-
stable_mir::ty::Const { literal: cnst.stable(tables) }
1083+
stable_mir::ty::Const {
1084+
literal: match self.kind() {
1085+
ty::Value(val) => {
1086+
let const_val = tables.tcx.valtree_to_const_val((self.ty(), val));
1087+
stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
1088+
self.ty(),
1089+
const_val,
1090+
tables,
1091+
))
1092+
}
1093+
ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(&param)),
1094+
ty::ErrorCt(_) => unreachable!(),
1095+
ty::InferCt(_) => unreachable!(),
1096+
ty::BoundCt(_, _) => unimplemented!(),
1097+
ty::PlaceholderCt(_) => unimplemented!(),
1098+
ty::Unevaluated(uv) => {
1099+
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
1100+
ty: tables.intern_ty(self.ty()),
1101+
def: tables.const_def(uv.def),
1102+
args: uv.args.stable(tables),
1103+
promoted: None,
1104+
})
1105+
}
1106+
ty::ExprCt(_) => unimplemented!(),
1107+
},
1108+
}
10881109
}
10891110
}
10901111

@@ -1108,7 +1129,11 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
11081129
type T = stable_mir::ty::Allocation;
11091130

11101131
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1111-
allocation_filter(self, alloc_range(rustc_target::abi::Size::ZERO, self.size()), tables)
1132+
alloc::allocation_filter(
1133+
self,
1134+
alloc_range(rustc_target::abi::Size::ZERO, self.size()),
1135+
tables,
1136+
)
11121137
}
11131138
}
11141139

@@ -1155,26 +1180,18 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
11551180
type T = stable_mir::ty::ConstantKind;
11561181

11571182
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1158-
match self {
1159-
ConstantKind::Ty(c) => match c.kind() {
1160-
ty::Value(val) => {
1161-
let const_val = tables.tcx.valtree_to_const_val((c.ty(), val));
1162-
stable_mir::ty::ConstantKind::Allocated(new_allocation(self, const_val, tables))
1163-
}
1164-
ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(&param)),
1165-
ty::ErrorCt(_) => unreachable!(),
1166-
_ => unimplemented!(),
1167-
},
1183+
match *self {
1184+
ConstantKind::Ty(c) => c.stable(tables).literal,
11681185
ConstantKind::Unevaluated(unev_const, ty) => {
11691186
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
1170-
ty: tables.intern_ty(*ty),
1187+
ty: tables.intern_ty(ty),
11711188
def: tables.const_def(unev_const.def),
11721189
args: unev_const.args.stable(tables),
11731190
promoted: unev_const.promoted.map(|u| u.as_u32()),
11741191
})
11751192
}
1176-
ConstantKind::Val(val, _) => {
1177-
stable_mir::ty::ConstantKind::Allocated(new_allocation(self, *val, tables))
1193+
ConstantKind::Val(val, ty) => {
1194+
stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(ty, val, tables))
11781195
}
11791196
}
11801197
}

compiler/rustc_smir/src/stable_mir/ty.rs

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

94
#[derive(Copy, Clone, Debug)]
105
pub struct Ty(pub usize);
@@ -286,128 +281,6 @@ pub struct Allocation {
286281
pub mutability: Mutability,
287282
}
288283

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

0 commit comments

Comments
 (0)