Skip to content

Commit fa5ff85

Browse files
committed
Add support to global allocation to stable-mir
1 parent ed10a53 commit fa5ff85

File tree

8 files changed

+150
-24
lines changed

8 files changed

+150
-24
lines changed

compiler/rustc_smir/src/rustc_internal/internal.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
use crate::rustc_smir::Tables;
88
use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy};
99
use rustc_span::Symbol;
10+
use stable_mir::mir::alloc::AllocId;
1011
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
1112
use stable_mir::ty::{
1213
AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, FloatTy,
1314
GenericArgKind, GenericArgs, IntTy, Region, RigidTy, TraitRef, Ty, UintTy,
1415
};
15-
use stable_mir::{AllocId, CrateItem, DefId};
16+
use stable_mir::{CrateItem, DefId};
1617

1718
use super::RustcInternal;
1819

compiler/rustc_smir/src/rustc_internal/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ impl<'tcx> Tables<'tcx> {
118118
self.def_ids.create_or_fetch(did)
119119
}
120120

121-
fn create_alloc_id(&mut self, aid: AllocId) -> stable_mir::AllocId {
121+
fn create_alloc_id(&mut self, aid: AllocId) -> stable_mir::mir::alloc::AllocId {
122122
self.alloc_ids.create_or_fetch(aid)
123123
}
124124

compiler/rustc_smir/src/rustc_smir/mod.rs

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@ use rustc_middle::mir::mono::MonoItem;
1717
use rustc_middle::ty::{self, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, Variance};
1818
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
1919
use rustc_target::abi::FieldIdx;
20-
use stable_mir::mir::mono::InstanceDef;
20+
use stable_mir::mir::alloc::GlobalAlloc;
21+
use stable_mir::mir::mono::{InstanceDef, StaticDef};
2122
use stable_mir::mir::{
2223
Body, ConstOperand, CopyNonOverlapping, Statement, UserTypeProjection, VarDebugInfoFragment,
2324
VariantIdx,
2425
};
2526
use stable_mir::ty::{
26-
AdtDef, AdtKind, ClosureDef, ClosureKind, Const, ConstId, ConstantKind, EarlyParamRegion,
27-
FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span,
28-
TyKind, UintTy,
27+
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, ConstId, ConstantKind,
28+
EarlyParamRegion, FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability,
29+
RigidTy, Span, TyKind, UintTy,
2930
};
3031
use stable_mir::{self, opaque, Context, CrateItem, Error, Filename, ItemKind};
3132
use std::cell::RefCell;
@@ -318,6 +319,18 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
318319
.ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
319320
}
320321

322+
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
323+
let mut tables = self.0.borrow_mut();
324+
let def_id = def.0.internal(&mut *tables);
325+
tables.tcx.eval_static_initializer(def_id).stable(&mut *tables)
326+
}
327+
328+
fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc {
329+
let mut tables = self.0.borrow_mut();
330+
let alloc_id = alloc.internal(&mut *tables);
331+
tables.tcx.global_alloc(alloc_id).stable(&mut *tables)
332+
}
333+
321334
fn usize_to_const(&self, val: u64) -> Result<Const, Error> {
322335
let mut tables = self.0.borrow_mut();
323336
let ty = tables.tcx.types.usize;
@@ -342,7 +355,7 @@ pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell<Tables<'tcx>>);
342355
pub struct Tables<'tcx> {
343356
pub(crate) tcx: TyCtxt<'tcx>,
344357
pub(crate) def_ids: IndexMap<DefId, stable_mir::DefId>,
345-
pub(crate) alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
358+
pub(crate) alloc_ids: IndexMap<AllocId, stable_mir::mir::alloc::AllocId>,
346359
pub(crate) spans: IndexMap<rustc_span::Span, Span>,
347360
pub(crate) types: IndexMap<Ty<'tcx>, stable_mir::ty::Ty>,
348361
pub(crate) instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
@@ -1590,6 +1603,14 @@ impl<'tcx> Stable<'tcx> for ty::BoundTy {
15901603
}
15911604
}
15921605

1606+
impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> {
1607+
type T = Allocation;
1608+
1609+
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1610+
self.inner().stable(tables)
1611+
}
1612+
}
1613+
15931614
impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
15941615
type T = stable_mir::ty::Allocation;
15951616

