Add stable Instance::body() and RustcInternal trait
The `Instance::body()` returns a monomorphized body. For that, we had to implement visitor that monomorphize types and constants. We are also introducing the RustcInternal trait that will allow us to convert back from Stable to Internal. Note that this trait is not yet visible for our users as it depends on Tables. We should probably add a new trait that can be exposed.
This commit is contained in:
parent
cc705b8012
commit
6ed2a76bcc
10 changed files with 218 additions and 7 deletions
61
compiler/rustc_smir/src/rustc_internal/internal.rs
Normal file
61
compiler/rustc_smir/src/rustc_internal/internal.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
//! Module containing the translation from stable mir constructs to the rustc counterpart.
|
||||
//!
|
||||
//! This module will only include a few constructs to allow users to invoke internal rustc APIs
|
||||
//! due to incomplete stable coverage.
|
||||
|
||||
// Prefer importing stable_mir over internal rustc constructs to make this file more readable.
|
||||
use crate::rustc_smir::{MaybeStable, Tables};
|
||||
use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy};
|
||||
use stable_mir::ty::{Const, GenericArgKind, GenericArgs, Region, Ty};
|
||||
use stable_mir::DefId;
|
||||
|
||||
use super::RustcInternal;
|
||||
|
||||
impl<'tcx> RustcInternal<'tcx> for DefId {
|
||||
type T = rustc_span::def_id::DefId;
|
||||
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
tables.def_ids[*self]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RustcInternal<'tcx> for GenericArgs {
|
||||
type T = rustc_ty::GenericArgsRef<'tcx>;
|
||||
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
tables.tcx.mk_args_from_iter(self.0.iter().map(|arg| arg.internal(tables)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RustcInternal<'tcx> for GenericArgKind {
|
||||
type T = rustc_ty::GenericArg<'tcx>;
|
||||
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
GenericArgKind::Lifetime(reg) => reg.internal(tables).into(),
|
||||
GenericArgKind::Type(ty) => ty.internal(tables).into(),
|
||||
GenericArgKind::Const(cnst) => cnst.internal(tables).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RustcInternal<'tcx> for Region {
|
||||
type T = rustc_ty::Region<'tcx>;
|
||||
fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RustcInternal<'tcx> for Ty {
|
||||
type T = InternalTy<'tcx>;
|
||||
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match tables.types[self.0] {
|
||||
MaybeStable::Stable(_) => todo!(),
|
||||
MaybeStable::Rustc(ty) => ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RustcInternal<'tcx> for Const {
|
||||
type T = rustc_ty::Const<'tcx>;
|
||||
fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||
todo!()
|
||||
}
|
||||
}
|
|
@ -20,6 +20,8 @@ use std::fmt::Debug;
|
|||
use std::hash::Hash;
|
||||
use std::ops::{ControlFlow, Index};
|
||||
|
||||
mod internal;
|
||||
|
||||
impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
|
||||
type Output = DefId;
|
||||
|
||||
|
@ -231,3 +233,11 @@ impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V
|
|||
k
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait used to translate a stable construct to its rustc counterpart.
|
||||
///
|
||||
/// This is basically a mirror of [crate::rustc_smir::Stable].
|
||||
pub(crate) trait RustcInternal<'tcx> {
|
||||
type T;
|
||||
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T;
|
||||
}
|
||||
|
|
55
compiler/rustc_smir/src/rustc_smir/builder.rs
Normal file
55
compiler/rustc_smir/src/rustc_smir/builder.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
//! Logic required to produce a monomorphic stable body.
|
||||
//!
|
||||
//! We first retrieve and monomorphize the rustc body representation, i.e., we generate a
|
||||
//! monomorphic body using internal representation.
|
||||
//! After that, we convert the internal representation into a stable one.
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::visit::MutVisitor;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
|
||||
/// Builds a monomorphic body for a given instance.
|
||||
pub struct BodyBuilder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> BodyBuilder<'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self {
|
||||
BodyBuilder { tcx, instance }
|
||||
}
|
||||
|
||||
pub fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body {
|
||||
let mut body = self.tcx.instance_mir(self.instance.def).clone();
|
||||
let generics = self.tcx.generics_of(self.instance.def_id());
|
||||
if generics.requires_monomorphization(self.tcx) {
|
||||
self.visit_body(&mut body);
|
||||
}
|
||||
body.stable(tables)
|
||||
}
|
||||
|
||||
fn monomorphize<T>(&self, value: T) -> T
|
||||
where
|
||||
T: ty::TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
self.instance.instantiate_mir_and_normalize_erasing_regions(
|
||||
self.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
ty::EarlyBinder::bind(value),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
|
||||
fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, _location: mir::Location) {
|
||||
*ct = self.monomorphize(*ct);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: mir::visit::TyContext) {
|
||||
*ty = self.monomorphize(*ty);
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
//!
|
||||
//! For now, we are developing everything inside `rustc`, thus, we keep this module private.
|
||||
|
||||
use crate::rustc_internal::IndexMap;
|
||||
use crate::rustc_internal::{IndexMap, RustcInternal};
|
||||
use crate::rustc_smir::hir::def::DefKind;
|
||||
use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region};
|
||||
use rustc_hir as hir;
|
||||
|
@ -26,6 +26,7 @@ use stable_mir::{self, opaque, Context, Filename};
|
|||
use tracing::debug;
|
||||
|
||||
mod alloc;
|
||||
mod builder;
|
||||
|
||||
impl<'tcx> Context for Tables<'tcx> {
|
||||
fn local_crate(&self) -> stable_mir::Crate {
|
||||
|
@ -171,8 +172,9 @@ impl<'tcx> Context for Tables<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn instance_body(&mut self, _def: InstanceDef) -> Body {
|
||||
todo!("Monomorphize the body")
|
||||
fn instance_body(&mut self, def: InstanceDef) -> Body {
|
||||
let instance = self.instances[def];
|
||||
builder::BodyBuilder::new(self.tcx, instance).build(self)
|
||||
}
|
||||
|
||||
fn instance_ty(&mut self, def: InstanceDef) -> stable_mir::ty::Ty {
|
||||
|
@ -195,9 +197,21 @@ impl<'tcx> Context for Tables<'tcx> {
|
|||
let def_id = self[def_id];
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let result = generics.requires_monomorphization(self.tcx);
|
||||
println!("req {result}: {def_id:?}");
|
||||
result
|
||||
}
|
||||
|
||||
fn resolve_instance(
|
||||
&mut self,
|
||||
def: stable_mir::ty::FnDef,
|
||||
args: &stable_mir::ty::GenericArgs,
|
||||
) -> Option<stable_mir::mir::mono::Instance> {
|
||||
let def_id = def.0.internal(self);
|
||||
let args_ref = args.internal(self);
|
||||
match Instance::resolve(self.tcx, ParamEnv::reveal_all(), def_id, args_ref) {
|
||||
Ok(Some(instance)) => Some(instance.stable(self)),
|
||||
Ok(None) | Err(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue