about summary refs log tree commit diff
path: root/compiler/rustc_smir
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_smir')
-rw-r--r--compiler/rustc_smir/Cargo.toml6
-rw-r--r--compiler/rustc_smir/src/lib.rs7
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs61
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs232
-rw-r--r--compiler/rustc_smir/src/rustc_smir/builder.rs55
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs228
6 files changed, 437 insertions, 152 deletions
diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml
index 4c29f743708..41c7d3a8594 100644
--- a/compiler/rustc_smir/Cargo.toml
+++ b/compiler/rustc_smir/Cargo.toml
@@ -4,14 +4,12 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
-rustc_driver = { path = "../rustc_driver" }
-rustc_interface = { path = "../rustc_interface" }
-rustc_session = {path = "../rustc_session" }
-tracing = "0.1"
 stable_mir = {path = "../stable_mir" }
+tracing = "0.1"
 
 [features]
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
index b6c36678db5..c24b9efe865 100644
--- a/compiler/rustc_smir/src/lib.rs
+++ b/compiler/rustc_smir/src/lib.rs
@@ -10,10 +10,9 @@
     html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
     test(attr(allow(unused_variables), deny(warnings)))
 )]
-#![feature(rustc_private)]
-#![feature(ptr_metadata)]
-#![feature(type_alias_impl_trait)] // Used to define opaque types.
-#![feature(intra_doc_pointers)]
+#![cfg_attr(not(bootstrap), doc(rust_logo))]
+#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
+#![cfg_attr(not(bootstrap), allow(internal_features))]
 
 pub mod rustc_internal;
 
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
new file mode 100644
index 00000000000..f42a9739320
--- /dev/null
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -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!()
+    }
+}
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 1a9dea99f64..f7e519570fa 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -3,24 +3,27 @@
 //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
 //! until stable MIR is complete.
 
-use std::ops::{ControlFlow, Index};
-
-use crate::rustc_internal;
 use crate::rustc_smir::Tables;
-use rustc_driver::{Callbacks, Compilation, RunCompiler};
-use rustc_interface::{interface, Queries};
+use rustc_data_structures::fx;
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_middle::mir::interpret::AllocId;
+use rustc_middle::ty;
 use rustc_middle::ty::TyCtxt;
-pub use rustc_span::def_id::{CrateNum, DefId};
+use rustc_span::def_id::{CrateNum, DefId};
 use rustc_span::Span;
-use stable_mir::CompilerError;
+use stable_mir::ty::IndexedVal;
+use std::fmt::Debug;
+use std::hash::Hash;
+use std::ops::Index;
+
+mod internal;
 
 impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
     type Output = DefId;
 
     #[inline(always)]
     fn index(&self, index: stable_mir::DefId) -> &Self::Output {
-        &self.def_ids[index.0]
+        &self.def_ids[index]
     }
 }
 
@@ -29,7 +32,7 @@ impl<'tcx> Index<stable_mir::ty::Span> for Tables<'tcx> {
 
     #[inline(always)]
     fn index(&self, index: stable_mir::ty::Span) -> &Self::Output {
-        &self.spans[index.0]
+        &self.spans[index]
     }
 }
 
@@ -54,8 +57,8 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::ClosureDef(self.create_def_id(did))
     }
 