@@ -1602,6 +1623,25 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
16021623
}
16031624
}
16041625

1626+
impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
1627+
type T = GlobalAlloc;
1628+
1629+
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1630+
match self {
1631+
mir::interpret::GlobalAlloc::Function(instance) => {
1632+
GlobalAlloc::Function(instance.stable(tables))
1633+
}
1634+
mir::interpret::GlobalAlloc::VTable(ty, trait_ref) => {
1635+
GlobalAlloc::VTable(ty.stable(tables), trait_ref.stable(tables))
1636+
}
1637+
mir::interpret::GlobalAlloc::Static(def) => {
1638+
GlobalAlloc::Static(tables.static_def(*def))
1639+
}
1640+
mir::interpret::GlobalAlloc::Memory(alloc) => GlobalAlloc::Memory(alloc.stable(tables)),
1641+
}
1642+
}
1643+
}
1644+
16051645
impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind {
16061646
type T = stable_mir::ty::TraitSpecializationKind;
16071647
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
@@ -1989,6 +2029,14 @@ impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
19892029
}
19902030
}
19912031

2032+
impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
2033+
type T = Error;
2034+
2035+
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
2036+
Error::new(format!("{self:?}"))
2037+
}
2038+
}
2039+
19922040
impl<'tcx, T> Stable<'tcx> for &T
19932041
where
19942042
T: Stable<'tcx>,
@@ -2010,3 +2058,18 @@ where
20102058
self.as_ref().map(|value| value.stable(tables))
20112059
}
20122060
}
2061+
2062+
impl<'tcx, T, E> Stable<'tcx> for Result<T, E>
2063+
where
2064+
T: Stable<'tcx>,
2065+
E: Stable<'tcx>,
2066+
{
2067+
type T = Result<T::T, E::T>;
2068+
2069+
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
2070+
match self {
2071+
Ok(val) => Ok(val.stable(tables)),
2072+
Err(error) => Err(error.stable(tables)),
2073+
}
2074+
}
2075+
}

compiler/stable_mir/src/lib.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//! The goal is to eventually be published on
1818
//! [crates.io](https://crates.io).
1919
20-
use crate::mir::mono::InstanceDef;
20+
use crate::mir::mono::{InstanceDef, StaticDef};
2121
use crate::mir::Body;
2222
use std::fmt;
2323
use std::fmt::Debug;
@@ -37,9 +37,10 @@ pub mod mir;
3737
pub mod ty;
3838
pub mod visitor;
3939

40+
use crate::mir::alloc::{AllocId, GlobalAlloc};
4041
use crate::mir::pretty::function_name;
4142
use crate::mir::Mutability;
42-
use crate::ty::{AdtDef, AdtKind, ClosureDef, ClosureKind, Const, RigidTy};
43+
use crate::ty::{AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, RigidTy};
4344
pub use error::*;
4445
use mir::mono::Instance;
4546
use ty::{FnDef, GenericArgs};
@@ -73,19 +74,6 @@ impl IndexedVal for DefId {
7374
}
7475
}
7576

76-
/// A unique identification number for each provenance
77-
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
78-
pub struct AllocId(usize);
79-
80-
impl IndexedVal for AllocId {
81-
fn to_val(index: usize) -> Self {
82-
AllocId(index)
83-
}
84-
fn to_index(&self) -> usize {
85-
self.0
86-
}
87-
}
88-
8977
/// A list of crate items.
9078
pub type CrateItems = Vec<CrateItem>;
9179

@@ -141,6 +129,10 @@ impl CrateItem {
141129
with(|cx| cx.def_ty(self.0))
142130
}
143131

132+
pub fn is_foreign_item(&self) -> bool {
133+
with(|cx| cx.is_foreign_item(*self))
134+
}
135+
144136
pub fn dump<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
145137
writeln!(w, "{}", function_name(*self))?;
146138
self.body().dump(w)
@@ -190,6 +182,8 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
190182
with(|cx| cx.trait_impl(trait_impl))
191183
}
192184

