about summary refs log tree commit diff
path: root/compiler/rustc_public_bridge/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_public_bridge/src/lib.rs')
-rw-r--r--compiler/rustc_public_bridge/src/lib.rs305
1 files changed, 305 insertions, 0 deletions
diff --git a/compiler/rustc_public_bridge/src/lib.rs b/compiler/rustc_public_bridge/src/lib.rs
new file mode 100644
index 00000000000..652a8093a87
--- /dev/null
+++ b/compiler/rustc_public_bridge/src/lib.rs
@@ -0,0 +1,305 @@
+//! Crate that implements what will become the rustc side of Stable MIR.
+//!
+//! This crate is responsible for building Stable MIR components from internal components.
+//!
+//! This crate is not intended to be invoked directly by users.
+//! This crate is the public API of rustc that will be invoked by the `rustc_public` crate.
+//!
+//! For more information see <https://github.com/rust-lang/project-stable-mir>
+//!
+//! # Note
+//!
+//! This API is still completely unstable and subject to change.
+
+// tidy-alphabetical-start
+#![allow(internal_features)]
+#![allow(rustc::usage_of_ty_tykind)]
+#![doc(
+    html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
+    test(attr(allow(unused_variables), deny(warnings)))
+)]
+#![doc(rust_logo)]
+#![feature(rustdoc_internals)]
+#![feature(sized_hierarchy)]
+// tidy-alphabetical-end
+
+use std::cell::RefCell;
+use std::fmt::Debug;
+use std::hash::Hash;
+use std::ops::Index;
+
+use bridge::*;
+use context::SmirCtxt;
+use rustc_data_structures::fx::{self, FxIndexMap};
+use rustc_middle::mir;
+use rustc_middle::mir::interpret::AllocId;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::Span;
+use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
+
+pub mod alloc;
+pub mod bridge;
+mod builder;
+pub mod context;
+
+#[deprecated(note = "please use `rustc_public::rustc_internal` instead")]
+pub mod rustc_internal {}
+
+/// A container which is used for TLS.
+pub struct SmirContainer<'tcx, B: Bridge> {
+    pub tables: RefCell<Tables<'tcx, B>>,
+    pub cx: RefCell<SmirCtxt<'tcx, B>>,
+}
+
+pub struct Tables<'tcx, B: Bridge> {
+    pub def_ids: IndexMap<DefId, B::DefId>,
+    pub alloc_ids: IndexMap<AllocId, B::AllocId>,
+    pub spans: IndexMap<rustc_span::Span, B::Span>,
+    pub types: IndexMap<Ty<'tcx>, B::Ty>,
+    pub instances: IndexMap<ty::Instance<'tcx>, B::InstanceDef>,
+    pub ty_consts: IndexMap<ty::Const<'tcx>, B::TyConstId>,
+    pub mir_consts: IndexMap<mir::Const<'tcx>, B::MirConstId>,
+    pub layouts: IndexMap<rustc_abi::Layout<'tcx>, B::Layout>,
+}
+
+impl<'tcx, B: Bridge> Default for Tables<'tcx, B> {
+    fn default() -> Self {
+        Self {
+            def_ids: IndexMap::default(),
+            alloc_ids: IndexMap::default(),
+            spans: IndexMap::default(),
+            types: IndexMap::default(),
+            instances: IndexMap::default(),
+            ty_consts: IndexMap::default(),
+            mir_consts: IndexMap::default(),
+            layouts: IndexMap::default(),
+        }
+    }
+}
+
+impl<'tcx, B: Bridge> Index<B::DefId> for Tables<'tcx, B> {
+    type Output = DefId;
+
+    #[inline(always)]
+    fn index(&self, index: B::DefId) -> &Self::Output {
+        &self.def_ids[index]
+    }
+}
+
+impl<'tcx, B: Bridge> Tables<'tcx, B> {
+    pub fn intern_ty(&mut self, ty: Ty<'tcx>) -> B::Ty {
+        self.types.create_or_fetch(ty)
+    }
+
+    pub fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> B::TyConstId {
+        self.ty_consts.create_or_fetch(ct)
+    }
+
+    pub fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> B::MirConstId {
+        self.mir_consts.create_or_fetch(constant)
+    }
+
+    pub fn create_def_id(&mut self, did: DefId) -> B::DefId {
+        self.def_ids.create_or_fetch(did)
+    }
+
+    pub fn create_alloc_id(&mut self, aid: AllocId) -> B::AllocId {
+        self.alloc_ids.create_or_fetch(aid)
+    }
+
+    pub fn create_span(&mut self, span: Span) -> B::Span {
+        self.spans.create_or_fetch(span)
+    }
+
+    pub fn instance_def(&mut self, instance: ty::Instance<'tcx>) -> B::InstanceDef {
+        self.instances.create_or_fetch(instance)
+    }
+
+    pub fn layout_id(&mut self, layout: rustc_abi::Layout<'tcx>) -> B::Layout {
+        self.layouts.create_or_fetch(layout)
+    }
+
+    pub fn crate_item(&mut self, did: rustc_span::def_id::DefId) -> B::CrateItem {
+        B::CrateItem::new(self.create_def_id(did))
+    }
+
+    pub fn adt_def(&mut self, did: rustc_span::def_id::DefId) -> B::AdtDef {
+        B::AdtDef::new(self.create_def_id(did))
+    }
+
+    pub fn foreign_module_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignModuleDef {
+        B::ForeignModuleDef::new(self.create_def_id(did))
+    }
+
+    pub fn foreign_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignDef {
+        B::ForeignDef::new(self.create_def_id(did))
+    }
+
+    pub fn fn_def(&mut self, did: rustc_span::def_id::DefId) -> B::FnDef {
+        B::FnDef::new(self.create_def_id(did))
+    }
+
+    pub fn closure_def(&mut self, did: rustc_span::def_id::DefId) -> B::ClosureDef {
+        B::ClosureDef::new(self.create_def_id(did))
+    }
+
+    pub fn coroutine_def(&mut self, did: rustc_span::def_id::DefId) -> B::CoroutineDef {
+        B::CoroutineDef::new(self.create_def_id(did))
+    }
+
+    pub fn coroutine_closure_def(
+        &mut self,
+        did: rustc_span::def_id::DefId,
+    ) -> B::CoroutineClosureDef {
+        B::CoroutineClosureDef::new(self.create_def_id(did))
+    }
+
+    pub fn alias_def(&mut self, did: rustc_span::def_id::DefId) -> B::AliasDef {
+        B::AliasDef::new(self.create_def_id(did))
+    }
+
+    pub fn param_def(&mut self, did: rustc_span::def_id::DefId) -> B::ParamDef {
+        B::ParamDef::new(self.create_def_id(did))
+    }
+
+    pub fn br_named_def(&mut self, did: rustc_span::def_id::DefId) -> B::BrNamedDef {
+        B::BrNamedDef::new(self.create_def_id(did))
+    }
+
+    pub fn trait_def(&mut self, did: rustc_span::def_id::DefId) -> B::TraitDef {
+        B::TraitDef::new(self.create_def_id(did))
+    }
+
+    pub fn generic_def(&mut self, did: rustc_span::def_id::DefId) -> B::GenericDef {
+        B::GenericDef::new(self.create_def_id(did))
+    }
+
+    pub fn const_def(&mut self, did: rustc_span::def_id::DefId) -> B::ConstDef {
+        B::ConstDef::new(self.create_def_id(did))
+    }
+
+    pub fn impl_def(&mut self, did: rustc_span::def_id::DefId) -> B::ImplDef {
+        B::ImplDef::new(self.create_def_id(did))
+    }
+
+    pub fn region_def(&mut self, did: rustc_span::def_id::DefId) -> B::RegionDef {
+        B::RegionDef::new(self.create_def_id(did))
+    }
+
+    pub fn coroutine_witness_def(
+        &mut self,
+        did: rustc_span::def_id::DefId,
+    ) -> B::CoroutineWitnessDef {
+        B::CoroutineWitnessDef::new(self.create_def_id(did))
+    }
+
+    pub fn assoc_def(&mut self, did: rustc_span::def_id::DefId) -> B::AssocDef {
+        B::AssocDef::new(self.create_def_id(did))
+    }
+
+    pub fn opaque_def(&mut self, did: rustc_span::def_id::DefId) -> B::OpaqueDef {
+        B::OpaqueDef::new(self.create_def_id(did))
+    }
+
+    pub fn prov(&mut self, aid: rustc_middle::mir::interpret::AllocId) -> B::Prov {
+        B::Prov::new(self.create_alloc_id(aid))
+    }
+
+    pub fn static_def(&mut self, did: rustc_span::def_id::DefId) -> B::StaticDef {
+        B::StaticDef::new(self.create_def_id(did))
+    }
+}
+
+/// A trait defining types that are used to emulate StableMIR components, which is really
+/// useful when programming in rustc_public-agnostic settings.
+pub trait Bridge: Sized {
+    type DefId: Copy + Debug + PartialEq + IndexedVal;
+    type AllocId: Copy + Debug + PartialEq + IndexedVal;
+    type Span: Copy + Debug + PartialEq + IndexedVal;
+    type Ty: Copy + Debug + PartialEq + IndexedVal;
+    type InstanceDef: Copy + Debug + PartialEq + IndexedVal;
+    type TyConstId: Copy + Debug + PartialEq + IndexedVal;
+    type MirConstId: Copy + Debug + PartialEq + IndexedVal;
+    type Layout: Copy + Debug + PartialEq + IndexedVal;
+
+    type Error: SmirError;
+    type CrateItem: CrateItem<Self>;
+    type AdtDef: AdtDef<Self>;
+    type ForeignModuleDef: ForeignModuleDef<Self>;
+    type ForeignDef: ForeignDef<Self>;
+    type FnDef: FnDef<Self>;
+    type ClosureDef: ClosureDef<Self>;
+    type CoroutineDef: CoroutineDef<Self>;
+    type CoroutineClosureDef: CoroutineClosureDef<Self>;
+    type AliasDef: AliasDef<Self>;
+    type ParamDef: ParamDef<Self>;
+    type BrNamedDef: BrNamedDef<Self>;
+    type TraitDef: TraitDef<Self>;
+    type GenericDef: GenericDef<Self>;
+    type ConstDef: ConstDef<Self>;
+    type ImplDef: ImplDef<Self>;
+    type RegionDef: RegionDef<Self>;
+    type CoroutineWitnessDef: CoroutineWitnessDef<Self>;
+    type AssocDef: AssocDef<Self>;
+    type OpaqueDef: OpaqueDef<Self>;
+    type Prov: Prov<Self>;
+    type StaticDef: StaticDef<Self>;
+
+    type Allocation: Allocation<Self>;
+}
+
+pub trait IndexedVal {
+    fn to_val(index: usize) -> Self;
+
+    fn to_index(&self) -> usize;
+}
+
+/// Similar 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<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>
+{
+    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
+    }
+}
+
+/// Iterate over the definitions of the given crate.
+pub(crate) fn filter_def_ids<F, T>(tcx: TyCtxt<'_>, krate: CrateNum, mut func: F) -> Vec<T>
+where
+    F: FnMut(DefId) -> Option<T>,
+{
+    if krate == LOCAL_CRATE {
+        tcx.iter_local_def_id().filter_map(|did| func(did.to_def_id())).collect()
+    } else {
+        let num_definitions = tcx.num_extern_def_ids(krate);
+        (0..num_definitions)
+            .filter_map(move |i| {
+                let def_id = DefId { krate, index: rustc_span::def_id::DefIndex::from_usize(i) };
+                func(def_id)
+            })
+            .collect()
+    }
+}