-    pub fn generator_def(&mut self, did: DefId) -> stable_mir::ty::GeneratorDef {
-        stable_mir::ty::GeneratorDef(self.create_def_id(did))
+    pub fn coroutine_def(&mut self, did: DefId) -> stable_mir::ty::CoroutineDef {
+        stable_mir::ty::CoroutineDef(self.create_def_id(did))
     }
 
     pub fn alias_def(&mut self, did: DefId) -> stable_mir::ty::AliasDef {
@@ -94,37 +97,27 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::Prov(self.create_alloc_id(aid))
     }
 
-    fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
-        // FIXME: this becomes inefficient when we have too many ids
-        for (i, &d) in self.def_ids.iter().enumerate() {
-            if d == did {
-                return stable_mir::DefId(i);
-            }
-        }
-        let id = self.def_ids.len();
-        self.def_ids.push(did);
-        stable_mir::DefId(id)
+    pub(crate) fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
+        self.def_ids.create_or_fetch(did)
     }
 
     fn create_alloc_id(&mut self, aid: AllocId) -> stable_mir::AllocId {
-        // FIXME: this becomes inefficient when we have too many ids
-        if let Some(i) = self.alloc_ids.iter().position(|a| *a == aid) {
-            return stable_mir::AllocId(i);
-        };
-        let id = self.def_ids.len();
-        self.alloc_ids.push(aid);
-        stable_mir::AllocId(id)
+        self.alloc_ids.create_or_fetch(aid)
     }
 
     pub(crate) fn create_span(&mut self, span: Span) -> stable_mir::ty::Span {
-        for (i, &sp) in self.spans.iter().enumerate() {
-            if sp == span {
-                return stable_mir::ty::Span(i);
-            }
-        }
-        let id = self.spans.len();
-        self.spans.push(span);
-        stable_mir::ty::Span(id)
+        self.spans.create_or_fetch(span)
+    }
+
+    pub(crate) fn instance_def(
+        &mut self,
+        instance: ty::Instance<'tcx>,
+    ) -> stable_mir::mir::mono::InstanceDef {
+        self.instances.create_or_fetch(instance)
+    }
+
+    pub(crate) fn static_def(&mut self, did: DefId) -> stable_mir::mir::mono::StaticDef {
+        stable_mir::mir::mono::StaticDef(self.create_def_id(did))
     }
 }
 
@@ -134,66 +127,131 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
 
 pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
     stable_mir::run(
-        Tables { tcx, def_ids: vec![], alloc_ids: vec![], spans: vec![], types: vec![] },
+        Tables {
+            tcx,
+            def_ids: IndexMap::default(),
+            alloc_ids: IndexMap::default(),
+            spans: IndexMap::default(),
+            types: vec![],
+            instances: IndexMap::default(),
+        },
         f,
     );
 }
 
