refactor: remove the tcx field in Tables

the only functionality of `Tables` is caching results. this commit moves calls to rustc queries from `Tables` to `SmirCtxt`.
This commit is contained in:
Makai 2025-05-06 12:41:34 +08:00
parent 6916089d7c
commit 45cf29d651
8 changed files with 100 additions and 119 deletions

View file

@ -127,7 +127,7 @@ where
F: FnOnce() -> T,
{
let smir_cx = RefCell::new(SmirCtxt::new(tcx));
let container = SmirContainer { tables: RefCell::new(Tables::new(tcx)), cx: smir_cx };
let container = SmirContainer { tables: RefCell::new(Tables::default()), cx: smir_cx };
stable_mir::compiler_interface::run(&container, || init(&container, f))
}

View file

@ -8,19 +8,28 @@ use rustc_abi::{Size, TyAndLayout};
use rustc_middle::mir::interpret::{
AllocId, AllocInit, AllocRange, Allocation, ConstAllocation, Pointer, Scalar, alloc_range,
};
use rustc_middle::ty::Ty;
use rustc_middle::ty::{Ty, layout};
use crate::rustc_smir::{Bridge, SmirError, Tables};
use super::SmirCtxt;
use crate::rustc_smir::{Bridge, SmirError};
pub fn create_ty_and_layout<'tcx, B: Bridge>(
cx: &SmirCtxt<'tcx, B>,
ty: Ty<'tcx>,
) -> Result<TyAndLayout<'tcx, Ty<'tcx>>, &'tcx layout::LayoutError<'tcx>> {
use crate::rustc_smir::context::SmirTypingEnv;
cx.tcx.layout_of(cx.fully_monomorphized().as_query_input(ty))
}
pub fn try_new_scalar<'tcx, B: Bridge>(
layout: TyAndLayout<'tcx, Ty<'tcx>>,
scalar: Scalar,
tables: &mut Tables<'tcx, B>,
cx: &SmirCtxt<'tcx, B>,
) -> Result<Allocation, B::Error> {
let size = scalar.size();
let mut allocation = Allocation::new(size, layout.align.abi, AllocInit::Uninit, ());
allocation
.write_scalar(&tables.tcx, alloc_range(Size::ZERO, size), scalar)
.write_scalar(&cx.tcx, alloc_range(Size::ZERO, size), scalar)
.map_err(|e| B::Error::from_internal(e))?;
Ok(allocation)
@ -30,24 +39,20 @@ pub fn try_new_slice<'tcx, B: Bridge>(
layout: TyAndLayout<'tcx, Ty<'tcx>>,
data: ConstAllocation<'tcx>,
meta: u64,
tables: &mut Tables<'tcx, B>,
cx: &SmirCtxt<'tcx, B>,
) -> Result<Allocation, B::Error> {
let alloc_id = tables.tcx.reserve_and_set_memory_alloc(data);
let alloc_id = cx.tcx.reserve_and_set_memory_alloc(data);
let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
let scalar_ptr = Scalar::from_pointer(ptr, &tables.tcx);
let scalar_meta: Scalar = Scalar::from_target_usize(meta, &tables.tcx);
let mut allocation = Allocation::new(layout.size, layout.align.abi, AllocInit::Uninit, ());
allocation
.write_scalar(
&tables.tcx,
alloc_range(Size::ZERO, tables.tcx.data_layout.pointer_size),
scalar_ptr,
)
.write_scalar(&cx.tcx, alloc_range(Size::ZERO, cx.tcx.data_layout.pointer_size), scalar_ptr)
.map_err(|e| B::Error::from_internal(e))?;
allocation
.write_scalar(
&tables.tcx,
alloc_range(tables.tcx.data_layout.pointer_size, scalar_meta.size()),
&cx.tcx,
alloc_range(cx.tcx.data_layout.pointer_size, scalar_meta.size()),
scalar_meta,
)
.map_err(|e| B::Error::from_internal(e))?;
@ -57,9 +62,9 @@ pub fn try_new_slice<'tcx, B: Bridge>(
pub fn try_new_indirect<'tcx, B: Bridge>(
alloc_id: AllocId,
tables: &mut Tables<'tcx, B>,
cx: &SmirCtxt<'tcx, B>,
) -> ConstAllocation<'tcx> {
let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory();
let alloc = cx.tcx.global_alloc(alloc_id).unwrap_memory();
alloc
}

