Skip to content

Commit 09a6316

Browse files
committed
refactor: separate rustc_smir::alloc into two parts
1 parent 1204d0c commit 09a6316

File tree

3 files changed

+150
-97
lines changed

3 files changed

+150
-97
lines changed
+63-96
Original file line numberDiff line numberDiff line change
@@ -1,100 +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-
allocation
53-
.write_scalar(&tables.tcx, alloc_range(Size::ZERO, size), scalar)
54-
.map_err(|e| e.stable(tables))?;
55-
allocation.stable(tables)
56-
}
57-
ConstValue::ZeroSized => new_empty_allocation(layout.align.abi),
58-
ConstValue::Slice { data, meta } => {
59-
let alloc_id = tables.tcx.reserve_and_set_memory_alloc(data);
60-
let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
61-
let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
62-
let scalar_meta =
63-
rustc_middle::mir::interpret::Scalar::from_target_usize(meta, &tables.tcx);
64-
let mut allocation = rustc_middle::mir::interpret::Allocation::new(
65-
layout.size,
66-
layout.align.abi,
67-
AllocInit::Uninit,
68-
);
69-
allocation
70-
.write_scalar(
71-
&tables.tcx,
72-
alloc_range(Size::ZERO, tables.tcx.data_layout.pointer_size),
73-
scalar_ptr,
74-
)
75-
.map_err(|e| e.stable(tables))?;
76-
allocation
77-
.write_scalar(
78-
&tables.tcx,
79-
alloc_range(tables.tcx.data_layout.pointer_size, scalar_meta.size()),
80-
scalar_meta,
81-
)
82-
.map_err(|e| e.stable(tables))?;
83-
allocation.stable(tables)
84-
}
85-
ConstValue::Indirect { alloc_id, offset } => {
86-
let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory();
87-
allocation_filter(&alloc.0, alloc_range(offset, layout.size), tables)
88-
}
89-
})
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
9065
}
9166

9267
/// Creates an `Allocation` only from information within the `AllocRange`.
93-
pub(super) fn allocation_filter<'tcx>(
68+
pub fn allocation_filter(
9469
alloc: &rustc_middle::mir::interpret::Allocation,
9570
alloc_range: AllocRange,
96-
tables: &mut Tables<'tcx>,
97-
) -> Allocation {
71+
) -> (Vec<Option<u8>>, Vec<(usize, AllocId)>) {
9872
let mut bytes: Vec<Option<u8>> = alloc
9973
.inspect_with_uninit_and_ptr_outside_interpreter(
10074
alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
@@ -115,15 +89,8 @@ pub(super) fn allocation_filter<'tcx>(
11589
.iter()
11690
.filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
11791
{
118-
ptrs.push((
119-
offset.bytes_usize() - alloc_range.start.bytes_usize(),
120-
tables.prov(prov.alloc_id()),
121-
));
122-
}
123-
Allocation {
124-
bytes,
125-
provenance: ProvenanceMap { ptrs },
126-
align: alloc.align.bytes(),
127-
mutability: alloc.mutability.stable(tables),
92+
ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), prov.alloc_id()));
12893
}
94+
95+
(bytes, ptrs)
12996
}

compiler/rustc_smir/src/rustc_smir/mod.rs

+1-1
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

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+
}

0 commit comments

Comments
 (0)