-pub struct StableMir<B = (), C = ()>
-where
-    B: Send,
-    C: Send,
-{
-    args: Vec<String>,
-    callback: fn(TyCtxt<'_>) -> ControlFlow<B, C>,
-    result: Option<ControlFlow<B, C>>,
-}
+#[macro_export]
+macro_rules! run {
+    ($args:expr, $callback:expr) => {
+        run!($args, tcx, $callback)
+    };
+    ($args:expr, $tcx:ident, $callback:expr) => {{
+        use rustc_driver::{Callbacks, Compilation, RunCompiler};
+        use rustc_interface::{interface, Queries};
+        use stable_mir::CompilerError;
+        use std::ops::ControlFlow;
 
-impl<B, C> StableMir<B, C>
-where
-    B: Send,
-    C: Send,
-{
-    /// Creates a new `StableMir` instance, with given test_function and arguments.
-    pub fn new(args: Vec<String>, callback: fn(TyCtxt<'_>) -> ControlFlow<B, C>) -> Self {
-        StableMir { args, callback, result: None }
-    }
-
-    /// Runs the compiler against given target and tests it with `test_function`
-    pub fn run(&mut self) -> Result<C, CompilerError<B>> {
-        let compiler_result =
-            rustc_driver::catch_fatal_errors(|| RunCompiler::new(&self.args.clone(), self).run());
-        match (compiler_result, self.result.take()) {
-            (Ok(Ok(())), Some(ControlFlow::Continue(value))) => Ok(value),
-            (Ok(Ok(())), Some(ControlFlow::Break(value))) => Err(CompilerError::Interrupted(value)),
-            (Ok(Ok(_)), None) => Err(CompilerError::Skipped),
-            (Ok(Err(_)), _) => Err(CompilerError::CompilationFailed),
-            (Err(_), _) => Err(CompilerError::ICE),
+        pub struct StableMir<B = (), C = ()>
+        where
+            B: Send,
+            C: Send,
+        {
+            args: Vec<String>,
+            callback: fn(TyCtxt<'_>) -> ControlFlow<B, C>,
+            result: Option<ControlFlow<B, C>>,
         }
+
+        impl<B, C> StableMir<B, C>
+        where
+            B: Send,
+            C: Send,
+        {
+            /// Creates a new `StableMir` instance, with given test_function and arguments.
+            pub fn new(args: Vec<String>, callback: fn(TyCtxt<'_>) -> ControlFlow<B, C>) -> Self {
+                StableMir { args, callback, result: None }
+            }
+
+            /// Runs the compiler against given target and tests it with `test_function`
+            pub fn run(&mut self) -> Result<C, CompilerError<B>> {
+                let compiler_result = rustc_driver::catch_fatal_errors(|| {
+                    RunCompiler::new(&self.args.clone(), self).run()
+                });
+                match (compiler_result, self.result.take()) {
+                    (Ok(Ok(())), Some(ControlFlow::Continue(value))) => Ok(value),
+                    (Ok(Ok(())), Some(ControlFlow::Break(value))) => {
+                        Err(CompilerError::Interrupted(value))
+                    }
+                    (Ok(Ok(_)), None) => Err(CompilerError::Skipped),
+                    (Ok(Err(_)), _) => Err(CompilerError::CompilationFailed),
+                    (Err(_), _) => Err(CompilerError::ICE),
+                }
+            }
+        }
+
+        impl<B, C> Callbacks for StableMir<B, C>
+        where
+            B: Send,
+            C: Send,
+        {
+            /// Called after analysis. Return value instructs the compiler whether to
+            /// continue the compilation afterwards (defaults to `Compilation::Continue`)
+            fn after_analysis<'tcx>(
+                &mut self,
+                _compiler: &interface::Compiler,
+                queries: &'tcx Queries<'tcx>,
+            ) -> Compilation {
+                queries.global_ctxt().unwrap().enter(|tcx| {
+                    rustc_internal::run(tcx, || {
+                        self.result = Some((self.callback)(tcx));
+                    });
+                    if self.result.as_ref().is_some_and(|val| val.is_continue()) {
+                        Compilation::Continue
+                    } else {
+                        Compilation::Stop
+                    }
+                })
+            }
+        }
+
+        StableMir::new($args, |$tcx| $callback).run()
+    }};
+}
+
+/// Simmilar to rustc's `FxIndexMap`, `IndexMap` with extra
+/// safety features added.
+pub struct IndexMap<K, V> {
+    index_map: fx::FxIndexMap<K, V>,
+}
+
+impl<K, V> Default for IndexMap<K, V> {
+    fn default() -> Self {
+        Self { index_map: FxIndexMap::default() }
     }
 }
 
-impl<B, C> Callbacks for StableMir<B, C>
-where
-    B: Send,
-    C: Send,
+impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> {
+    pub fn create_or_fetch(&mut self, key: K) -> V {
+        let len = self.index_map.len();
+        let v = self.index_map.entry(key).or_insert(V::to_val(len));
+        *v
+    }
+}
+
+impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V>
+    for IndexMap<K, V>
 {
-    /// Called after analysis. Return value instructs the compiler whether to
-    /// continue the compilation afterwards (defaults to `Compilation::Continue`)
-    fn after_analysis<'tcx>(
-        &mut self,
-        _compiler: &interface::Compiler,
-        queries: &'tcx Queries<'tcx>,
-    ) -> Compilation {
-        queries.global_ctxt().unwrap().enter(|tcx| {
-            rustc_internal::run(tcx, || {
-                self.result = Some((self.callback)(tcx));
-            });
-            if self.result.as_ref().is_some_and(|val| val.is_continue()) {
-                Compilation::Continue
-            } else {
-                Compilation::Stop
-            }
-        })
+    type Output = K;
+
+    fn index(&self, index: V) -> &Self::Output {
+        let (k, v) = self.index_map.get_index(index.to_index()).unwrap();
+        assert_eq!(*v, index, "Provided value doesn't match with indexed value");
+        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;
+}
diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs
new file mode 100644
index 00000000000..8ff3958da7b
--- /dev/null
+++ b/compiler/rustc_smir/src/rustc_smir/builder.rs
@@ -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
+    }
+}
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 7d1122c2fd2..d5379797f1c 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -7,20 +7,26 @@
 //!
 //! For now, we are developing everything inside `rustc`, thus, we keep this module private.
 
+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;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{alloc_range, AllocId};
-use rustc_middle::ty::{self, Ty, TyCtxt, Variance};
+use rustc_middle::mir::mono::MonoItem;
+use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt, Variance};
 use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_target::abi::FieldIdx;
-use stable_mir::mir::{CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
-use stable_mir::ty::{FloatTy, GenericParamDef, IntTy, Movability, RigidTy, Span, TyKind, UintTy};
-use stable_mir::{self, opaque, Context};
+use stable_mir::mir::mono::InstanceDef;
+use stable_mir::mir::{Body, CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
+use stable_mir::ty::{
+    FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy,
+};
+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 {
@@ -31,21 +37,45 @@ impl<'tcx> Context for Tables<'tcx> {
         self.tcx.crates(()).iter().map(|crate_num| smir_crate(self.tcx, *crate_num)).collect()
     }
 
-    fn find_crate(&self, name: &str) -> Option<stable_mir::Crate> {
-        [LOCAL_CRATE].iter().chain(self.tcx.crates(()).iter()).find_map(|crate_num| {
-            let crate_name = self.tcx.crate_name(*crate_num).to_string();
-            (name == crate_name).then(|| smir_crate(self.tcx, *crate_num))
-        })
+    fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
+        let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE]
+            .iter()
+            .chain(self.tcx.crates(()).iter())
+            .map(|crate_num| {
+                let crate_name = self.tcx.crate_name(*crate_num).to_string();
+                (name == crate_name).then(|| smir_crate(self.tcx, *crate_num))
+            })
+            .into_iter()
+            .filter_map(|c| c)
+            .collect();
+        crates
     }
 
     fn name_of_def_id(&self, def_id: stable_mir::DefId) -> String {
         self.tcx.def_path_str(self[def_id])
     }
 
-    fn print_span(&self, span: stable_mir::ty::Span) -> String {
+    fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
         self.tcx.sess.source_map().span_to_diagnostic_string(self[span])
     }
 
+    fn get_filename(&self, span: &Span) -> Filename {
+        opaque(
+            &self
+                .tcx
+                .sess
+                .source_map()
+                .span_to_filename(self[*span])
+                .display(rustc_span::FileNameDisplayPreference::Local)
+                .to_string(),
+        )
+    }
+
+    fn get_lines(&self, span: &Span) -> LineInfo {
+        let lines = &self.tcx.sess.source_map().span_to_location_info(self[*span]);
+        LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 }
+    }
+
     fn def_kind(&mut self, def_id: stable_mir::DefId) -> stable_mir::DefKind {
         self.tcx.def_kind(self[def_id]).stable(self)
     }
@@ -92,29 +122,7 @@ impl<'tcx> Context for Tables<'tcx> {
 
     fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body {
         let def_id = self[item];
-        let mir = self.tcx.instance_mir(ty::InstanceDef::Item(def_id));
-        stable_mir::mir::Body {
-            blocks: mir
-                .basic_blocks
-                .iter()
-                .map(|block| stable_mir::mir::BasicBlock {
-                    terminator: block.terminator().stable(self),
-                    statements: block
-                        .statements
-                        .iter()
-                        .map(|statement| statement.stable(self))
-                        .collect(),
-                })
-                .collect(),
-            locals: mir
-                .local_decls
-                .iter()
-                .map(|decl| stable_mir::mir::LocalDecl {
-                    ty: self.intern_ty(decl.ty),
-                    span: decl.source_info.span.stable(self),
-                })
-                .collect(),
-        }
+        self.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(self)
     }
 
     fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind {
@@ -163,6 +171,47 @@ impl<'tcx> Context for Tables<'tcx> {
                 .collect(),
         }
     }
+
+    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 {
+        let instance = self.instances[def];
+        let ty = instance.ty(self.tcx, ParamEnv::empty());
+        self.intern_ty(ty)
+    }
+
+    fn instance_def_id(&mut self, def: InstanceDef) -> stable_mir::DefId {
+        let def_id = self.instances[def].def_id();
+        self.create_def_id(def_id)
+    }
+
+    fn mono_instance(&mut self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance {
+        let def_id = self[item.0];
+        Instance::mono(self.tcx, def_id).stable(self)
+    }
+
+    fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
+        let def_id = self[def_id];
+        let generics = self.tcx.generics_of(def_id);
+        let result = generics.requires_monomorphization(self.tcx);
+        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)]
@@ -194,10 +243,11 @@ impl<S, R: PartialEq> PartialEq<R> for MaybeStable<S, R> {
 
 pub struct Tables<'tcx> {
     pub tcx: TyCtxt<'tcx>,
-    pub def_ids: Vec<DefId>,
-    pub alloc_ids: Vec<AllocId>,
-    pub spans: Vec<rustc_span::Span>,
-    pub types: Vec<MaybeStable<stable_mir::ty::TyKind, Ty<'tcx>>>,
+    pub def_ids: IndexMap<DefId, stable_mir::DefId>,
+    pub alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
+    pub spans: IndexMap<rustc_span::Span, Span>,
+    pub types: Vec<MaybeStable<TyKind, Ty<'tcx>>>,
+    pub instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
 }
 
 impl<'tcx> Tables<'tcx> {
@@ -227,6 +277,35 @@ pub(crate) trait Stable<'tcx> {
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T;
 }
 
+impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
+    type T = stable_mir::mir::Body;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        stable_mir::mir::Body {
+            blocks: self
+                .basic_blocks
+                .iter()
+                .map(|block| stable_mir::mir::BasicBlock {
+                    terminator: block.terminator().stable(tables),
+                    statements: block
+                        .statements
+                        .iter()
+                        .map(|statement| statement.stable(tables))
+                        .collect(),
+                })
+                .collect(),
+            locals: self
+                .local_decls
+                .iter()
+                .map(|decl| stable_mir::mir::LocalDecl {
+                    ty: tables.intern_ty(decl.ty),
+                    span: decl.source_info.span.stable(tables),
+                })
+                .collect(),
+        }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
     type T = stable_mir::mir::Statement;
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
@@ -703,11 +782,11 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
             AssertKind::RemainderByZero(op) => {
                 stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables))
             }
-            AssertKind::ResumedAfterReturn(generator) => {
-                stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable(tables))
+            AssertKind::ResumedAfterReturn(coroutine) => {
+                stable_mir::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables))
             }
-            AssertKind::ResumedAfterPanic(generator) => {
-                stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable(tables))
+            AssertKind::ResumedAfterPanic(coroutine) => {
+                stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables))
             }
             AssertKind::MisalignedPointerDereference { required, found } => {
                 stable_mir::mir::AssertMessage::MisalignedPointerDereference {
@@ -784,9 +863,9 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
                     generic_arg.stable(tables),
                 )
             }
