Skip to content

Commit 0d18128

Browse files
committed
refactor: split rustc_smir::alloc into two parts
The previous `rustc_smir::alloc` had many direct calls to rustc queries. This commit splits it into two parts: `rustc_smir::alloc` and `stable_mir::alloc`. Following the same pattern as `SmirCtxt` and `SmirInterface`, the `rustc_smir::alloc` handles all direct interactions with rustc queries and performs the actual memory allocations, while the `stable_mir::alloc` is responsible for constructing stable components.
1 parent 2d4e300 commit 0d18128

File tree

4 files changed

+151
-99
lines changed

4 files changed

+151
-99
lines changed
Lines changed: 63 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,74 @@
1-
use rustc_abi::{Align, Size};
2-
use rustc_middle::mir::ConstValue;
3-
use rustc_middle::mir::interpret::{AllocInit, AllocRange, Pointer, alloc_range};
4-
use stable_mir::Error;
5-
use stable_mir::mir::Mutability;
6-
use stable_mir::ty::{Allocation, ProvenanceMap};
1+
//! Internal memory allocator implementation for StableMIR.
2+
//!
3+
//! This module handles all direct interactions with rustc queries and performs
4+
//! the actual memory allocations. The stable interface in `stable_mir::alloc`
5+
//! delegates all query-related operations to this implementation.
76
8-
use crate::rustc_smir::{Stable, Tables};
9-
use crate::stable_mir;
7+
use rustc_abi::{Size, TyAndLayout};
8+
use rustc_middle::mir::interpret::{
9+
AllocId, AllocInit, AllocRange, Allocation, ConstAllocation, Pointer, Scalar, alloc_range,
10+
};
11+
use rustc_middle::ty::Ty;
1012

11-
/// Creates new empty `Allocation` from given `Align`.
12-
fn new_empty_allocation(align: Align) -> Allocation {
13-
Allocation {
14-
bytes: Vec::new(),
15-
provenance: ProvenanceMap { ptrs: Vec::new() },
16-
align: align.bytes(),
17-
mutability: Mutability::Not,
18-
}
13+
use crate::rustc_smir::{Bridge, SmirError, Tables};
14+
15+
pub fn try_new_scalar<'tcx, B: Bridge>(
16+
layout: TyAndLayout<'tcx, Ty<'tcx>>,
17+
scalar: Scalar,
18+
tables: &mut Tables<'tcx, B>,
19+
) -> Result<Allocation, B::Error> {
20+
let size = scalar.size();
21+
let mut allocation = Allocation::new(size, layout.align.abi, AllocInit::Uninit, ());
22+
allocation
23+
.write_scalar(&tables.tcx, alloc_range(Size::ZERO, size), scalar)
24+
.map_err(|e| B::Error::from_internal(e))?;
25+
26+
Ok(allocation)
1927
}
2028

21-
// We need this method instead of a Stable implementation
22-
// because we need to get `Ty` of the const we are trying to create, to do that
23-
// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
24-
#[allow(rustc::usage_of_qualified_ty)]
25-
pub(crate) fn new_allocation<'tcx>(
26-
ty: rustc_middle::ty::Ty<'tcx>,
27-
const_value: ConstValue<'tcx>,
28-
tables: &mut Tables<'tcx>,
29-
) -> Allocation {
30-
try_new_allocation(ty, const_value, tables)
31-
.unwrap_or_else(|_| panic!("Failed to convert: {const_value:?} to {ty:?}"))
29+
pub fn try_new_slice<'tcx, B: Bridge>(
30+
layout: TyAndLayout<'tcx, Ty<'tcx>>,
31+
data: ConstAllocation<'tcx>,
32+
meta: u64,
33+
tables: &mut Tables<'tcx, B>,
34+
) -> Result<Allocation, B::Error> {
35+
let alloc_id = tables.tcx.reserve_and_set_memory_alloc(data);
36+
let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
37+
let scalar_ptr = Scalar::from_pointer(ptr, &tables.tcx);
38+
let scalar_meta: Scalar = Scalar::from_target_usize(meta, &tables.tcx);
39+
let mut allocation = Allocation::new(layout.size, layout.align.abi, AllocInit::Uninit, ());
40+
allocation
41+
.write_scalar(
42+
&tables.tcx,
43+
alloc_range(Size::ZERO, tables.tcx.data_layout.pointer_size),
44+
scalar_ptr,
45+
)
46+
.map_err(|e| B::Error::from_internal(e))?;
47+
allocation
48+
.write_scalar(
49+
&tables.tcx,
50+
alloc_range(tables.tcx.data_layout.pointer_size, scalar_meta.size()),
51+
scalar_meta,
52+
)
53+
.map_err(|e| B::Error::from_internal(e))?;
54+
55+
Ok(allocation)
3256
}
3357

