Skip to content

Commit c5fd82d

Browse files
authored
Unrolled build for rust-lang#118012
Rollup merge of rust-lang#118012 - celinval:smir-alloc, r=ouz-a Add support for global allocation in smir Add APIs to StableMir to support global allocation. Before this change, StableMir users had no API available to retrieve Allocation provenance information. They had to resource to internal APIs instead. One example is retrieving the Allocation of an `&str`. See test for an example on how the API can be used.
2 parents 6d2b84b + c07a6d5 commit c5fd82d

File tree

9 files changed

+329
-26
lines changed

9 files changed

+329
-26
lines changed

compiler/rustc_smir/src/rustc_internal/internal.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
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::{
12-
AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, FloatTy,
13-
GenericArgKind, GenericArgs, IntTy, Region, RigidTy, TraitRef, Ty, UintTy,
13+
AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const,
14+
ExistentialTraitRef, FloatTy, GenericArgKind, GenericArgs, IntTy, Region, RigidTy, TraitRef,
15+
Ty, UintTy,
1416
};
15-
use stable_mir::{AllocId, CrateItem, DefId};
17+
use stable_mir::{CrateItem, DefId};
1618

1719
use super::RustcInternal;
1820

@@ -228,6 +230,17 @@ impl<'tcx> RustcInternal<'tcx> for BoundVariableKind {
228230
}
229231
}
230232

233+
impl<'tcx> RustcInternal<'tcx> for ExistentialTraitRef {
234+
type T = rustc_ty::ExistentialTraitRef<'tcx>;
235+
236+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
237+
rustc_ty::ExistentialTraitRef {
238+
def_id: self.def_id.0.internal(tables),
239+
args: self.generic_args.internal(tables),
240+
}
241+
}
242+
}
243+
231244
impl<'tcx> RustcInternal<'tcx> for TraitRef {
232245
type T = rustc_ty::TraitRef<'tcx>;
233246

@@ -276,3 +289,13 @@ where
276289
(*self).internal(tables)
277290
}
278291
}
292+
impl<'tcx, T> RustcInternal<'tcx> for Option<T>
293+
where
294+
T: RustcInternal<'tcx>,
295+
{
296+
type T = Option<T::T>;
297+
298+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
299+
self.as_ref().map(|inner| inner.internal(tables))
300+
}
301+
}

compiler/rustc_smir/src/rustc_internal/mod.rs

+1-1
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+
pub(crate) 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

+87-5
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,30 @@ 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+
334+
fn vtable_allocation(
335+
&self,
336+
global_alloc: &GlobalAlloc,
337+
) -> Option<stable_mir::mir::alloc::AllocId> {
338+
let mut tables = self.0.borrow_mut();
339+
let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else { return None };
340+
let alloc_id = tables
341+
.tcx
342+
.vtable_allocation((ty.internal(&mut *tables), trait_ref.internal(&mut *tables)));
343+
Some(alloc_id.stable(&mut *tables))
344+
}
345+
321346
fn usize_to_const(&self, val: u64) -> Result<Const, Error> {
322347
let mut tables = self.0.borrow_mut();
323348
let ty = tables.tcx.types.usize;
@@ -342,7 +367,7 @@ pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell<Tables<'tcx>>);
342367
pub struct Tables<'tcx> {
343368
pub(crate) tcx: TyCtxt<'tcx>,
344369
pub(crate) def_ids: IndexMap<DefId, stable_mir::DefId>,
345-
pub(crate) alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
370+
pub(crate) alloc_ids: IndexMap<AllocId, stable_mir::mir::alloc::AllocId>,
346371
pub(crate) spans: IndexMap<rustc_span::Span, Span>,
347372
pub(crate) types: IndexMap<Ty<'tcx>, stable_mir::ty::Ty>,
348373
pub(crate) instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
@@ -1590,6 +1615,14 @@ impl<'tcx> Stable<'tcx> for ty::BoundTy {
15901615
}
15911616
}
15921617

1618+
impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> {
1619+
type T = Allocation;
1620+
1621+
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1622+
self.inner().stable(tables)
1623+
}
1624+
}
1625+
15931626
impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
15941627
type T = stable_mir::ty::Allocation;
15951628

@@ -1602,6 +1635,32 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
16021635
}
16031636
}
16041637