-            mir::AggregateKind::Generator(def_id, generic_arg, movability) => {
-                stable_mir::mir::AggregateKind::Generator(
-                    tables.generator_def(*def_id),
+            mir::AggregateKind::Coroutine(def_id, generic_arg, movability) => {
+                stable_mir::mir::AggregateKind::Coroutine(
+                    tables.coroutine_def(*def_id),
                     generic_arg.stable(tables),
                     movability.stable(tables),
                 )
@@ -795,20 +874,20 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
     }
 }
 
-impl<'tcx> Stable<'tcx> for rustc_hir::GeneratorKind {
-    type T = stable_mir::mir::GeneratorKind;
+impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
+    type T = stable_mir::mir::CoroutineKind;
     fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
-        use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
+        use rustc_hir::{AsyncCoroutineKind, CoroutineKind};
         match self {
-            GeneratorKind::Async(async_gen) => {
+            CoroutineKind::Async(async_gen) => {
                 let async_gen = match async_gen {
-                    AsyncGeneratorKind::Block => stable_mir::mir::AsyncGeneratorKind::Block,
-                    AsyncGeneratorKind::Closure => stable_mir::mir::AsyncGeneratorKind::Closure,
-                    AsyncGeneratorKind::Fn => stable_mir::mir::AsyncGeneratorKind::Fn,
+                    AsyncCoroutineKind::Block => stable_mir::mir::AsyncCoroutineKind::Block,
+                    AsyncCoroutineKind::Closure => stable_mir::mir::AsyncCoroutineKind::Closure,
+                    AsyncCoroutineKind::Fn => stable_mir::mir::AsyncCoroutineKind::Fn,
                 };
-                stable_mir::mir::GeneratorKind::Async(async_gen)
+                stable_mir::mir::CoroutineKind::Async(async_gen)
             }
-            GeneratorKind::Gen => stable_mir::mir::GeneratorKind::Gen,
+            CoroutineKind::Coroutine => stable_mir::mir::CoroutineKind::Coroutine,
         }
     }
 }
@@ -911,7 +990,7 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
                 unwind: unwind.stable(tables),
             },
             mir::TerminatorKind::Yield { .. }