185+
/// This trait defines the interface between stable_mir and the Rust compiler.
186+
/// Do not use this directly.
193187
pub trait Context {
194188
fn entry_fn(&self) -> Option<CrateItem>;
195189
/// Retrieve all items of the local crate that have a MIR associated with them.
@@ -291,6 +285,12 @@ pub trait Context {
291285
args: &GenericArgs,
292286
kind: ClosureKind,
293287
) -> Option<Instance>;
288+
289+
/// Evaluate a static's initializer.
290+
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error>;
291+
292+
/// Retrieve global allocation for the given allocation ID.
293+
fn global_alloc(&self, id: AllocId) -> GlobalAlloc;
294294
}
295295

296296
// A thread local variable that stores a pointer to the tables mapping between TyCtxt

compiler/stable_mir/src/mir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod alloc;
12
mod body;
23
pub mod mono;
34
pub mod pretty;

compiler/stable_mir/src/mir/alloc.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use crate::mir::mono::{Instance, StaticDef};
2+
use crate::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty};
3+
use crate::with;
4+
5+
/// An allocation in the SMIR global memory can be either a function pointer,
6+
/// a static, or a "real" allocation with some data in it.
7+
#[derive(Debug, Clone, Eq, PartialEq)]
8+
pub enum GlobalAlloc {
9+
/// The alloc ID is used as a function pointer.
10+
Function(Instance),
11+
/// This alloc ID points to a symbolic (not-reified) vtable.
12+
VTable(Ty, Option<Binder<ExistentialTraitRef>>),
13+
/// The alloc ID points to a "lazy" static variable that did not get computed (yet).
14+
/// This is also used to break the cycle in recursive statics.
15+
Static(StaticDef),
16+
/// The alloc ID points to memory.
17+
Memory(Allocation),
18+
}
19+
20+
impl From<AllocId> for GlobalAlloc {
21+
fn from(value: AllocId) -> Self {
22+
with(|cx| cx.global_alloc(value))
23+
}
24+
}
25+
26+
/// A unique identification number for each provenance
27+
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
28+
pub struct AllocId(usize);
29+
30+
impl IndexedVal for AllocId {
31+
fn to_val(index: usize) -> Self {
32+
AllocId(index)
33+
}
34+
fn to_index(&self) -> usize {
35+
self.0
36+
}
37+
}

compiler/stable_mir/src/mir/mono.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::mir::Body;
2-
use crate::ty::{ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty};
2+
use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty};
33
use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque};
44
use std::fmt::{Debug, Formatter};
55

@@ -37,6 +37,11 @@ impl Instance {
3737
with(|context| context.instance_body(self.def))
3838
}
3939

40+
pub fn is_foreign_item(&self) -> bool {
41+
let item = CrateItem::try_from(*self);
42+
item.as_ref().map_or(false, CrateItem::is_foreign_item)
43+
}
44+
4045
/// Get the instance type with generic substitutions applied and lifetimes erased.
4146
pub fn ty(&self) -> Ty {
4247
with(|context| context.instance_ty(self.def))
@@ -128,6 +133,18 @@ impl From<Instance> for MonoItem {
128133
}
129134
}
130135

136+
impl From<StaticDef> for MonoItem {
137+
fn from(value: StaticDef) -> Self {
138+
MonoItem::Static(value)
139+
}
140+
}
141+
142+
impl From<StaticDef> for CrateItem {
143+
fn from(value: StaticDef) -> Self {
144+
CrateItem(value.0)
145+
}
146+
}
147+
131148
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
132149
pub struct InstanceDef(usize);
133150

@@ -147,9 +164,15 @@ impl TryFrom<CrateItem> for StaticDef {
147164
}
148165

149166
impl StaticDef {
167+
/// Return the type of this static definition.
150168
pub fn ty(&self) -> Ty {
151169
with(|cx| cx.def_ty(self.0))
152170
}
171+
172+
/// Evaluate a static's initializer, returning the allocation of the initializer's memory.
173+
pub fn eval_initializer(&self) -> Result<Allocation, Error> {
174+
with(|cx| cx.eval_static_initializer(*self))
175+
}
153176
}
154177

155178
impl IndexedVal for InstanceDef {

compiler/stable_mir/src/ty.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use super::{
22
mir::Safety,
33
mir::{Body, Mutability},
4-
with, AllocId, DefId, Error, Symbol,
4+
with, DefId, Error, Symbol,
55
};
6+
use crate::mir::alloc::AllocId;
67
use crate::{Filename, Opaque};
78
use std::fmt::{self, Debug, Display, Formatter};
89

0 commit comments

Comments
 (0)