34-
#[allow(rustc::usage_of_qualified_ty)]
35-
pub(crate) fn try_new_allocation<'tcx>(
36-
ty: rustc_middle::ty::Ty<'tcx>,
37-
const_value: ConstValue<'tcx>,
38-
tables: &mut Tables<'tcx>,
39-
) -> Result<Allocation, Error> {
40-
let layout = tables
41-
.tcx
42-
.layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty))
43-
.map_err(|e| e.stable(tables))?;
44-
Ok(match const_value {
45-
ConstValue::Scalar(scalar) => {
46-
let size = scalar.size();
47-
let mut allocation = rustc_middle::mir::interpret::Allocation::new(
48-
size,
49-
layout.align.abi,
50-
AllocInit::Uninit,
51-
(),
52-
);
53-
allocation
54-
.write_scalar(&tables.tcx, alloc_range(Size::ZERO, size), scalar)
55-
.map_err(|e| e.stable(tables))?;
56-
allocation.stable(tables)
57-
}
58-
ConstValue::ZeroSized => new_empty_allocation(layout.align.abi),
59-
ConstValue::Slice { data, meta } => {
60-
let alloc_id = tables.tcx.reserve_and_set_memory_alloc(data);
61-
let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
62-
let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
63-
let scalar_meta =
64-
rustc_middle::mir::interpret::Scalar::from_target_usize(meta, &tables.tcx);
65-
let mut allocation = rustc_middle::mir::interpret::Allocation::new(
66-
layout.size,
67-
layout.align.abi,
68-
AllocInit::Uninit,
69-
(),
70-
);
71-
allocation
72-
.write_scalar(
73-
&tables.tcx,
74-
alloc_range(Size::ZERO, tables.tcx.data_layout.pointer_size),
75-
scalar_ptr,
76-
)
77-
.map_err(|e| e.stable(tables))?;
78-
allocation
79-
.write_scalar(
80-
&tables.tcx,
81-
alloc_range(tables.tcx.data_layout.pointer_size, scalar_meta.size()),
82-
scalar_meta,
83-
)
84-
.map_err(|e| e.stable(tables))?;
85-
allocation.stable(tables)
86-
}
87-
ConstValue::Indirect { alloc_id, offset } => {
88-
let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory();
89-
allocation_filter(&alloc.0, alloc_range(offset, layout.size), tables)
90-
}
91-
})
58+
pub fn try_new_indirect<'tcx, B: Bridge>(
59+
alloc_id: AllocId,
60+
tables: &mut Tables<'tcx, B>,
61+
) -> ConstAllocation<'tcx> {
62+
let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory();
63+
64+
alloc
9265
}
9366

9467
/// Creates an `Allocation` only from information within the `AllocRange`.
95-
pub(super) fn allocation_filter<'tcx>(
68+
pub fn allocation_filter(
9669
alloc: &rustc_middle::mir::interpret::Allocation,
9770
alloc_range: AllocRange,
98-
tables: &mut Tables<'tcx>,
99-
) -> Allocation {
71+
) -> (Vec<Option<u8>>, Vec<(usize, AllocId)>) {
10072
let mut bytes: Vec<Option<u8>> = alloc
10173
.inspect_with_uninit_and_ptr_outside_interpreter(
10274
alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
@@ -117,15 +89,8 @@ pub(super) fn allocation_filter<'tcx>(
11789
.iter()
11890
.filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
11991
{
120-
ptrs.push((
121-
offset.bytes_usize() - alloc_range.start.bytes_usize(),
122-
tables.prov(prov.alloc_id()),
123-
));
124-
}
125-
Allocation {
126-
bytes,
127-
provenance: ProvenanceMap { ptrs },
128-
align: alloc.align.bytes(),
129-
mutability: alloc.mutability.stable(tables),
92+
ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), prov.alloc_id()));
13093
}
94+
95+
(bytes, ptrs)
13196
}

compiler/rustc_smir/src/rustc_smir/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
1919

2020
use crate::rustc_internal::IndexMap;
2121