-            | mir::TerminatorKind::GeneratorDrop
+            | mir::TerminatorKind::CoroutineDrop
             | mir::TerminatorKind::FalseEdge { .. }
             | mir::TerminatorKind::FalseUnwind { .. } => unreachable!(),
         }
@@ -1166,8 +1245,8 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> {
                 tables.closure_def(*def_id),
                 generic_args.stable(tables),
             )),
-            ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
-                tables.generator_def(*def_id),
+            ty::Coroutine(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Coroutine(
+                tables.coroutine_def(*def_id),
                 generic_args.stable(tables),
                 movability.stable(tables),
             )),
@@ -1182,7 +1261,7 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> {
             ty::Bound(debruijn_idx, bound_ty) => {
                 TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables))
             }
-            ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) | ty::Error(_) => {
+            ty::Placeholder(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => {
                 unreachable!();
             }
         }
@@ -1610,3 +1689,38 @@ impl<'tcx> Stable<'tcx> for DefKind {
         opaque(self)
     }
 }
+
+impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
+    type T = stable_mir::mir::mono::Instance;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        let def = tables.instance_def(*self);
+        let kind = match self.def {
+            ty::InstanceDef::Item(..) => stable_mir::mir::mono::InstanceKind::Item,
+            ty::InstanceDef::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic,
+            ty::InstanceDef::Virtual(..) => stable_mir::mir::mono::InstanceKind::Virtual,
+            ty::InstanceDef::VTableShim(..)
+            | ty::InstanceDef::ReifyShim(..)
+            | ty::InstanceDef::FnPtrAddrShim(..)
+            | ty::InstanceDef::ClosureOnceShim { .. }
+            | ty::InstanceDef::ThreadLocalShim(..)
+            | ty::InstanceDef::DropGlue(..)
+            | ty::InstanceDef::CloneShim(..)
+            | ty::InstanceDef::FnPtrShim(..) => stable_mir::mir::mono::InstanceKind::Shim,
+        };
+        stable_mir::mir::mono::Instance { def, kind }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
+    type T = stable_mir::mir::mono::MonoItem;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::mir::mono::MonoItem as StableMonoItem;
+        match self {
+            MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables)),
+            MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)),
+            MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)),
+        }
+    }
+}