1638+
impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
1639+
type T = stable_mir::mir::alloc::AllocId;
1640+
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1641+
tables.create_alloc_id(*self)
1642+
}
1643+
}
1644+
1645+
impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
1646+
type T = GlobalAlloc;
1647+
1648+
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1649+
match self {
1650+
mir::interpret::GlobalAlloc::Function(instance) => {
1651+
GlobalAlloc::Function(instance.stable(tables))
1652+
}
1653+
mir::interpret::GlobalAlloc::VTable(ty, trait_ref) => {
1654+
GlobalAlloc::VTable(ty.stable(tables), trait_ref.stable(tables))
1655+
}
1656+
mir::interpret::GlobalAlloc::Static(def) => {
1657+
GlobalAlloc::Static(tables.static_def(*def))
1658+
}
1659+
mir::interpret::GlobalAlloc::Memory(alloc) => GlobalAlloc::Memory(alloc.stable(tables)),
1660+
}
1661+
}
1662+
}
1663+
16051664
impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind {
16061665
type T = stable_mir::ty::TraitSpecializationKind;
16071666
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
@@ -1989,6 +2048,14 @@ impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
19892048
}
19902049
}
19912050

2051+
impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
2052+
type T = Error;
2053+
2054+
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
2055+
Error::new(format!("{self:?}"))
2056+
}
2057+
}
2058+
19922059
impl<'tcx, T> Stable<'tcx> for &T
19932060
where
19942061
T: Stable<'tcx>,
@@ -2010,3 +2077,18 @@ where
20102077
self.as_ref().map(|value| value.stable(tables))
20112078
}
20122079
}
2080+
2081+
impl<'tcx, T, E> Stable<'tcx> for Result<T, E>
2082+
where
2083+
T: Stable<'tcx>,
2084+
E: Stable<'tcx>,
2085+
{
2086+
type T = Result<T::T, E::T>;
2087+
2088+
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
2089+
match self {
2090+
Ok(val) => Ok(val.stable(tables)),
2091+
Err(error) => Err(error.stable(tables)),
2092+
}
2093+
}
2094+
}

compiler/stable_mir/src/lib.rs

+18-15
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,15 @@ 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;
294+
295+
/// Retrieve the id for the virtual table.
296+
fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>;
294297
}
295298

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

compiler/stable_mir/src/mir.rs

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

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//! This module provides methods to retrieve allocation information, such as static variables.
2+
use crate::mir::mono::{Instance, StaticDef};
3+
use crate::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty};
4+
use crate::with;
5+
6+
/// An allocation in the SMIR global memory can be either a function pointer,
7+
/// a static, or a "real" allocation with some data in it.
8+
#[derive(Debug, Clone, Eq, PartialEq)]
9+
pub enum GlobalAlloc {
10+
/// The alloc ID is used as a function pointer.
11+
Function(Instance),
12+
/// This alloc ID points to a symbolic (not-reified) vtable.
13+
/// The `None` trait ref is used to represent auto traits.
14+
VTable(Ty, Option<Binder<ExistentialTraitRef>>),
15+
/// The alloc ID points to a "lazy" static variable that did not get computed (yet).
16+
/// This is also used to break the cycle in recursive statics.
17+
Static(StaticDef),
18+
/// The alloc ID points to memory.
19+
Memory(Allocation),
20+
}
21+
22+
impl From<AllocId> for GlobalAlloc {
23+
fn from(value: AllocId) -> Self {
24+
with(|cx| cx.global_alloc(value))
25+
}
26+
}
27+
28+
impl GlobalAlloc {
29+
/// Retrieve the allocation id for a global allocation if it exists.
30+
///
31+
/// For `[GlobalAlloc::VTable]`, this will return the allocation for the VTable of the given
32+
/// type for the optional trait if the type implements the trait.
33+
///
34+
/// This method will always return `None` for allocations other than `[GlobalAlloc::VTable]`.
35+
pub fn vtable_allocation(&self) -> Option<AllocId> {
36+
with(|cx| cx.vtable_allocation(self))
37+
}
38+
}
39+
40+
/// A unique identification number for each provenance
41+
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
42+
pub struct AllocId(usize);
43+
44+
impl IndexedVal for AllocId {
45+
fn to_val(index: usize) -> Self {
46+
AllocId(index)
47+
}
48+
fn to_index(&self) -> usize {
49+
self.0
50+
}
51+
}

compiler/stable_mir/src/mir/mono.rs

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

0 commit comments

Comments
 (0)