22-
mod alloc;
22+
pub mod alloc;
2323
mod builder;
2424
pub mod context;
2525
mod convert;
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//! Memory allocation implementation for StableMIR.
2+
//!
3+
//! This module is responsible for constructing stable components.
4+
//! All operations requiring rustc queries must be delegated
5+
//! to `rustc_smir::alloc` to maintain stability guarantees.
6+
7+
use rustc_abi::Align;
8+
use rustc_middle::mir::ConstValue;
9+
use rustc_middle::mir::interpret::AllocRange;
10+
use rustc_smir::context::SmirCtxt;
11+
use rustc_smir::{SmirError, Tables, alloc};
12+
13+
use super::Error;
14+
use super::compiler_interface::BridgeTys;
15+
use super::convert::Stable;
16+
use super::mir::Mutability;
17+
use super::ty::{Allocation, ProvenanceMap};
18+
use crate::rustc_smir;
19+
20+
/// Creates new empty `Allocation` from given `Align`.
21+
fn new_empty_allocation(align: Align) -> Allocation {
22+
Allocation {
23+
bytes: Vec::new(),
24+
provenance: ProvenanceMap { ptrs: Vec::new() },
25+
align: align.bytes(),
26+
mutability: Mutability::Not,
27+
}
28+
}
29+
30+
// We need this method instead of a Stable implementation
31+
// because we need to get `Ty` of the const we are trying to create, to do that
32+
// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
33+
#[allow(rustc::usage_of_qualified_ty)]
34+
pub(crate) fn new_allocation<'tcx>(
35+
ty: rustc_middle::ty::Ty<'tcx>,
36+
const_value: ConstValue<'tcx>,
37+
tables: &mut Tables<'tcx, BridgeTys>,
38+
cx: &SmirCtxt<'tcx, BridgeTys>,
39+
) -> Allocation {
40+
try_new_allocation(ty, const_value, tables, cx)
41+
.unwrap_or_else(|_| panic!("Failed to convert: {const_value:?} to {ty:?}"))
42+
}
43+
44+
#[allow(rustc::usage_of_qualified_ty)]
45+
pub(crate) fn try_new_allocation<'tcx>(
46+
ty: rustc_middle::ty::Ty<'tcx>,
47+
const_value: ConstValue<'tcx>,
48+
tables: &mut Tables<'tcx, BridgeTys>,
49+
cx: &SmirCtxt<'tcx, BridgeTys>,
50+
) -> Result<Allocation, Error> {
51+
use rustc_smir::context::SmirTypingEnv;
52+
let layout = cx
53+
.layout_of(cx.fully_monomorphized().as_query_input(ty))
54+
.map_err(|e| Error::from_internal(e))?;
55+
match const_value {
56+
ConstValue::Scalar(scalar) => {
57+
alloc::try_new_scalar(layout, scalar, tables).map(|alloc| alloc.stable(tables, cx))
58+
}
59+
ConstValue::ZeroSized => Ok(new_empty_allocation(layout.align.abi)),
60+
ConstValue::Slice { data, meta } => {
61+
alloc::try_new_slice(layout, data, meta, tables).map(|alloc| alloc.stable(tables, cx))
62+
}
63+
ConstValue::Indirect { alloc_id, offset } => {
64+
let alloc = alloc::try_new_indirect(alloc_id, tables);
65+
use rustc_smir::context::SmirAllocRange;
66+
Ok(allocation_filter(&alloc.0, cx.alloc_range(offset, layout.size), tables, cx))
67+
}
68+
}
69+
}
70+
71+
/// Creates an `Allocation` only from information within the `AllocRange`.
72+
pub(super) fn allocation_filter<'tcx>(
73+
alloc: &rustc_middle::mir::interpret::Allocation,
74+
alloc_range: AllocRange,
75+
tables: &mut Tables<'tcx, BridgeTys>,
76+
cx: &SmirCtxt<'tcx, BridgeTys>,
77+
) -> Allocation {
78+
let (bytes, ptrs) = alloc::allocation_filter(alloc, alloc_range);
79+
let ptrs = ptrs.iter().map(|(i, aid)| (*i, tables.prov(*aid))).collect();
80+
Allocation {
81+
bytes,
82+
provenance: ProvenanceMap { ptrs },
83+
align: alloc.align.bytes(),
84+
mutability: alloc.mutability.stable(tables, cx),
85+
}
86+
}

compiler/rustc_smir/src/stable_mir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use stable_mir::ty::{AssocItem, FnDef, ForeignModuleDef, ImplDef, Span, TraitDef
4040
use crate::{rustc_smir, stable_mir};
4141

4242
pub mod abi;
43+
mod alloc;
4344
#[macro_use]
4445
pub mod crate_def;
4546
pub mod compiler_interface;

0 commit comments

Comments
 (0)