View file

@ -9,8 +9,6 @@ use rustc_middle::mir;
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::ty::{self, TyCtxt};
use crate::rustc_smir::{Bridge, Tables};
/// Builds a monomorphic body for a given instance.
pub(crate) struct BodyBuilder<'tcx> {
tcx: TyCtxt<'tcx>,
@ -30,8 +28,8 @@ impl<'tcx> BodyBuilder<'tcx> {
/// Build a stable monomorphic body for a given instance based on the MIR body.
///
/// All constants are also evaluated.
pub(crate) fn build<B: Bridge>(mut self, tables: &mut Tables<'tcx, B>) -> mir::Body<'tcx> {
let body = tables.tcx.instance_mir(self.instance.def).clone();
pub(crate) fn build(mut self) -> mir::Body<'tcx> {
let body = self.tcx.instance_mir(self.instance.def).clone();
let mono_body = if !self.instance.args.is_empty()
// Without the `generic_const_exprs` feature gate, anon consts in signatures do not
// get generic parameters. Which is wrong, but also not a problem without
@ -39,7 +37,7 @@ impl<'tcx> BodyBuilder<'tcx> {
|| self.tcx.def_kind(self.instance.def_id()) != DefKind::AnonConst
{
let mut mono_body = self.instance.instantiate_mir_and_normalize_erasing_regions(
tables.tcx,
self.tcx,
ty::TypingEnv::fully_monomorphized(),
ty::EarlyBinder::bind(body),
);

View file

@ -143,6 +143,46 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
self.tcx.valtree_to_const_val(key)
}
/// Return whether the instance as a body available.
///
/// Items and intrinsics may have a body available from its definition.
/// Shims body may be generated depending on their type.
pub(crate) fn instance_has_body(&self, instance: Instance<'tcx>) -> bool {
let def_id = instance.def_id();
self.item_has_body(def_id)
|| !matches!(
instance.def,
ty::InstanceKind::Virtual(..)
| ty::InstanceKind::Intrinsic(..)
| ty::InstanceKind::Item(..)
)
}
/// Return whether the item has a body defined by the user.
///
/// Note that intrinsics may have a placeholder body that shouldn't be used in practice.
/// In StableMIR, we handle this case as if the body is not available.
pub(crate) fn item_has_body(&self, def_id: DefId) -> bool {
let must_override = if let Some(intrinsic) = self.tcx.intrinsic(def_id) {
intrinsic.must_be_overridden
} else {
false
};
!must_override && self.tcx.is_mir_available(def_id)
}
fn filter_fn_def(&self, def_id: DefId) -> Option<DefId> {
if matches!(self.tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
Some(def_id)
} else {
None
}
}
fn filter_static_def(&self, def_id: DefId) -> Option<DefId> {
matches!(self.tcx.def_kind(def_id), DefKind::Static { .. }).then(|| def_id)
}
pub fn target_endian(&self) -> Endian {
self.tcx.data_layout.endian
}
@ -167,8 +207,8 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
}
/// Check whether the body of a function is available.
pub fn has_body(&self, def: DefId, tables: &mut Tables<'_, B>) -> bool {
tables.item_has_body(def)
pub fn has_body(&self, def: DefId) -> bool {
self.item_has_body(def)
}
pub fn foreign_modules(&self, crate_num: CrateNum) -> Vec<DefId> {
@ -176,13 +216,13 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
}
/// Retrieve all functions defined in this crate.
pub fn crate_functions(&self, crate_num: CrateNum, tables: &mut Tables<'_, B>) -> Vec<DefId> {
filter_def_ids(self.tcx, crate_num, |def_id| tables.filter_fn_def(def_id))
pub fn crate_functions(&self, crate_num: CrateNum) -> Vec<DefId> {
filter_def_ids(self.tcx, crate_num, |def_id| self.filter_fn_def(def_id))
}
/// Retrieve all static items defined in this crate.
pub fn crate_statics(&self, crate_num: CrateNum, tables: &mut Tables<'_, B>) -> Vec<DefId> {
filter_def_ids(self.tcx, crate_num, |def_id| tables.filter_static_def(def_id))
pub fn crate_statics(&self, crate_num: CrateNum) -> Vec<DefId> {
filter_def_ids(self.tcx, crate_num, |def_id| self.filter_static_def(def_id))
}
pub fn foreign_module(&self, mod_def: DefId) -> &ForeignModule {
@ -574,14 +614,8 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
}
/// Get the body of an Instance which is already monomorphized.
pub fn instance_body(
&self,
instance: ty::Instance<'tcx>,
tables: &mut Tables<'tcx, B>,
) -> Option<Body<'tcx>> {
tables
.instance_has_body(instance)
.then(|| BodyBuilder::new(self.tcx, instance).build(tables))
pub fn instance_body(&self, instance: ty::Instance<'tcx>) -> Option<Body<'tcx>> {
self.instance_has_body(instance).then(|| BodyBuilder::new(self.tcx, instance).build())
}
/// Get the instance type with generic instantiations applied and lifetimes erased.
@ -599,18 +633,13 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
pub fn instance_abi(
&self,
instance: ty::Instance<'tcx>,
tables: &mut Tables<'tcx, B>,
) -> Result<&FnAbi<'tcx, Ty<'tcx>>, B::Error> {
Ok(tables.fn_abi_of_instance(instance, List::empty())?)
Ok(self.fn_abi_of_instance(instance, List::empty())?)
}
/// Get the ABI of a function pointer.
pub fn fn_ptr_abi(
&self,
sig: PolyFnSig<'tcx>,
tables: &mut Tables<'tcx, B>,
) -> Result<&FnAbi<'tcx, Ty<'tcx>>, B::Error> {
Ok(tables.fn_abi_of_fn_ptr(sig, List::empty())?)
pub fn fn_ptr_abi(&self, sig: PolyFnSig<'tcx>) -> Result<&FnAbi<'tcx, Ty<'tcx>>, B::Error> {
Ok(self.fn_abi_of_fn_ptr(sig, List::empty())?)
}
/// Get the instance.
@ -737,12 +766,8 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
}
/// Get the layout of a type.
pub fn ty_layout(
&self,
ty: Ty<'tcx>,
tables: &mut Tables<'tcx, B>,
) -> Result<Layout<'tcx>, B::Error> {
let layout = tables.layout_of(ty)?.layout;
pub fn ty_layout(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, B::Error> {
let layout = self.layout_of(ty)?.layout;
Ok(layout)
}

View file

@ -9,7 +9,7 @@ use rustc_middle::ty;
use rustc_middle::ty::layout::{FnAbiOfHelpers, HasTyCtxt, HasTypingEnv, LayoutOfHelpers};
use rustc_middle::ty::{Ty, TyCtxt};
use crate::rustc_smir::{Bridge, SmirError, Tables};
use crate::rustc_smir::{Bridge, SmirError};
mod impls;
mod traits;
@ -21,7 +21,7 @@ pub use traits::*;
/// The [`crate::stable_mir::compiler_interface::SmirInterface`] must go through
/// this context to obtain rustc-level information.
pub struct SmirCtxt<'tcx, B: Bridge> {
tcx: TyCtxt<'tcx>,
pub(crate) tcx: TyCtxt<'tcx>,
_marker: PhantomData<B>,
}
@ -32,7 +32,7 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
}
/// Implement error handling for extracting function ABI information.
impl<'tcx, B: Bridge> FnAbiOfHelpers<'tcx> for Tables<'tcx, B> {
impl<'tcx, B: Bridge> FnAbiOfHelpers<'tcx> for SmirCtxt<'tcx, B> {
type FnAbiOfResult = Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, B::Error>;
#[inline]
@ -46,7 +46,7 @@ impl<'tcx, B: Bridge> FnAbiOfHelpers<'tcx> for Tables<'tcx, B> {
}
}
impl<'tcx, B: Bridge> LayoutOfHelpers<'tcx> for Tables<'tcx, B> {
impl<'tcx, B: Bridge> LayoutOfHelpers<'tcx> for SmirCtxt<'tcx, B> {
type LayoutOfResult = Result<ty::layout::TyAndLayout<'tcx>, B::Error>;
#[inline]
@ -60,19 +60,19 @@ impl<'tcx, B: Bridge> LayoutOfHelpers<'tcx> for Tables<'tcx, B> {
}
}
impl<'tcx, B: Bridge> HasTypingEnv<'tcx> for Tables<'tcx, B> {
impl<'tcx, B: Bridge> HasTypingEnv<'tcx> for SmirCtxt<'tcx, B> {
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
ty::TypingEnv::fully_monomorphized()
}
}
impl<'tcx, B: Bridge> HasTyCtxt<'tcx> for Tables<'tcx, B> {
impl<'tcx, B: Bridge> HasTyCtxt<'tcx> for SmirCtxt<'tcx, B> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
}
impl<'tcx, B: Bridge> HasDataLayout for Tables<'tcx, B> {
impl<'tcx, B: Bridge> HasDataLayout for SmirCtxt<'tcx, B> {
fn data_layout(&self) -> &rustc_abi::TargetDataLayout {
self.tcx.data_layout()
}

View file

@ -14,7 +14,7 @@ use context::SmirCtxt;
use rustc_hir::def::DefKind;
use rustc_middle::mir;
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
use crate::rustc_internal::IndexMap;
@ -30,7 +30,6 @@ pub struct SmirContainer<'tcx, B: Bridge> {
}
pub struct Tables<'tcx, B: Bridge> {
tcx: TyCtxt<'tcx>,
pub(crate) def_ids: IndexMap<DefId, B::DefId>,
pub(crate) alloc_ids: IndexMap<AllocId, B::AllocId>,
pub(crate) spans: IndexMap<rustc_span::Span, B::Span>,
@ -41,10 +40,9 @@ pub struct Tables<'tcx, B: Bridge> {
pub(crate) layouts: IndexMap<rustc_abi::Layout<'tcx>, B::Layout>,
}
impl<'tcx, B: Bridge> Tables<'tcx, B> {
pub(crate) fn new(tcx: TyCtxt<'tcx>) -> Self {
impl<'tcx, B: Bridge> Default for Tables<'tcx, B> {
fn default() -> Self {
Self {
tcx,
def_ids: IndexMap::default(),
alloc_ids: IndexMap::default(),
spans: IndexMap::default(),
@ -69,46 +67,6 @@ impl<'tcx, B: Bridge> Tables<'tcx, B> {
pub(crate) fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> B::MirConstId {
self.mir_consts.create_or_fetch(constant)
}
/// Return whether the instance as a body available.
///
/// Items and intrinsics may have a body available from its definition.
/// Shims body may be generated depending on their type.
pub(crate) fn instance_has_body(&self, instance: Instance<'tcx>) -> bool {
let def_id = instance.def_id();
self.item_has_body(def_id)
|| !matches!(
instance.def,
ty::InstanceKind::Virtual(..)
| ty::InstanceKind::Intrinsic(..)
| ty::InstanceKind::Item(..)
)
}
/// Return whether the item has a body defined by the user.
///
/// Note that intrinsics may have a placeholder body that shouldn't be used in practice.
/// In StableMIR, we handle this case as if the body is not available.
pub(crate) fn item_has_body(&self, def_id: DefId) -> bool {
let must_override = if let Some(intrinsic) = self.tcx.intrinsic(def_id) {
intrinsic.must_be_overridden
} else {
false
};
!must_override && self.tcx.is_mir_available(def_id)
}
fn filter_fn_def(&mut self, def_id: DefId) -> Option<DefId> {
if matches!(self.tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
Some(def_id)
} else {
None
}
}
fn filter_static_def(&mut self, def_id: DefId) -> Option<DefId> {
matches!(self.tcx.def_kind(def_id), DefKind::Static { .. }).then(|| def_id)
}
}
/// A trait defining types that are used to emulate StableMIR components, which is really

View file

@ -48,20 +48,17 @@ pub(crate) fn try_new_allocation<'tcx>(
tables: &mut Tables<'tcx, BridgeTys>,
cx: &SmirCtxt<'tcx, BridgeTys>,
) -> Result<Allocation, Error> {
use rustc_smir::context::SmirTypingEnv;
let layout = cx
.layout_of(cx.fully_monomorphized().as_query_input(ty))
.map_err(|e| Error::from_internal(e))?;
let layout = alloc::create_ty_and_layout(cx, ty).map_err(|e| Error::from_internal(e))?;
match const_value {
ConstValue::Scalar(scalar) => {
alloc::try_new_scalar(layout, scalar, tables).map(|alloc| alloc.stable(tables, cx))
alloc::try_new_scalar(layout, scalar, cx).map(|alloc| alloc.stable(tables, cx))
}
ConstValue::ZeroSized => Ok(new_empty_allocation(layout.align.abi)),
ConstValue::Slice { data, meta } => {
alloc::try_new_slice(layout, data, meta, tables).map(|alloc| alloc.stable(tables, cx))
alloc::try_new_slice(layout, data, meta, cx).map(|alloc| alloc.stable(tables, cx))
}
ConstValue::Indirect { alloc_id, offset } => {
let alloc = alloc::try_new_indirect(alloc_id, tables);
let alloc = alloc::try_new_indirect(alloc_id, cx);
use rustc_smir::context::SmirAllocRange;
Ok(allocation_filter(&alloc.0, cx.alloc_range(offset, layout.size), tables, cx))
}

View file

@ -432,7 +432,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
let tables_ref = &mut *tables;
let cx = &*self.cx.borrow();
let def = item.internal(tables_ref, cx);
cx.has_body(def, tables_ref)
cx.has_body(def)
}
fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef> {
@ -448,18 +448,16 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
let mut tables = self.tables.borrow_mut();
let cx = &*self.cx.borrow();
let tables_ref = &mut *tables;
let krate = crate_num.internal(tables_ref, cx);
cx.crate_functions(krate, tables_ref).iter().map(|did| tables.fn_def(*did)).collect()
let krate = crate_num.internal(&mut *tables, cx);
cx.crate_functions(krate).iter().map(|did| tables.fn_def(*did)).collect()
}
/// Retrieve all static items defined in this crate.
fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
let mut tables = self.tables.borrow_mut();
let cx = &*self.cx.borrow();
let tables_ref = &mut *tables;
let krate = crate_num.internal(tables_ref, cx);
cx.crate_statics(krate, tables_ref).iter().map(|did| tables.static_def(*did)).collect()
let krate = crate_num.internal(&mut *tables, cx);
cx.crate_statics(krate).iter().map(|did| tables.static_def(*did)).collect()
}
fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule {
@ -908,7 +906,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
let mut tables = self.tables.borrow_mut();
let cx = &*self.cx.borrow();
let instance = tables.instances[instance];
cx.instance_body(instance, &mut *tables).map(|body| body.stable(&mut *tables, cx))
cx.instance_body(instance).map(|body| body.stable(&mut *tables, cx))
}
/// Get the instance type with generic instantiations applied and lifetimes erased.
@ -1078,7 +1076,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
let mut tables = self.tables.borrow_mut();
let cx = &*self.cx.borrow();
let instance = tables.instances[def];
cx.instance_abi(instance, &mut *tables).map(|fn_abi| fn_abi.stable(&mut *tables, cx))
cx.instance_abi(instance).map(|fn_abi| fn_abi.stable(&mut *tables, cx))
}
/// Get the ABI of a function pointer.
@ -1086,7 +1084,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
let mut tables = self.tables.borrow_mut();
let cx = &*self.cx.borrow();
let sig = fn_ptr.internal(&mut *tables, cx);
cx.fn_ptr_abi(sig, &mut *tables).map(|fn_abi| fn_abi.stable(&mut *tables, cx))
cx.fn_ptr_abi(sig).map(|fn_abi| fn_abi.stable(&mut *tables, cx))
}
/// Get the layout of a type.
@ -1094,7 +1092,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
let mut tables = self.tables.borrow_mut();
let cx = &*self.cx.borrow();
let internal_ty = ty.internal(&mut *tables, cx);
cx.ty_layout(internal_ty, &mut *tables).map(|layout| layout.stable(&mut *tables, cx))
cx.ty_layout(internal_ty).map(|layout| layout.stable(&mut *tables, cx))
}
/// Get the layout shape.