Skip to content

Commit cd559ad

Browse files
committed
Add support to get virtual table allocation
1 parent 5a77f1d commit cd559ad

File tree

5 files changed

+89
-4
lines changed

5 files changed

+89
-4
lines changed

compiler/rustc_smir/src/rustc_internal/internal.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_span::Symbol;
1010
use stable_mir::mir::alloc::AllocId;
1111
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
1212
use stable_mir::ty::{
13-
Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, GenericArgKind,
14-
GenericArgs, Region, TraitRef, Ty,
13+
Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const,
14+
ExistentialTraitRef, GenericArgKind, GenericArgs, Region, TraitRef, Ty,
1515
};
1616
use stable_mir::{CrateItem, DefId};
1717

@@ -153,6 +153,17 @@ impl<'tcx> RustcInternal<'tcx> for BoundVariableKind {
153153
}
154154
}
155155

156+
impl<'tcx> RustcInternal<'tcx> for ExistentialTraitRef {
157+
type T = rustc_ty::ExistentialTraitRef<'tcx>;
158+
159+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
160+
rustc_ty::ExistentialTraitRef {
161+
def_id: self.def_id.0.internal(tables),
162+
args: self.generic_args.internal(tables),
163+
}
164+
}
165+
}
166+
156167
impl<'tcx> RustcInternal<'tcx> for TraitRef {
157168
type T = rustc_ty::TraitRef<'tcx>;
158169

@@ -194,3 +205,13 @@ where
194205
(*self).internal(tables)
195206
}
196207
}
208+
impl<'tcx, T> RustcInternal<'tcx> for Option<T>
209+
where
210+
T: RustcInternal<'tcx>,
211+
{
212+
type T = Option<T::T>;
213+
214+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
215+
self.as_ref().map(|inner| inner.internal(tables))
216+
}
217+
}

compiler/rustc_smir/src/rustc_internal/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl<'tcx> Tables<'tcx> {
117117
self.def_ids.create_or_fetch(did)
118118
}
119119

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

compiler/rustc_smir/src/rustc_smir/mod.rs

+55-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ use rustc_target::abi::FieldIdx;
2020
use stable_mir::mir::alloc::GlobalAlloc;
2121
use stable_mir::mir::mono::{InstanceDef, StaticDef};
2222
use stable_mir::mir::{Body, CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
23-
use stable_mir::ty::{AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, ConstId, ConstantKind, FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy, EarlyParamRegion};
23+
use stable_mir::ty::{
24+
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, ConstId, ConstantKind,
25+
EarlyParamRegion, FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability,
26+
RigidTy, Span, TyKind, UintTy,
27+
};
2428
use stable_mir::{self, opaque, Context, CrateItem, Error, Filename, ItemKind};
2529
use std::cell::RefCell;
2630
use tracing::debug;
@@ -312,6 +316,49 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
312316
let alloc_id = alloc.internal(&mut *tables);
313317
tables.tcx.global_alloc(alloc_id).stable(&mut *tables)
314318
}
319+
320+
fn vtable_allocation(
321+
&self,
322+
global_alloc: &GlobalAlloc,
323+
) -> Option<stable_mir::mir::alloc::AllocId> {
324+
let mut tables = self.0.borrow_mut();
325+
let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else { return None };
326+
let alloc_id = tables
327+
.tcx
328+
.vtable_allocation((ty.internal(&mut *tables), trait_ref.internal(&mut *tables)));
329+
Some(alloc_id.stable(&mut *tables))
330+
}
331+
332+
fn adt_is_box(&self, def: AdtDef) -> bool {
333+
let mut tables = self.0.borrow_mut();
334+
def.internal(&mut *tables).is_box()
335+
}
336+
337+
fn eval_target_usize(&self, cnst: &Const) -> Result<u64, Error> {
338+
let mut tables = self.0.borrow_mut();
339+
let mir_const = cnst.internal(&mut *tables);
340+
mir_const
341+
.try_eval_target_usize(tables.tcx, ParamEnv::empty())
342+
.ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
343+
}
344+
345+
fn usize_to_const(&self, val: u64) -> Result<Const, Error> {
346+
let mut tables = self.0.borrow_mut();
347+
let ty = tables.tcx.types.usize;
348+
let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size;
349+
350+
let scalar = ScalarInt::try_from_uint(val, size).ok_or_else(|| {
351+
Error::new(format!("Value overflow: cannot covert `{val}` to usize."))
352+
})?;
353+
Ok(ty::Const::new_value(tables.tcx, ty::ValTree::from_scalar_int(scalar), ty)
354+
.stable(&mut *tables))
355+
}
356+
357+
fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty {
358+
let mut tables = self.0.borrow_mut();
359+
let internal_kind = kind.internal(&mut *tables);
360+
tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables)
361+
}
315362
}
316363

317364
pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell<Tables<'tcx>>);
@@ -1536,6 +1583,13 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
15361583
}
15371584
}
15381585

1586+
impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
1587+
type T = stable_mir::mir::alloc::AllocId;
1588+
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
1589+
tables.create_alloc_id(*self)
1590+
}
1591+
}
1592+
15391593
impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
15401594
type T = GlobalAlloc;
15411595

compiler/stable_mir/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ pub trait Context {
268268

269269
/// Retrieve global allocation for the given allocation ID.
270270
fn global_alloc(&self, id: AllocId) -> GlobalAlloc;
271+
272+
/// Retrieve the id for the virtual table.
273+
fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>;
271274
}
272275

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

compiler/stable_mir/src/mir/alloc.rs

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub enum GlobalAlloc {
99
/// The alloc ID is used as a function pointer.
1010
Function(Instance),
1111
/// This alloc ID points to a symbolic (not-reified) vtable.
12+
/// The `None` trait ref is used to represent auto traits.
1213
VTable(Ty, Option<Binder<ExistentialTraitRef>>),
1314
/// The alloc ID points to a "lazy" static variable that did not get computed (yet).
1415
/// This is also used to break the cycle in recursive statics.
@@ -23,6 +24,12 @@ impl From<AllocId> for GlobalAlloc {
2324
}
2425
}
2526

27+
impl GlobalAlloc {
28+
pub fn vtable_allocation(&self) -> Option<AllocId> {
29+
with(|cx| cx.vtable_allocation(self))
30+
}
31+
}
32+
2633
/// A unique identification number for each provenance
2734
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2835
pub struct AllocId(usize);

0 commit comments

Comments
 (0)