diff options
Diffstat (limited to 'compiler/rustc_smir/src')
32 files changed, 293 insertions, 11151 deletions
| diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/alloc.rs index ecaf3571896..cad643f3709 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/alloc.rs @@ -11,14 +11,14 @@ use rustc_middle::mir::interpret::{ use rustc_middle::ty::{Ty, layout}; use super::{SmirCtxt, Tables}; -use crate::rustc_smir::bridge::Allocation as _; -use crate::rustc_smir::{Bridge, SmirError}; +use crate::bridge::Allocation as _; +use crate::{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; + use crate::context::SmirTypingEnv; cx.tcx.layout_of(cx.fully_monomorphized().as_query_input(ty)) } diff --git a/compiler/rustc_smir/src/rustc_smir/bridge.rs b/compiler/rustc_smir/src/bridge.rs index a31eb93d0e8..a31eb93d0e8 100644 --- a/compiler/rustc_smir/src/rustc_smir/bridge.rs +++ b/compiler/rustc_smir/src/bridge.rs diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/builder.rs index 2141053d09a..2141053d09a 100644 --- a/compiler/rustc_smir/src/rustc_smir/builder.rs +++ b/compiler/rustc_smir/src/builder.rs diff --git a/compiler/rustc_smir/src/rustc_smir/context/impls.rs b/compiler/rustc_smir/src/context/impls.rs index 89ae47143ef..9faadabe489 100644 --- a/compiler/rustc_smir/src/rustc_smir/context/impls.rs +++ b/compiler/rustc_smir/src/context/impls.rs @@ -25,8 +25,8 @@ use rustc_span::{FileNameDisplayPreference, Span, Symbol}; use rustc_target::callconv::FnAbi; use super::{SmirAllocRange, SmirCtxt, SmirTy, SmirTypingEnv}; -use crate::rustc_smir::builder::BodyBuilder; -use crate::rustc_smir::{Bridge, SmirError, Tables, filter_def_ids}; +use crate::builder::BodyBuilder; +use crate::{Bridge, SmirError, Tables, filter_def_ids}; impl<'tcx, B: Bridge> SmirTy<'tcx> for SmirCtxt<'tcx, B> { fn new_foreign(&self, def_id: DefId) -> ty::Ty<'tcx> { @@ -426,7 +426,7 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> { /// Evaluate constant as a target usize. pub fn eval_target_usize(&self, cnst: MirConst<'tcx>) -> Result<u64, B::Error> { - use crate::rustc_smir::context::SmirTypingEnv; + use crate::context::SmirTypingEnv; cnst.try_eval_target_usize(self.tcx, self.fully_monomorphized()) .ok_or_else(|| B::Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) } @@ -436,10 +436,7 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> { .ok_or_else(|| B::Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) } - pub(crate) fn try_new_const_zst( - &self, - ty_internal: Ty<'tcx>, - ) -> Result<MirConst<'tcx>, B::Error> { + pub fn try_new_const_zst(&self, ty_internal: Ty<'tcx>) -> Result<MirConst<'tcx>, B::Error> { let size = self .tcx .layout_of(self.fully_monomorphized().as_query_input(ty_internal)) diff --git a/compiler/rustc_smir/src/rustc_smir/context/mod.rs b/compiler/rustc_smir/src/context/mod.rs index 38743e5f7d3..da20be2a4b3 100644 --- a/compiler/rustc_smir/src/rustc_smir/context/mod.rs +++ b/compiler/rustc_smir/src/context/mod.rs @@ -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}; +use crate::{Bridge, SmirError}; mod impls; mod traits; @@ -18,7 +18,7 @@ pub use traits::*; /// Provides direct access to rustc's internal queries. /// -/// The [`crate::stable_mir::compiler_interface::SmirInterface`] must go through +/// `SmirInterface` must go through /// this context to obtain rustc-level information. pub struct SmirCtxt<'tcx, B: Bridge> { pub tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_smir/src/rustc_smir/context/traits.rs b/compiler/rustc_smir/src/context/traits.rs index 19e09016cdd..8483bee4aad 100644 --- a/compiler/rustc_smir/src/rustc_smir/context/traits.rs +++ b/compiler/rustc_smir/src/context/traits.rs @@ -8,31 +8,6 @@ use rustc_middle::ty; use rustc_middle::ty::Ty; use rustc_span::def_id::DefId; -pub trait SmirExistentialProjection<'tcx> { - fn new_from_args( - &self, - def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - term: ty::Term<'tcx>, - ) -> ty::ExistentialProjection<'tcx>; -} - -pub trait SmirExistentialTraitRef<'tcx> { - fn new_from_args( - &self, - trait_def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> ty::ExistentialTraitRef<'tcx>; -} - -pub trait SmirTraitRef<'tcx> { - fn new_from_args( - &self, - trait_def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> ty::TraitRef<'tcx>; -} - pub trait SmirTy<'tcx> { fn new_foreign(&self, def_id: DefId) -> Ty<'tcx>; } diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 067adda791d..fbebf98df7d 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -1,4 +1,9 @@ -//! The WIP stable interface to rustc internals. +//! 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 `stable_mir` crate. //! //! For more information see <https://github.com/rust-lang/project-stable-mir> //! @@ -18,8 +23,283 @@ #![feature(sized_hierarchy)] // tidy-alphabetical-end -pub mod rustc_internal; +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 `stable_mir::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 stable_mir-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; -pub mod rustc_smir; + 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 + } +} -pub mod stable_mir; +/// 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() + } +} diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs deleted file mode 100644 index dcdc77b76c2..00000000000 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ /dev/null @@ -1,273 +0,0 @@ -//! Module that implements the bridge between Stable MIR and internal compiler MIR. -//! -//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs -//! until stable MIR is complete. - -use std::cell::{Cell, RefCell}; - -use rustc_middle::ty::TyCtxt; -use rustc_span::def_id::CrateNum; -use scoped_tls::scoped_thread_local; -use stable_mir::Error; -use stable_mir::unstable::{RustcInternal, Stable}; - -use crate::rustc_smir::context::SmirCtxt; -use crate::rustc_smir::{Bridge, SmirContainer, Tables}; -use crate::stable_mir; - -pub mod pretty; - -/// Convert an internal Rust compiler item into its stable counterpart, if one exists. -/// -/// # Warning -/// -/// This function is unstable, and its behavior may change at any point. -/// E.g.: Items that were previously supported, may no longer be supported, or its translation may -/// change. -/// -/// # Panics -/// -/// This function will panic if StableMIR has not been properly initialized. -pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T { - with_container(|tables, cx| item.stable(tables, cx)) -} - -/// Convert a stable item into its internal Rust compiler counterpart, if one exists. -/// -/// # Warning -/// -/// This function is unstable, and it's behavior may change at any point. -/// Not every stable item can be converted to an internal one. -/// Furthermore, items that were previously supported, may no longer be supported in newer versions. -/// -/// # Panics -/// -/// This function will panic if StableMIR has not been properly initialized. -pub fn internal<'tcx, S>(tcx: TyCtxt<'tcx>, item: S) -> S::T<'tcx> -where - S: RustcInternal, -{ - // The tcx argument ensures that the item won't outlive the type context. - // See https://github.com/rust-lang/rust/pull/120128/commits/9aace6723572438a94378451793ca37deb768e72 - // for more details. - with_container(|tables, _| item.internal(tables, tcx)) -} - -pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { - item.id.into() -} - -// A thread local variable that stores a pointer to the tables mapping between TyCtxt -// datastructures and stable MIR datastructures -scoped_thread_local! (static TLV: Cell<*const ()>); - -pub(crate) fn init<'tcx, F, T, B: Bridge>(container: &SmirContainer<'tcx, B>, f: F) -> T -where - F: FnOnce() -> T, -{ - assert!(!TLV.is_set()); - let ptr = container as *const _ as *const (); - TLV.set(&Cell::new(ptr), || f()) -} - -/// Loads the current context and calls a function with it. -/// Do not nest these, as that will ICE. -pub(crate) fn with_container<R, B: Bridge>( - f: impl for<'tcx> FnOnce(&mut Tables<'tcx, B>, &SmirCtxt<'tcx, B>) -> R, -) -> R { - assert!(TLV.is_set()); - TLV.with(|tlv| { - let ptr = tlv.get(); - assert!(!ptr.is_null()); - let container = ptr as *const SmirContainer<'_, B>; - let mut tables = unsafe { (*container).tables.borrow_mut() }; - let cx = unsafe { (*container).cx.borrow() }; - f(&mut *tables, &*cx) - }) -} - -pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error> -where - F: FnOnce() -> T, -{ - let smir_cx = RefCell::new(SmirCtxt::new(tcx)); - let container = SmirContainer { tables: RefCell::new(Tables::default()), cx: smir_cx }; - - stable_mir::compiler_interface::run(&container, || init(&container, f)) -} - -/// Instantiate and run the compiler with the provided arguments and callback. -/// -/// The callback will be invoked after the compiler ran all its analyses, but before code generation. -/// Note that this macro accepts two different formats for the callback: -/// 1. An ident that resolves to a function that accepts no argument and returns `ControlFlow<B, C>` -/// ```ignore(needs-extern-crate) -/// # extern crate rustc_driver; -/// # extern crate rustc_interface; -/// # extern crate rustc_middle; -/// # #[macro_use] -/// # extern crate rustc_smir; -/// # extern crate stable_mir; -/// # -/// # fn main() { -/// # use std::ops::ControlFlow; -/// # use stable_mir::CompilerError; -/// fn analyze_code() -> ControlFlow<(), ()> { -/// // Your code goes in here. -/// # ControlFlow::Continue(()) -/// } -/// # let args = &["--verbose".to_string()]; -/// let result = run!(args, analyze_code); -/// # assert_eq!(result, Err(CompilerError::Skipped)) -/// # } -/// ``` -/// 2. A closure expression: -/// ```ignore(needs-extern-crate) -/// # extern crate rustc_driver; -/// # extern crate rustc_interface; -/// # extern crate rustc_middle; -/// # #[macro_use] -/// # extern crate rustc_smir; -/// # extern crate stable_mir; -/// # -/// # fn main() { -/// # use std::ops::ControlFlow; -/// # use stable_mir::CompilerError; -/// fn analyze_code(extra_args: Vec<String>) -> ControlFlow<(), ()> { -/// # let _ = extra_args; -/// // Your code goes in here. -/// # ControlFlow::Continue(()) -/// } -/// # let args = &["--verbose".to_string()]; -/// # let extra_args = vec![]; -/// let result = run!(args, || analyze_code(extra_args)); -/// # assert_eq!(result, Err(CompilerError::Skipped)) -/// # } -/// ``` -#[macro_export] -macro_rules! run { - ($args:expr, $callback_fn:ident) => { - run_driver!($args, || $callback_fn()) - }; - ($args:expr, $callback:expr) => { - run_driver!($args, $callback) - }; -} - -/// Instantiate and run the compiler with the provided arguments and callback. -/// -/// This is similar to `run` but it invokes the callback with the compiler's `TyCtxt`, -/// which can be used to invoke internal APIs. -#[macro_export] -macro_rules! run_with_tcx { - ($args:expr, $callback_fn:ident) => { - run_driver!($args, |tcx| $callback_fn(tcx), with_tcx) - }; - ($args:expr, $callback:expr) => { - run_driver!($args, $callback, with_tcx) - }; -} - -/// Optionally include an ident. This is needed due to macro hygiene. -#[macro_export] -#[doc(hidden)] -macro_rules! optional { - (with_tcx $ident:ident) => { - $ident - }; -} - -/// Prefer using [run!] and [run_with_tcx] instead. -/// -/// This macro implements the instantiation of a StableMIR driver, and it will invoke -/// the given callback after the compiler analyses. -/// -/// The third argument determines whether the callback requires `tcx` as an argument. -#[macro_export] -#[doc(hidden)] -macro_rules! run_driver { - ($args:expr, $callback:expr $(, $with_tcx:ident)?) => {{ - use rustc_driver::{Callbacks, Compilation, run_compiler}; - use rustc_middle::ty::TyCtxt; - use rustc_interface::interface; - use rustc_smir::rustc_internal; - use stable_mir::CompilerError; - use std::ops::ControlFlow; - - pub struct StableMir<B = (), C = (), F = fn($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C>> - where - B: Send, - C: Send, - F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send, - { - callback: Option<F>, - result: Option<ControlFlow<B, C>>, - } - - impl<B, C, F> StableMir<B, C, F> - where - B: Send, - C: Send, - F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send, - { - /// Creates a new `StableMir` instance, with given test_function and arguments. - pub fn new(callback: F) -> Self { - StableMir { callback: Some(callback), result: None } - } - - /// Runs the compiler against given target and tests it with `test_function` - pub fn run(&mut self, args: &[String]) -> Result<C, CompilerError<B>> { - let compiler_result = rustc_driver::catch_fatal_errors(|| -> interface::Result::<()> { - run_compiler(&args, self); - Ok(()) - }); - 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), - // Two cases here: - // - `run` finished normally and returned `Err` - // - `run` panicked with `FatalErr` - // You might think that normal compile errors cause the former, and - // ICEs cause the latter. But some normal compiler errors also cause - // the latter. So we can't meaningfully distinguish them, and group - // them together. - (Ok(Err(_)), _) | (Err(_), _) => Err(CompilerError::Failed), - } - } - } - - impl<B, C, F> Callbacks for StableMir<B, C, F> - where - B: Send, - C: Send, - F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, 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, - tcx: TyCtxt<'tcx>, - ) -> Compilation { - if let Some(callback) = self.callback.take() { - rustc_internal::run(tcx, || { - self.result = Some(callback($(optional!($with_tcx tcx))?)); - }) - .unwrap(); - if self.result.as_ref().is_some_and(|val| val.is_continue()) { - Compilation::Continue - } else { - Compilation::Stop - } - } else { - Compilation::Continue - } - } - } - - StableMir::new($callback).run($args) - }}; -} diff --git a/compiler/rustc_smir/src/rustc_internal/pretty.rs b/compiler/rustc_smir/src/rustc_internal/pretty.rs deleted file mode 100644 index 0710c18746a..00000000000 --- a/compiler/rustc_smir/src/rustc_internal/pretty.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::io; - -use rustc_middle::ty::TyCtxt; - -use super::run; -use crate::stable_mir; - -pub fn write_smir_pretty<'tcx, W: io::Write>(tcx: TyCtxt<'tcx>, w: &mut W) -> io::Result<()> { - writeln!( - w, - "// WARNING: This is highly experimental output it's intended for stable-mir developers only." - )?; - writeln!( - w, - "// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir." - )?; - let _ = run(tcx, || { - let items = stable_mir::all_local_items(); - let _ = items.iter().map(|item| -> io::Result<()> { item.emit_mir(w) }).collect::<Vec<_>>(); - }); - Ok(()) -} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs deleted file mode 100644 index e8b7a3fec09..00000000000 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ /dev/null @@ -1,286 +0,0 @@ -//! Module that implements what will become the rustc side of Stable MIR. - -//! This module is responsible for building Stable MIR components from internal components. -//! -//! This module is not intended to be invoked directly by users. It will eventually -//! become the public API of rustc that will be invoked by the `stable_mir` crate. -//! -//! For now, we are developing everything inside `rustc`, thus, we keep this module private. - -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; - -/// 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 stable_mir-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() - } -} diff --git a/compiler/rustc_smir/src/stable_mir/abi.rs b/compiler/rustc_smir/src/stable_mir/abi.rs deleted file mode 100644 index 369d08e444e..00000000000 --- a/compiler/rustc_smir/src/stable_mir/abi.rs +++ /dev/null @@ -1,494 +0,0 @@ -use std::fmt::{self, Debug}; -use std::num::NonZero; -use std::ops::RangeInclusive; - -use serde::Serialize; -use stable_mir::compiler_interface::with; -use stable_mir::mir::FieldIdx; -use stable_mir::target::{MachineInfo, MachineSize as Size}; -use stable_mir::ty::{Align, Ty, VariantIdx}; -use stable_mir::{Error, Opaque, error}; - -use crate::stable_mir; - -/// A function ABI definition. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub struct FnAbi { - /// The types of each argument. - pub args: Vec<ArgAbi>, - - /// The expected return type. - pub ret: ArgAbi, - - /// The count of non-variadic arguments. - /// - /// Should only be different from `args.len()` when a function is a C variadic function. - pub fixed_count: u32, - - /// The ABI convention. - pub conv: CallConvention, - - /// Whether this is a variadic C function, - pub c_variadic: bool, -} - -/// Information about the ABI of a function's argument, or return value. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub struct ArgAbi { - pub ty: Ty, - pub layout: Layout, - pub mode: PassMode, -} - -/// How a function argument should be passed in to the target function. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub enum PassMode { - /// Ignore the argument. - /// - /// The argument is either uninhabited or a ZST. - Ignore, - /// Pass the argument directly. - /// - /// The argument has a layout abi of `Scalar` or `Vector`. - Direct(Opaque), - /// Pass a pair's elements directly in two arguments. - /// - /// The argument has a layout abi of `ScalarPair`. - Pair(Opaque, Opaque), - /// Pass the argument after casting it. - Cast { pad_i32: bool, cast: Opaque }, - /// Pass the argument indirectly via a hidden pointer. - Indirect { attrs: Opaque, meta_attrs: Opaque, on_stack: bool }, -} - -/// The layout of a type, alongside the type itself. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub struct TyAndLayout { - pub ty: Ty, - pub layout: Layout, -} - -/// The layout of a type in memory. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub struct LayoutShape { - /// The fields location within the layout - pub fields: FieldsShape, - - /// Encodes information about multi-variant layouts. - /// Even with `Multiple` variants, a layout still has its own fields! Those are then - /// shared between all variants. - /// - /// To access all fields of this layout, both `fields` and the fields of the active variant - /// must be taken into account. - pub variants: VariantsShape, - - /// The `abi` defines how this data is passed between functions. - pub abi: ValueAbi, - - /// The ABI mandated alignment in bytes. - pub abi_align: Align, - - /// The size of this layout in bytes. - pub size: Size, -} - -impl LayoutShape { - /// Returns `true` if the layout corresponds to an unsized type. - #[inline] - pub fn is_unsized(&self) -> bool { - self.abi.is_unsized() - } - - #[inline] - pub fn is_sized(&self) -> bool { - !self.abi.is_unsized() - } - - /// Returns `true` if the type is sized and a 1-ZST (meaning it has size 0 and alignment 1). - pub fn is_1zst(&self) -> bool { - self.is_sized() && self.size.bits() == 0 && self.abi_align == 1 - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub struct Layout(usize); - -impl Layout { - pub fn shape(self) -> LayoutShape { - with(|cx| cx.layout_shape(self)) - } -} - -impl stable_mir::IndexedVal for Layout { - fn to_val(index: usize) -> Self { - Layout(index) - } - fn to_index(&self) -> usize { - self.0 - } -} - -/// Describes how the fields of a type are shaped in memory. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub enum FieldsShape { - /// Scalar primitives and `!`, which never have fields. - Primitive, - - /// All fields start at no offset. The `usize` is the field count. - Union(NonZero<usize>), - - /// Array/vector-like placement, with all fields of identical types. - Array { stride: Size, count: u64 }, - - /// Struct-like placement, with precomputed offsets. - /// - /// Fields are guaranteed to not overlap, but note that gaps - /// before, between and after all the fields are NOT always - /// padding, and as such their contents may not be discarded. - /// For example, enum variants leave a gap at the start, - /// where the discriminant field in the enum layout goes. - Arbitrary { - /// Offsets for the first byte of each field, - /// ordered to match the source definition order. - /// I.e.: It follows the same order as [super::ty::VariantDef::fields()]. - /// This vector does not go in increasing order. - offsets: Vec<Size>, - }, -} - -impl FieldsShape { - pub fn fields_by_offset_order(&self) -> Vec<FieldIdx> { - match self { - FieldsShape::Primitive => vec![], - FieldsShape::Union(_) | FieldsShape::Array { .. } => (0..self.count()).collect(), - FieldsShape::Arbitrary { offsets, .. } => { - let mut indices = (0..offsets.len()).collect::<Vec<_>>(); - indices.sort_by_key(|idx| offsets[*idx]); - indices - } - } - } - - pub fn count(&self) -> usize { - match self { - FieldsShape::Primitive => 0, - FieldsShape::Union(count) => count.get(), - FieldsShape::Array { count, .. } => *count as usize, - FieldsShape::Arbitrary { offsets, .. } => offsets.len(), - } - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub enum VariantsShape { - /// A type with no valid variants. Must be uninhabited. - Empty, - - /// Single enum variants, structs/tuples, unions, and all non-ADTs. - Single { index: VariantIdx }, - - /// Enum-likes with more than one inhabited variant: each variant comes with - /// a *discriminant* (usually the same as the variant index but the user can - /// assign explicit discriminant values). That discriminant is encoded - /// as a *tag* on the machine. The layout of each variant is - /// a struct, and they all have space reserved for the tag. - /// For enums, the tag is the sole field of the layout. - Multiple { - tag: Scalar, - tag_encoding: TagEncoding, - tag_field: usize, - variants: Vec<LayoutShape>, - }, -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub enum TagEncoding { - /// The tag directly stores the discriminant, but possibly with a smaller layout - /// (so converting the tag to the discriminant can require sign extension). - Direct, - - /// Niche (values invalid for a type) encoding the discriminant: - /// Discriminant and variant index coincide. - /// The variant `untagged_variant` contains a niche at an arbitrary - /// offset (field `tag_field` of the enum), which for a variant with - /// discriminant `d` is set to - /// `(d - niche_variants.start).wrapping_add(niche_start)`. - /// - /// For example, `Option<(usize, &T)>` is represented such that - /// `None` has a null pointer for the second tuple field, and - /// `Some` is the identity function (with a non-null reference). - Niche { - untagged_variant: VariantIdx, - niche_variants: RangeInclusive<VariantIdx>, - niche_start: u128, - }, -} - -/// Describes how values of the type are passed by target ABIs, -/// in terms of categories of C types there are ABI rules for. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub enum ValueAbi { - Scalar(Scalar), - ScalarPair(Scalar, Scalar), - Vector { - element: Scalar, - count: u64, - }, - Aggregate { - /// If true, the size is exact, otherwise it's only a lower bound. - sized: bool, - }, -} - -impl ValueAbi { - /// Returns `true` if the layout corresponds to an unsized type. - pub fn is_unsized(&self) -> bool { - match *self { - ValueAbi::Scalar(_) | ValueAbi::ScalarPair(..) | ValueAbi::Vector { .. } => false, - ValueAbi::Aggregate { sized } => !sized, - } - } -} - -/// Information about one scalar component of a Rust type. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize)] -pub enum Scalar { - Initialized { - /// The primitive type used to represent this value. - value: Primitive, - /// The range that represents valid values. - /// The range must be valid for the `primitive` size. - valid_range: WrappingRange, - }, - Union { - /// Unions never have niches, so there is no `valid_range`. - /// Even for unions, we need to use the correct registers for the kind of - /// values inside the union, so we keep the `Primitive` type around. - /// It is also used to compute the size of the scalar. - value: Primitive, - }, -} - -impl Scalar { - pub fn has_niche(&self, target: &MachineInfo) -> bool { - match self { - Scalar::Initialized { value, valid_range } => { - !valid_range.is_full(value.size(target)).unwrap() - } - Scalar::Union { .. } => false, - } - } -} - -/// Fundamental unit of memory access and layout. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize)] -pub enum Primitive { - /// The `bool` is the signedness of the `Integer` type. - /// - /// One would think we would not care about such details this low down, - /// but some ABIs are described in terms of C types and ISAs where the - /// integer arithmetic is done on {sign,zero}-extended registers, e.g. - /// a negative integer passed by zero-extension will appear positive in - /// the callee, and most operations on it will produce the wrong values. - Int { - length: IntegerLength, - signed: bool, - }, - Float { - length: FloatLength, - }, - Pointer(AddressSpace), -} - -impl Primitive { - pub fn size(self, target: &MachineInfo) -> Size { - match self { - Primitive::Int { length, .. } => Size::from_bits(length.bits()), - Primitive::Float { length } => Size::from_bits(length.bits()), - Primitive::Pointer(_) => target.pointer_width, - } - } -} - -/// Enum representing the existing integer lengths. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] -pub enum IntegerLength { - I8, - I16, - I32, - I64, - I128, -} - -/// Enum representing the existing float lengths. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] -pub enum FloatLength { - F16, - F32, - F64, - F128, -} - -impl IntegerLength { - pub fn bits(self) -> usize { - match self { - IntegerLength::I8 => 8, - IntegerLength::I16 => 16, - IntegerLength::I32 => 32, - IntegerLength::I64 => 64, - IntegerLength::I128 => 128, - } - } -} - -impl FloatLength { - pub fn bits(self) -> usize { - match self { - FloatLength::F16 => 16, - FloatLength::F32 => 32, - FloatLength::F64 => 64, - FloatLength::F128 => 128, - } - } -} - -/// An identifier that specifies the address space that some operation -/// should operate on. Special address spaces have an effect on code generation, -/// depending on the target and the address spaces it implements. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] -pub struct AddressSpace(pub u32); - -impl AddressSpace { - /// The default address space, corresponding to data space. - pub const DATA: Self = AddressSpace(0); -} - -/// Inclusive wrap-around range of valid values (bitwise representation), that is, if -/// start > end, it represents `start..=MAX`, followed by `0..=end`. -/// -/// That is, for an i8 primitive, a range of `254..=2` means following -/// sequence: -/// -/// 254 (-2), 255 (-1), 0, 1, 2 -#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)] -pub struct WrappingRange { - pub start: u128, - pub end: u128, -} - -impl WrappingRange { - /// Returns `true` if `size` completely fills the range. - #[inline] - pub fn is_full(&self, size: Size) -> Result<bool, Error> { - let Some(max_value) = size.unsigned_int_max() else { - return Err(error!("Expected size <= 128 bits, but found {} instead", size.bits())); - }; - if self.start <= max_value && self.end <= max_value { - Ok(self.start == (self.end.wrapping_add(1) & max_value)) - } else { - Err(error!("Range `{self:?}` out of bounds for size `{}` bits.", size.bits())) - } - } - - /// Returns `true` if `v` is contained in the range. - #[inline(always)] - pub fn contains(&self, v: u128) -> bool { - if self.wraps_around() { - self.start <= v || v <= self.end - } else { - self.start <= v && v <= self.end - } - } - - /// Returns `true` if the range wraps around. - /// I.e., the range represents the union of `self.start..=MAX` and `0..=self.end`. - /// Returns `false` if this is a non-wrapping range, i.e.: `self.start..=self.end`. - #[inline] - pub fn wraps_around(&self) -> bool { - self.start > self.end - } -} - -impl Debug for WrappingRange { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.start > self.end { - write!(fmt, "(..={}) | ({}..)", self.end, self.start)?; - } else { - write!(fmt, "{}..={}", self.start, self.end)?; - } - Ok(()) - } -} - -/// General language calling conventions. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub enum CallConvention { - C, - Rust, - - Cold, - PreserveMost, - PreserveAll, - - Custom, - - // Target-specific calling conventions. - ArmAapcs, - CCmseNonSecureCall, - CCmseNonSecureEntry, - - Msp430Intr, - - PtxKernel, - - GpuKernel, - - X86Fastcall, - X86Intr, - X86Stdcall, - X86ThisCall, - X86VectorCall, - - X86_64SysV, - X86_64Win64, - - AvrInterrupt, - AvrNonBlockingInterrupt, - - RiscvInterrupt, -} - -#[non_exhaustive] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] -pub struct ReprFlags { - pub is_simd: bool, - pub is_c: bool, - pub is_transparent: bool, - pub is_linear: bool, -} - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] -pub enum IntegerType { - /// Pointer-sized integer type, i.e. `isize` and `usize`. - Pointer { - /// Signedness. e.g. `true` for `isize` - is_signed: bool, - }, - /// Fixed-sized integer type, e.g. `i8`, `u32`, `i128`. - Fixed { - /// Length of this integer type. e.g. `IntegerLength::I8` for `u8`. - length: IntegerLength, - /// Signedness. e.g. `false` for `u8` - is_signed: bool, - }, -} - -/// Representation options provided by the user -#[non_exhaustive] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] -pub struct ReprOptions { - pub int: Option<IntegerType>, - pub align: Option<Align>, - pub pack: Option<Align>, - pub flags: ReprFlags, -} diff --git a/compiler/rustc_smir/src/stable_mir/alloc.rs b/compiler/rustc_smir/src/stable_mir/alloc.rs deleted file mode 100644 index 120cb4404b9..00000000000 --- a/compiler/rustc_smir/src/stable_mir/alloc.rs +++ /dev/null @@ -1,77 +0,0 @@ -//! Memory allocation implementation for StableMIR. -//! -//! This module is responsible for constructing stable components. -//! All operations requiring rustc queries must be delegated -//! to `rustc_smir::alloc` to maintain stability guarantees. - -use rustc_abi::Align; -use rustc_middle::mir::ConstValue; -use rustc_middle::mir::interpret::AllocRange; -use rustc_smir::bridge::SmirError; -use rustc_smir::context::SmirCtxt; -use rustc_smir::{Tables, alloc}; - -use super::Error; -use super::compiler_interface::BridgeTys; -use super::mir::Mutability; -use super::ty::{Allocation, ProvenanceMap}; -use super::unstable::Stable; -use crate::rustc_smir; - -/// Creates new empty `Allocation` from given `Align`. -fn new_empty_allocation(align: Align) -> Allocation { - Allocation { - bytes: Vec::new(), - provenance: ProvenanceMap { ptrs: Vec::new() }, - align: align.bytes(), - mutability: Mutability::Not, - } -} - -// We need this method instead of a Stable implementation -// because we need to get `Ty` of the const we are trying to create, to do that -// we need to have access to `ConstantKind` but we can't access that inside Stable impl. -#[allow(rustc::usage_of_qualified_ty)] -pub(crate) fn new_allocation<'tcx>( - ty: rustc_middle::ty::Ty<'tcx>, - const_value: ConstValue<'tcx>, - tables: &mut Tables<'tcx, BridgeTys>, - cx: &SmirCtxt<'tcx, BridgeTys>, -) -> Allocation { - try_new_allocation(ty, const_value, tables, cx) - .unwrap_or_else(|_| panic!("Failed to convert: {const_value:?} to {ty:?}")) -} - -#[allow(rustc::usage_of_qualified_ty)] -pub(crate) fn try_new_allocation<'tcx>( - ty: rustc_middle::ty::Ty<'tcx>, - const_value: ConstValue<'tcx>, - tables: &mut Tables<'tcx, BridgeTys>, - cx: &SmirCtxt<'tcx, BridgeTys>, -) -> Result<Allocation, Error> { - 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, 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, cx).map(|alloc| alloc.stable(tables, cx)) - } - ConstValue::Indirect { alloc_id, offset } => { - 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)) - } - } -} - -/// Creates an `Allocation` only from information within the `AllocRange`. -pub(super) fn allocation_filter<'tcx>( - alloc: &rustc_middle::mir::interpret::Allocation, - alloc_range: AllocRange, - tables: &mut Tables<'tcx, BridgeTys>, - cx: &SmirCtxt<'tcx, BridgeTys>, -) -> Allocation { - alloc::allocation_filter(alloc, alloc_range, tables, cx) -} diff --git a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs deleted file mode 100644 index a19968d2ab7..00000000000 --- a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs +++ /dev/null @@ -1,1100 +0,0 @@ -//! Define the interface with the Rust compiler. -//! -//! StableMIR users should not use any of the items in this module directly. -//! These APIs have no stability guarantee. - -use std::cell::Cell; - -use rustc_hir::def::DefKind; -use rustc_smir::context::SmirCtxt; -use rustc_smir::{Bridge, SmirContainer}; -use stable_mir::abi::{FnAbi, Layout, LayoutShape, ReprOptions}; -use stable_mir::crate_def::Attribute; -use stable_mir::mir::alloc::{AllocId, GlobalAlloc}; -use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef}; -use stable_mir::mir::{BinOp, Body, Place, UnOp}; -use stable_mir::target::{MachineInfo, MachineSize}; -use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef, - ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, - Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, - TraitDecl, TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, VariantIdx, -}; -use stable_mir::unstable::{RustcInternal, Stable, new_item_kind}; -use stable_mir::{ - AssocItems, Crate, CrateDef, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, - ImplTraitDecls, ItemKind, Symbol, TraitDecls, alloc, mir, -}; -use tracing::debug; - -use crate::{rustc_smir, stable_mir}; - -pub struct BridgeTys; - -impl Bridge for BridgeTys { - type DefId = stable_mir::DefId; - type AllocId = stable_mir::mir::alloc::AllocId; - type Span = stable_mir::ty::Span; - type Ty = stable_mir::ty::Ty; - type InstanceDef = stable_mir::mir::mono::InstanceDef; - type TyConstId = stable_mir::ty::TyConstId; - type MirConstId = stable_mir::ty::MirConstId; - type Layout = stable_mir::abi::Layout; - - type Error = stable_mir::Error; - type CrateItem = stable_mir::CrateItem; - type AdtDef = stable_mir::ty::AdtDef; - type ForeignModuleDef = stable_mir::ty::ForeignModuleDef; - type ForeignDef = stable_mir::ty::ForeignDef; - type FnDef = stable_mir::ty::FnDef; - type ClosureDef = stable_mir::ty::ClosureDef; - type CoroutineDef = stable_mir::ty::CoroutineDef; - type CoroutineClosureDef = stable_mir::ty::CoroutineClosureDef; - type AliasDef = stable_mir::ty::AliasDef; - type ParamDef = stable_mir::ty::ParamDef; - type BrNamedDef = stable_mir::ty::BrNamedDef; - type TraitDef = stable_mir::ty::TraitDef; - type GenericDef = stable_mir::ty::GenericDef; - type ConstDef = stable_mir::ty::ConstDef; - type ImplDef = stable_mir::ty::ImplDef; - type RegionDef = stable_mir::ty::RegionDef; - type CoroutineWitnessDef = stable_mir::ty::CoroutineWitnessDef; - type AssocDef = stable_mir::ty::AssocDef; - type OpaqueDef = stable_mir::ty::OpaqueDef; - type Prov = stable_mir::ty::Prov; - type StaticDef = stable_mir::mir::mono::StaticDef; - - type Allocation = stable_mir::ty::Allocation; -} - -/// Stable public API for querying compiler information. -/// -/// All queries are delegated to [`crate::rustc_smir::context::SmirCtxt`] that provides -/// similar APIs but based on internal rustc constructs. -/// -/// Do not use this directly. This is currently used in the macro expansion. -pub(crate) trait SmirInterface { - fn entry_fn(&self) -> Option<CrateItem>; - /// Retrieve all items of the local crate that have a MIR associated with them. - fn all_local_items(&self) -> CrateItems; - /// Retrieve the body of a function. - /// This function will panic if the body is not available. - fn mir_body(&self, item: DefId) -> mir::Body; - /// Check whether the body of a function is available. - fn has_body(&self, item: DefId) -> bool; - fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef>; - - /// Retrieve all functions defined in this crate. - fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef>; - - /// Retrieve all static items defined in this crate. - fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef>; - fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule; - fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef>; - fn all_trait_decls(&self) -> TraitDecls; - fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls; - fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl; - fn all_trait_impls(&self) -> ImplTraitDecls; - fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls; - fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait; - fn generics_of(&self, def_id: DefId) -> Generics; - fn predicates_of(&self, def_id: DefId) -> GenericPredicates; - fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates; - - /// Get information about the local crate. - fn local_crate(&self) -> Crate; - /// Retrieve a list of all external crates. - fn external_crates(&self) -> Vec<Crate>; - - /// Find a crate with the given name. - fn find_crates(&self, name: &str) -> Vec<Crate>; - - /// Returns the name of given `DefId` - fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol; - - /// Return registered tool attributes with the given attribute name. - /// - /// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool - /// attributes will simply return an empty list. - /// - /// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`. - /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`. - fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute>; - - /// Get all tool attributes of a definition. - fn all_tool_attrs(&self, def_id: DefId) -> Vec<Attribute>; - - /// Returns printable, human readable form of `Span` - fn span_to_string(&self, span: Span) -> String; - - /// Return filename from given `Span`, for diagnostic purposes - fn get_filename(&self, span: &Span) -> Filename; - - /// Return lines corresponding to this `Span` - fn get_lines(&self, span: &Span) -> LineInfo; - - /// Returns the `kind` of given `DefId` - fn item_kind(&self, item: CrateItem) -> ItemKind; - - /// Returns whether this is a foreign item. - fn is_foreign_item(&self, item: DefId) -> bool; - - /// Returns the kind of a given foreign item. - fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind; - - /// Returns the kind of a given algebraic data type - fn adt_kind(&self, def: AdtDef) -> AdtKind; - - /// Returns if the ADT is a box. - fn adt_is_box(&self, def: AdtDef) -> bool; - - /// Returns whether this ADT is simd. - fn adt_is_simd(&self, def: AdtDef) -> bool; - - /// Returns whether this definition is a C string. - fn adt_is_cstr(&self, def: AdtDef) -> bool; - - /// Returns the representation options for this ADT. - fn adt_repr(&self, def: AdtDef) -> ReprOptions; - - /// Retrieve the function signature for the given generic arguments. - fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig; - - /// Retrieve the intrinsic definition if the item corresponds one. - fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef>; - - /// Retrieve the plain function name of an intrinsic. - fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol; - - /// Retrieve the closure signature for the given generic arguments. - fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig; - - /// The number of variants in this ADT. - fn adt_variants_len(&self, def: AdtDef) -> usize; - - /// Discriminant for a given variant index of AdtDef. - fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr; - - /// Discriminant for a given variand index and args of a coroutine. - fn coroutine_discr_for_variant( - &self, - coroutine: CoroutineDef, - args: &GenericArgs, - variant: VariantIdx, - ) -> Discr; - - /// The name of a variant. - fn variant_name(&self, def: VariantDef) -> Symbol; - fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef>; - - /// Evaluate constant as a target usize. - fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error>; - fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error>; - - /// Create a new zero-sized constant. - fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error>; - - /// Create a new constant that represents the given string value. - fn new_const_str(&self, value: &str) -> MirConst; - - /// Create a new constant that represents the given boolean value. - fn new_const_bool(&self, value: bool) -> MirConst; - - /// Create a new constant that represents the given value. - fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error>; - fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<TyConst, Error>; - - /// Create a new type from the given kind. - fn new_rigid_ty(&self, kind: RigidTy) -> Ty; - - /// Create a new box type, `Box<T>`, for the given inner type `T`. - fn new_box_ty(&self, ty: Ty) -> Ty; - - /// Returns the type of given crate item. - fn def_ty(&self, item: DefId) -> Ty; - - /// Returns the type of given definition instantiated with the given arguments. - fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty; - - /// Returns literal value of a const as a string. - fn mir_const_pretty(&self, cnst: &MirConst) -> String; - - /// `Span` of an item - fn span_of_an_item(&self, def_id: DefId) -> Span; - - fn ty_const_pretty(&self, ct: TyConstId) -> String; - - /// Obtain the representation of a type. - fn ty_pretty(&self, ty: Ty) -> String; - - /// Obtain the kind of a type. - fn ty_kind(&self, ty: Ty) -> TyKind; - - // Get the discriminant Ty for this Ty if there's one. - fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty; - - /// Get the body of an Instance which is already monomorphized. - fn instance_body(&self, instance: InstanceDef) -> Option<Body>; - - /// Get the instance type with generic instantiations applied and lifetimes erased. - fn instance_ty(&self, instance: InstanceDef) -> Ty; - - /// Get the instantiation types. - fn instance_args(&self, def: InstanceDef) -> GenericArgs; - - /// Get the instance. - fn instance_def_id(&self, instance: InstanceDef) -> DefId; - - /// Get the instance mangled name. - fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol; - - /// Check if this is an empty DropGlue shim. - fn is_empty_drop_shim(&self, def: InstanceDef) -> bool; - - /// Convert a non-generic crate item into an instance. - /// This function will panic if the item is generic. - fn mono_instance(&self, def_id: DefId) -> Instance; - - /// Item requires monomorphization. - fn requires_monomorphization(&self, def_id: DefId) -> bool; - - /// Resolve an instance from the given function definition and generic arguments. - fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>; - - /// Resolve an instance for drop_in_place for the given type. - fn resolve_drop_in_place(&self, ty: Ty) -> Instance; - - /// Resolve instance for a function pointer. - fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>; - - /// Resolve instance for a closure with the requested type. - fn resolve_closure( - &self, - def: ClosureDef, - args: &GenericArgs, - kind: ClosureKind, - ) -> Option<Instance>; - - /// Evaluate a static's initializer. - fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error>; - - /// Try to evaluate an instance into a constant. - fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error>; - - /// Retrieve global allocation for the given allocation ID. - fn global_alloc(&self, id: AllocId) -> GlobalAlloc; - - /// Retrieve the id for the virtual table. - fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>; - fn krate(&self, def_id: DefId) -> Crate; - fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol; - - /// Return information about the target machine. - fn target_info(&self) -> MachineInfo; - - /// Get an instance ABI. - fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error>; - - /// Get the ABI of a function pointer. - fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error>; - - /// Get the layout of a type. - fn ty_layout(&self, ty: Ty) -> Result<Layout, Error>; - - /// Get the layout shape. - fn layout_shape(&self, id: Layout) -> LayoutShape; - - /// Get a debug string representation of a place. - fn place_pretty(&self, place: &Place) -> String; - - /// Get the resulting type of binary operation. - fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty; - - /// Get the resulting type of unary operation. - fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty; - - /// Get all associated items of a definition. - fn associated_items(&self, def_id: DefId) -> AssocItems; -} - -impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> { - fn entry_fn(&self) -> Option<CrateItem> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = cx.entry_fn(); - Some(tables.crate_item(did?)) - } - - /// Retrieve all items of the local crate that have a MIR associated with them. - fn all_local_items(&self) -> CrateItems { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.all_local_items().iter().map(|did| tables.crate_item(*did)).collect() - } - - /// Retrieve the body of a function. - /// This function will panic if the body is not available. - fn mir_body(&self, item: DefId) -> mir::Body { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[item]; - cx.mir_body(did).stable(&mut *tables, cx) - } - - /// Check whether the body of a function is available. - fn has_body(&self, item: DefId) -> bool { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let def = item.internal(&mut *tables, cx.tcx); - cx.has_body(def) - } - - fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.foreign_modules(crate_num.internal(&mut *tables, cx.tcx)) - .iter() - .map(|did| tables.foreign_module_def(*did)) - .collect() - } - - /// Retrieve all functions defined in this crate. - fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let krate = crate_num.internal(&mut *tables, cx.tcx); - 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 krate = crate_num.internal(&mut *tables, cx.tcx); - cx.crate_statics(krate).iter().map(|did| tables.static_def(*did)).collect() - } - - fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[mod_def.def_id()]; - cx.foreign_module(did).stable(&mut *tables, cx) - } - - fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[mod_def.def_id()]; - cx.foreign_items(did).iter().map(|did| tables.foreign_def(*did)).collect() - } - - fn all_trait_decls(&self) -> TraitDecls { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.all_trait_decls().map(|did| tables.trait_def(did)).collect() - } - - fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let krate = crate_num.internal(&mut *tables, cx.tcx); - cx.trait_decls(krate).iter().map(|did| tables.trait_def(*did)).collect() - } - - fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[trait_def.0]; - cx.trait_decl(did).stable(&mut *tables, cx) - } - - fn all_trait_impls(&self) -> ImplTraitDecls { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.all_trait_impls().iter().map(|did| tables.impl_def(*did)).collect() - } - - fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let krate = crate_num.internal(&mut *tables, cx.tcx); - cx.trait_impls(krate).iter().map(|did| tables.impl_def(*did)).collect() - } - - fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[trait_impl.0]; - cx.trait_impl(did).stable(&mut *tables, cx) - } - - fn generics_of(&self, def_id: DefId) -> Generics { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[def_id]; - cx.generics_of(did).stable(&mut *tables, cx) - } - - fn predicates_of(&self, def_id: DefId) -> GenericPredicates { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[def_id]; - let (parent, kinds) = cx.predicates_of(did); - stable_mir::ty::GenericPredicates { - parent: parent.map(|did| tables.trait_def(did)), - predicates: kinds - .iter() - .map(|(kind, span)| (kind.stable(&mut *tables, cx), span.stable(&mut *tables, cx))) - .collect(), - } - } - - fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[def_id]; - let (parent, kinds) = cx.explicit_predicates_of(did); - stable_mir::ty::GenericPredicates { - parent: parent.map(|did| tables.trait_def(did)), - predicates: kinds - .iter() - .map(|(kind, span)| (kind.stable(&mut *tables, cx), span.stable(&mut *tables, cx))) - .collect(), - } - } - - /// Get information about the local crate. - fn local_crate(&self) -> Crate { - let cx = &*self.cx.borrow(); - smir_crate(cx, cx.local_crate_num()) - } - - /// Retrieve a list of all external crates. - fn external_crates(&self) -> Vec<Crate> { - let cx = &*self.cx.borrow(); - cx.external_crates().iter().map(|crate_num| smir_crate(cx, *crate_num)).collect() - } - - /// Find a crate with the given name. - fn find_crates(&self, name: &str) -> Vec<Crate> { - let cx = &*self.cx.borrow(); - cx.find_crates(name).iter().map(|crate_num| smir_crate(cx, *crate_num)).collect() - } - - /// Returns the name of given `DefId`. - fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol { - let tables = self.tables.borrow(); - let cx = &*self.cx.borrow(); - let did = tables[def_id]; - cx.def_name(did, trimmed) - } - - /// Return registered tool attributes with the given attribute name. - /// - /// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool - /// attributes will simply return an empty list. - /// - /// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`. - /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`. - fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[def_id]; - cx.tool_attrs(did, attr) - .into_iter() - .map(|(attr_str, span)| Attribute::new(attr_str, span.stable(&mut *tables, cx))) - .collect() - } - - /// Get all tool attributes of a definition. - fn all_tool_attrs(&self, def_id: DefId) -> Vec<Attribute> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[def_id]; - cx.all_tool_attrs(did) - .into_iter() - .map(|(attr_str, span)| Attribute::new(attr_str, span.stable(&mut *tables, cx))) - .collect() - } - - /// Returns printable, human readable form of `Span`. - fn span_to_string(&self, span: Span) -> String { - let tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let sp = tables.spans[span]; - cx.span_to_string(sp) - } - - /// Return filename from given `Span`, for diagnostic purposes. - fn get_filename(&self, span: &Span) -> Filename { - let tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let sp = tables.spans[*span]; - cx.get_filename(sp) - } - - /// Return lines corresponding to this `Span`. - fn get_lines(&self, span: &Span) -> LineInfo { - let tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let sp = tables.spans[*span]; - let lines = cx.get_lines(sp); - LineInfo::from(lines) - } - - /// Returns the `kind` of given `DefId`. - fn item_kind(&self, item: CrateItem) -> ItemKind { - let tables = self.tables.borrow(); - let cx = &*self.cx.borrow(); - let did = tables[item.0]; - new_item_kind(cx.def_kind(did)) - } - - /// Returns whether this is a foreign item. - fn is_foreign_item(&self, item: DefId) -> bool { - let tables = self.tables.borrow(); - let cx = &*self.cx.borrow(); - let did = tables[item]; - cx.is_foreign_item(did) - } - - /// Returns the kind of a given foreign item. - fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let def_id = tables[def.def_id()]; - let def_kind = cx.foreign_item_kind(def_id); - match def_kind { - DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)), - DefKind::Static { .. } => ForeignItemKind::Static(tables.static_def(def_id)), - DefKind::ForeignTy => { - use rustc_smir::context::SmirTy; - ForeignItemKind::Type(tables.intern_ty(cx.new_foreign(def_id))) - } - def_kind => unreachable!("Unexpected kind for a foreign item: {:?}", def_kind), - } - } - - /// Returns the kind of a given algebraic data type. - fn adt_kind(&self, def: AdtDef) -> AdtKind { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.adt_kind(def.internal(&mut *tables, cx.tcx)).stable(&mut *tables, cx) - } - - /// Returns if the ADT is a box. - fn adt_is_box(&self, def: AdtDef) -> bool { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.adt_is_box(def.internal(&mut *tables, cx.tcx)) - } - - /// Returns whether this ADT is simd. - fn adt_is_simd(&self, def: AdtDef) -> bool { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.adt_is_simd(def.internal(&mut *tables, cx.tcx)) - } - - /// Returns whether this definition is a C string. - fn adt_is_cstr(&self, def: AdtDef) -> bool { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.adt_is_cstr(def.0.internal(&mut *tables, cx.tcx)) - } - - /// Returns the representation options for this ADT - fn adt_repr(&self, def: AdtDef) -> ReprOptions { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.adt_repr(def.internal(&mut *tables, cx.tcx)).stable(&mut *tables, cx) - } - - /// Retrieve the function signature for the given generic arguments. - fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let def_id = def.0.internal(&mut *tables, cx.tcx); - let args_ref = args.internal(&mut *tables, cx.tcx); - cx.fn_sig(def_id, args_ref).stable(&mut *tables, cx) - } - - /// Retrieve the intrinsic definition if the item corresponds one. - fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let def_id = item.internal(&mut *tables, cx.tcx); - cx.intrinsic(def_id).map(|_| IntrinsicDef(item)) - } - - /// Retrieve the plain function name of an intrinsic. - fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let def_id = def.0.internal(&mut *tables, cx.tcx); - cx.intrinsic_name(def_id) - } - - /// Retrieve the closure signature for the given generic arguments. - fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let args_ref = args.internal(&mut *tables, cx.tcx); - cx.closure_sig(args_ref).stable(&mut *tables, cx) - } - - /// The number of variants in this ADT. - fn adt_variants_len(&self, def: AdtDef) -> usize { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.adt_variants_len(def.internal(&mut *tables, cx.tcx)) - } - - /// Discriminant for a given variant index of AdtDef. - fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.adt_discr_for_variant( - adt.internal(&mut *tables, cx.tcx), - variant.internal(&mut *tables, cx.tcx), - ) - .stable(&mut *tables, cx) - } - - /// Discriminant for a given variand index and args of a coroutine. - fn coroutine_discr_for_variant( - &self, - coroutine: CoroutineDef, - args: &GenericArgs, - variant: VariantIdx, - ) -> Discr { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let tcx = cx.tcx; - let def = coroutine.def_id().internal(&mut *tables, tcx); - let args_ref = args.internal(&mut *tables, tcx); - cx.coroutine_discr_for_variant(def, args_ref, variant.internal(&mut *tables, tcx)) - .stable(&mut *tables, cx) - } - - /// The name of a variant. - fn variant_name(&self, def: VariantDef) -> Symbol { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.variant_name(def.internal(&mut *tables, cx.tcx)) - } - - fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - def.internal(&mut *tables, cx.tcx) - .fields - .iter() - .map(|f| f.stable(&mut *tables, cx)) - .collect() - } - - /// Evaluate constant as a target usize. - fn eval_target_usize(&self, mir_const: &MirConst) -> Result<u64, Error> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let cnst = mir_const.internal(&mut *tables, cx.tcx); - cx.eval_target_usize(cnst) - } - - fn eval_target_usize_ty(&self, ty_const: &TyConst) -> Result<u64, Error> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let cnst = ty_const.internal(&mut *tables, cx.tcx); - cx.eval_target_usize_ty(cnst) - } - - /// Create a new zero-sized constant. - fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let ty_internal = ty.internal(&mut *tables, cx.tcx); - cx.try_new_const_zst(ty_internal).map(|cnst| cnst.stable(&mut *tables, cx)) - } - - /// Create a new constant that represents the given string value. - fn new_const_str(&self, value: &str) -> MirConst { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.new_const_str(value).stable(&mut *tables, cx) - } - - /// Create a new constant that represents the given boolean value. - fn new_const_bool(&self, value: bool) -> MirConst { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.new_const_bool(value).stable(&mut *tables, cx) - } - - /// Create a new constant that represents the given value. - fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx.tcx)); - cx.try_new_const_uint(value, ty).map(|cnst| cnst.stable(&mut *tables, cx)) - } - - fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<TyConst, Error> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx.tcx)); - cx.try_new_ty_const_uint(value, ty).map(|cnst| cnst.stable(&mut *tables, cx)) - } - - /// Create a new type from the given kind. - fn new_rigid_ty(&self, kind: RigidTy) -> Ty { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let internal_kind = kind.internal(&mut *tables, cx.tcx); - cx.new_rigid_ty(internal_kind).stable(&mut *tables, cx) - } - - /// Create a new box type, `Box<T>`, for the given inner type `T`. - fn new_box_ty(&self, ty: Ty) -> Ty { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let inner = ty.internal(&mut *tables, cx.tcx); - cx.new_box_ty(inner).stable(&mut *tables, cx) - } - - /// Returns the type of given crate item. - fn def_ty(&self, item: DefId) -> Ty { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let inner = item.internal(&mut *tables, cx.tcx); - cx.def_ty(inner).stable(&mut *tables, cx) - } - - /// Returns the type of given definition instantiated with the given arguments. - fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let inner = item.internal(&mut *tables, cx.tcx); - let args_ref = args.internal(&mut *tables, cx.tcx); - cx.def_ty_with_args(inner, args_ref).stable(&mut *tables, cx) - } - - /// Returns literal value of a const as a string. - fn mir_const_pretty(&self, cnst: &MirConst) -> String { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cnst.internal(&mut *tables, cx.tcx).to_string() - } - - /// `Span` of an item. - fn span_of_an_item(&self, def_id: DefId) -> Span { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[def_id]; - cx.span_of_an_item(did).stable(&mut *tables, cx) - } - - fn ty_const_pretty(&self, ct: TyConstId) -> String { - let tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.ty_const_pretty(tables.ty_consts[ct]) - } - - /// Obtain the representation of a type. - fn ty_pretty(&self, ty: Ty) -> String { - let tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.ty_pretty(tables.types[ty]) - } - - /// Obtain the kind of a type. - fn ty_kind(&self, ty: Ty) -> TyKind { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - cx.ty_kind(tables.types[ty]).stable(&mut *tables, cx) - } - - /// Get the discriminant Ty for this Ty if there's one. - fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let internal_kind = ty.internal(&mut *tables, cx.tcx); - cx.rigid_ty_discriminant_ty(internal_kind).stable(&mut *tables, cx) - } - - /// Get the body of an Instance which is already monomorphized. - fn instance_body(&self, instance: InstanceDef) -> Option<Body> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let instance = tables.instances[instance]; - cx.instance_body(instance).map(|body| body.stable(&mut *tables, cx)) - } - - /// Get the instance type with generic instantiations applied and lifetimes erased. - fn instance_ty(&self, instance: InstanceDef) -> Ty { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let instance = tables.instances[instance]; - cx.instance_ty(instance).stable(&mut *tables, cx) - } - - /// Get the instantiation types. - fn instance_args(&self, def: InstanceDef) -> GenericArgs { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let instance = tables.instances[def]; - cx.instance_args(instance).stable(&mut *tables, cx) - } - - /// Get the instance. - fn instance_def_id(&self, instance: InstanceDef) -> DefId { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let instance = tables.instances[instance]; - cx.instance_def_id(instance, &mut *tables) - } - - /// Get the instance mangled name. - fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol { - let tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let instance = tables.instances[instance]; - cx.instance_mangled_name(instance) - } - - /// Check if this is an empty DropGlue shim. - fn is_empty_drop_shim(&self, def: InstanceDef) -> bool { - let tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let instance = tables.instances[def]; - cx.is_empty_drop_shim(instance) - } - - /// Convert a non-generic crate item into an instance. - /// This function will panic if the item is generic. - fn mono_instance(&self, def_id: DefId) -> Instance { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[def_id]; - cx.mono_instance(did).stable(&mut *tables, cx) - } - - /// Item requires monomorphization. - fn requires_monomorphization(&self, def_id: DefId) -> bool { - let tables = self.tables.borrow(); - let cx = &*self.cx.borrow(); - let did = tables[def_id]; - cx.requires_monomorphization(did) - } - - /// Resolve an instance from the given function definition and generic arguments. - fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let def_id = def.0.internal(&mut *tables, cx.tcx); - let args_ref = args.internal(&mut *tables, cx.tcx); - cx.resolve_instance(def_id, args_ref).map(|inst| inst.stable(&mut *tables, cx)) - } - - /// Resolve an instance for drop_in_place for the given type. - fn resolve_drop_in_place(&self, ty: Ty) -> Instance { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let internal_ty = ty.internal(&mut *tables, cx.tcx); - - cx.resolve_drop_in_place(internal_ty).stable(&mut *tables, cx) - } - - /// Resolve instance for a function pointer. - fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let def_id = def.0.internal(&mut *tables, cx.tcx); - let args_ref = args.internal(&mut *tables, cx.tcx); - cx.resolve_for_fn_ptr(def_id, args_ref).stable(&mut *tables, cx) - } - - /// Resolve instance for a closure with the requested type. - fn resolve_closure( - &self, - def: ClosureDef, - args: &GenericArgs, - kind: ClosureKind, - ) -> Option<Instance> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let def_id = def.0.internal(&mut *tables, cx.tcx); - let args_ref = args.internal(&mut *tables, cx.tcx); - let closure_kind = kind.internal(&mut *tables, cx.tcx); - cx.resolve_closure(def_id, args_ref, closure_kind).map(|inst| inst.stable(&mut *tables, cx)) - } - - /// Evaluate a static's initializer. - fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let def_id = def.0.internal(&mut *tables, cx.tcx); - - cx.eval_static_initializer(def_id).stable(&mut *tables, cx) - } - - /// Try to evaluate an instance into a constant. - fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error> { - let mut tables = self.tables.borrow_mut(); - let instance = tables.instances[def]; - let cx = &*self.cx.borrow(); - let const_ty = const_ty.internal(&mut *tables, cx.tcx); - cx.eval_instance(instance) - .map(|const_val| alloc::try_new_allocation(const_ty, const_val, &mut *tables, cx)) - .map_err(|e| e.stable(&mut *tables, cx))? - } - - /// Retrieve global allocation for the given allocation ID. - fn global_alloc(&self, id: AllocId) -> GlobalAlloc { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let alloc_id = id.internal(&mut *tables, cx.tcx); - cx.global_alloc(alloc_id).stable(&mut *tables, cx) - } - - /// Retrieve the id for the virtual table. - fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId> { - let mut tables = self.tables.borrow_mut(); - let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else { - return None; - }; - let cx = &*self.cx.borrow(); - let ty = ty.internal(&mut *tables, cx.tcx); - let trait_ref = trait_ref.internal(&mut *tables, cx.tcx); - let alloc_id = cx.vtable_allocation(ty, trait_ref); - Some(alloc_id.stable(&mut *tables, cx)) - } - - fn krate(&self, def_id: DefId) -> Crate { - let tables = self.tables.borrow(); - let cx = &*self.cx.borrow(); - smir_crate(cx, tables[def_id].krate) - } - - fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol { - let tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let instance = tables.instances[def]; - cx.instance_name(instance, trimmed) - } - - /// Return information about the target machine. - fn target_info(&self) -> MachineInfo { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - MachineInfo { - endian: cx.target_endian().stable(&mut *tables, cx), - pointer_width: MachineSize::from_bits(cx.target_pointer_size()), - } - } - - /// Get an instance ABI. - fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let instance = tables.instances[def]; - cx.instance_abi(instance).map(|fn_abi| fn_abi.stable(&mut *tables, cx)) - } - - /// Get the ABI of a function pointer. - fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let sig = fn_ptr.internal(&mut *tables, cx.tcx); - cx.fn_ptr_abi(sig).map(|fn_abi| fn_abi.stable(&mut *tables, cx)) - } - - /// Get the layout of a type. - fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let internal_ty = ty.internal(&mut *tables, cx.tcx); - cx.ty_layout(internal_ty).map(|layout| layout.stable(&mut *tables, cx)) - } - - /// Get the layout shape. - fn layout_shape(&self, id: Layout) -> LayoutShape { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - id.internal(&mut *tables, cx.tcx).0.stable(&mut *tables, cx) - } - - /// Get a debug string representation of a place. - fn place_pretty(&self, place: &Place) -> String { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - - format!("{:?}", place.internal(&mut *tables, cx.tcx)) - } - - /// Get the resulting type of binary operation. - fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let rhs_internal = rhs.internal(&mut *tables, cx.tcx); - let lhs_internal = lhs.internal(&mut *tables, cx.tcx); - let bin_op_internal = bin_op.internal(&mut *tables, cx.tcx); - cx.binop_ty(bin_op_internal, rhs_internal, lhs_internal).stable(&mut *tables, cx) - } - - /// Get the resulting type of unary operation. - fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let un_op = un_op.internal(&mut *tables, cx.tcx); - let arg = arg.internal(&mut *tables, cx.tcx); - cx.unop_ty(un_op, arg).stable(&mut *tables, cx) - } - - /// Get all associated items of a definition. - fn associated_items(&self, def_id: DefId) -> AssocItems { - let mut tables = self.tables.borrow_mut(); - let cx = &*self.cx.borrow(); - let did = tables[def_id]; - cx.associated_items(did).iter().map(|assoc| assoc.stable(&mut *tables, cx)).collect() - } -} - -// A thread local variable that stores a pointer to [`SmirInterface`]. -scoped_tls::scoped_thread_local!(static TLV: Cell<*const ()>); - -pub(crate) fn run<F, T>(interface: &dyn SmirInterface, f: F) -> Result<T, Error> -where - F: FnOnce() -> T, -{ - if TLV.is_set() { - Err(Error::from("StableMIR already running")) - } else { - let ptr: *const () = (&raw const interface) as _; - TLV.set(&Cell::new(ptr), || Ok(f())) - } -} - -/// Execute the given function with access the [`SmirInterface`]. -/// -/// I.e., This function will load the current interface and calls a function with it. -/// Do not nest these, as that will ICE. -pub(crate) fn with<R>(f: impl FnOnce(&dyn SmirInterface) -> R) -> R { - assert!(TLV.is_set()); - TLV.with(|tlv| { - let ptr = tlv.get(); - assert!(!ptr.is_null()); - f(unsafe { *(ptr as *const &dyn SmirInterface) }) - }) -} - -fn smir_crate<'tcx>( - cx: &SmirCtxt<'tcx, BridgeTys>, - crate_num: rustc_span::def_id::CrateNum, -) -> Crate { - let name = cx.crate_name(crate_num); - let is_local = cx.crate_is_local(crate_num); - let id = cx.crate_num_id(crate_num); - debug!(?name, ?crate_num, "smir_crate"); - Crate { id, name, is_local } -} diff --git a/compiler/rustc_smir/src/stable_mir/crate_def.rs b/compiler/rustc_smir/src/stable_mir/crate_def.rs deleted file mode 100644 index 64f7ef9b314..00000000000 --- a/compiler/rustc_smir/src/stable_mir/crate_def.rs +++ /dev/null @@ -1,175 +0,0 @@ -//! Module that define a common trait for things that represent a crate definition, -//! such as, a function, a trait, an enum, and any other definitions. - -use serde::Serialize; -use stable_mir::ty::{GenericArgs, Span, Ty}; -use stable_mir::{AssocItems, Crate, Symbol, with}; - -use crate::stable_mir; - -/// A unique identification number for each item accessible for the current compilation unit. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)] -pub struct DefId(pub(crate) usize); - -impl DefId { - /// Return fully qualified name of this definition - pub fn name(&self) -> Symbol { - with(|cx| cx.def_name(*self, false)) - } - - /// Return a trimmed name of this definition. - /// - /// This can be used to print more user friendly diagnostic messages. - /// - /// If a symbol name can only be imported from one place for a type, and as - /// long as it was not glob-imported anywhere in the current crate, we trim its - /// path and print only the name. - /// - /// For example, this function may shorten `std::vec::Vec` to just `Vec`, - /// as long as there is no other `Vec` importable anywhere. - pub fn trimmed_name(&self) -> Symbol { - with(|cx| cx.def_name(*self, true)) - } -} - -/// A trait for retrieving information about a particular definition. -/// -/// Implementors must provide the implementation of `def_id` which will be used to retrieve -/// information about a crate's definition. -pub trait CrateDef { - /// Retrieve the unique identifier for the current definition. - fn def_id(&self) -> DefId; - - /// Return the fully qualified name of the current definition. - /// - /// See [`DefId::name`] for more details - fn name(&self) -> Symbol { - self.def_id().name() - } - - /// Return a trimmed name of this definition. - /// - /// See [`DefId::trimmed_name`] for more details - fn trimmed_name(&self) -> Symbol { - self.def_id().trimmed_name() - } - - /// Return information about the crate where this definition is declared. - /// - /// This will return the crate number and its name. - fn krate(&self) -> Crate { - let def_id = self.def_id(); - with(|cx| cx.krate(def_id)) - } - - /// Return the span of this definition. - fn span(&self) -> Span { - let def_id = self.def_id(); - with(|cx| cx.span_of_an_item(def_id)) - } - - /// Return registered tool attributes with the given attribute name. - /// - /// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool - /// attributes will simply return an empty list. - /// - /// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`. - /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`. - fn tool_attrs(&self, attr: &[Symbol]) -> Vec<Attribute> { - let def_id = self.def_id(); - with(|cx| cx.tool_attrs(def_id, attr)) - } - - /// Return all tool attributes of this definition. - fn all_tool_attrs(&self) -> Vec<Attribute> { - let def_id = self.def_id(); - with(|cx| cx.all_tool_attrs(def_id)) - } -} - -/// A trait that can be used to retrieve a definition's type. -/// -/// Note that not every CrateDef has a type `Ty`. They should not implement this trait. -pub trait CrateDefType: CrateDef { - /// Returns the type of this crate item. - fn ty(&self) -> Ty { - with(|cx| cx.def_ty(self.def_id())) - } - - /// Retrieve the type of this definition by instantiating and normalizing it with `args`. - /// - /// This will panic if instantiation fails. - fn ty_with_args(&self, args: &GenericArgs) -> Ty { - with(|cx| cx.def_ty_with_args(self.def_id(), args)) - } -} - -/// A trait for retrieving all items from a definition within a crate. -pub trait CrateDefItems: CrateDef { - /// Retrieve all associated items from a definition. - fn associated_items(&self) -> AssocItems { - with(|cx| cx.associated_items(self.def_id())) - } -} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct Attribute { - value: String, - span: Span, -} - -impl Attribute { - pub fn new(value: String, span: Span) -> Attribute { - Attribute { value, span } - } - - /// Get the span of this attribute. - pub fn span(&self) -> Span { - self.span - } - - /// Get the string representation of this attribute. - pub fn as_str(&self) -> &str { - &self.value - } -} - -macro_rules! crate_def { - ( $(#[$attr:meta])* - $vis:vis $name:ident $(;)? - ) => { - $(#[$attr])* - #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] - $vis struct $name(pub DefId); - - impl CrateDef for $name { - fn def_id(&self) -> DefId { - self.0 - } - } - }; -} - -macro_rules! crate_def_with_ty { - ( $(#[$attr:meta])* - $vis:vis $name:ident $(;)? - ) => { - $(#[$attr])* - #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] - $vis struct $name(pub DefId); - - impl CrateDef for $name { - fn def_id(&self) -> DefId { - self.0 - } - } - - impl CrateDefType for $name {} - }; -} - -macro_rules! impl_crate_def_items { - ( $name:ident $(;)? ) => { - impl CrateDefItems for $name {} - }; -} diff --git a/compiler/rustc_smir/src/stable_mir/error.rs b/compiler/rustc_smir/src/stable_mir/error.rs deleted file mode 100644 index 3f9d67954b9..00000000000 --- a/compiler/rustc_smir/src/stable_mir/error.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! When things go wrong, we need some error handling. -//! There are a few different types of errors in StableMIR: -//! -//! - [CompilerError]: This represents errors that can be raised when invoking the compiler. -//! - [Error]: Generic error that represents the reason why a request that could not be fulfilled. - -use std::fmt::{Debug, Display, Formatter}; -use std::{fmt, io}; - -use rustc_smir::bridge::SmirError; - -use crate::rustc_smir; - -macro_rules! error { - ($fmt: literal $(,)?) => { Error(format!($fmt)) }; - ($fmt: literal, $($arg:tt)*) => { Error(format!($fmt, $($arg)*)) }; -} - -pub(crate) use error; - -/// An error type used to represent an error that has already been reported by the compiler. -#[derive(Clone, Copy, PartialEq, Eq)] -pub enum CompilerError<T> { - /// Compilation failed, either due to normal errors or ICE. - Failed, - /// Compilation was interrupted. - Interrupted(T), - /// Compilation skipped. This happens when users invoke rustc to retrieve information such as - /// --version. - Skipped, -} - -/// A generic error to represent an API request that cannot be fulfilled. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct Error(pub(crate) String); - -impl SmirError for Error { - fn new(msg: String) -> Self { - Self(msg) - } - - fn from_internal<T: Debug>(err: T) -> Self { - Self(format!("{err:?}")) - } -} - -impl From<&str> for Error { - fn from(value: &str) -> Self { - Self(value.into()) - } -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - Display::fmt(&self.0, f) - } -} - -impl<T> Display for CompilerError<T> -where - T: Display, -{ - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - CompilerError::Failed => write!(f, "Compilation Failed"), - CompilerError::Interrupted(reason) => write!(f, "Compilation Interrupted: {reason}"), - CompilerError::Skipped => write!(f, "Compilation Skipped"), - } - } -} - -impl<T> Debug for CompilerError<T> -where - T: Debug, -{ - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - CompilerError::Failed => write!(f, "Compilation Failed"), - CompilerError::Interrupted(reason) => write!(f, "Compilation Interrupted: {reason:?}"), - CompilerError::Skipped => write!(f, "Compilation Skipped"), - } - } -} - -impl std::error::Error for Error {} - -impl<T> std::error::Error for CompilerError<T> where T: Display + Debug {} - -impl From<io::Error> for Error { - fn from(value: io::Error) -> Self { - Error(value.to_string()) - } -} diff --git a/compiler/rustc_smir/src/stable_mir/mir.rs b/compiler/rustc_smir/src/stable_mir/mir.rs deleted file mode 100644 index 413b5152bb3..00000000000 --- a/compiler/rustc_smir/src/stable_mir/mir.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod alloc; -mod body; -pub mod mono; -pub mod pretty; -pub mod visit; - -pub use body::*; -pub use visit::{MirVisitor, MutMirVisitor}; diff --git a/compiler/rustc_smir/src/stable_mir/mir/alloc.rs b/compiler/rustc_smir/src/stable_mir/mir/alloc.rs deleted file mode 100644 index 26f30898a9c..00000000000 --- a/compiler/rustc_smir/src/stable_mir/mir/alloc.rs +++ /dev/null @@ -1,88 +0,0 @@ -//! This module provides methods to retrieve allocation information, such as static variables. - -use std::io::Read; - -use serde::Serialize; -use stable_mir::mir::mono::{Instance, StaticDef}; -use stable_mir::target::{Endian, MachineInfo}; -use stable_mir::ty::{Allocation, Binder, ExistentialTraitRef, Ty}; -use stable_mir::{Error, IndexedVal, with}; - -use crate::stable_mir; - -/// An allocation in the SMIR global memory can be either a function pointer, -/// a static, or a "real" allocation with some data in it. -#[derive(Debug, Clone, Eq, PartialEq, Serialize)] -pub enum GlobalAlloc { - /// The alloc ID is used as a function pointer. - Function(Instance), - /// This alloc ID points to a symbolic (not-reified) vtable. - /// The `None` trait ref is used to represent auto traits. - VTable(Ty, Option<Binder<ExistentialTraitRef>>), - /// The alloc ID points to a "lazy" static variable that did not get computed (yet). - /// This is also used to break the cycle in recursive statics. - Static(StaticDef), - /// The alloc ID points to memory. - Memory(Allocation), -} - -impl From<AllocId> for GlobalAlloc { - fn from(value: AllocId) -> Self { - with(|cx| cx.global_alloc(value)) - } -} - -impl GlobalAlloc { - /// Retrieve the allocation id for a global allocation if it exists. - /// - /// For `[GlobalAlloc::VTable]`, this will return the allocation for the VTable of the given - /// type for the optional trait if the type implements the trait. - /// - /// This method will always return `None` for allocations other than `[GlobalAlloc::VTable]`. - pub fn vtable_allocation(&self) -> Option<AllocId> { - with(|cx| cx.vtable_allocation(self)) - } -} - -/// A unique identification number for each provenance -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] -pub struct AllocId(usize); - -impl IndexedVal for AllocId { - fn to_val(index: usize) -> Self { - AllocId(index) - } - fn to_index(&self) -> usize { - self.0 - } -} - -/// Utility function used to read an allocation data into a unassigned integer. -pub(crate) fn read_target_uint(mut bytes: &[u8]) -> Result<u128, Error> { - let mut buf = [0u8; size_of::<u128>()]; - match MachineInfo::target_endianness() { - Endian::Little => { - bytes.read_exact(&mut buf[..bytes.len()])?; - Ok(u128::from_le_bytes(buf)) - } - Endian::Big => { - bytes.read_exact(&mut buf[16 - bytes.len()..])?; - Ok(u128::from_be_bytes(buf)) - } - } -} - -/// Utility function used to read an allocation data into an assigned integer. -pub(crate) fn read_target_int(mut bytes: &[u8]) -> Result<i128, Error> { - let mut buf = [0u8; size_of::<i128>()]; - match MachineInfo::target_endianness() { - Endian::Little => { - bytes.read_exact(&mut buf[..bytes.len()])?; - Ok(i128::from_le_bytes(buf)) - } - Endian::Big => { - bytes.read_exact(&mut buf[16 - bytes.len()..])?; - Ok(i128::from_be_bytes(buf)) - } - } -} diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs deleted file mode 100644 index 90d4a06b177..00000000000 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ /dev/null @@ -1,1128 +0,0 @@ -use std::io; - -use serde::Serialize; -use stable_mir::compiler_interface::with; -use stable_mir::mir::pretty::function_body; -use stable_mir::ty::{ - AdtDef, ClosureDef, CoroutineClosureDef, CoroutineDef, GenericArgs, MirConst, Movability, - Region, RigidTy, Ty, TyConst, TyKind, VariantIdx, -}; -use stable_mir::{Error, Opaque, Span, Symbol}; - -use crate::stable_mir; - -/// The SMIR representation of a single function. -#[derive(Clone, Debug, Serialize)] -pub struct Body { - pub blocks: Vec<BasicBlock>, - - /// Declarations of locals within the function. - /// - /// The first local is the return value pointer, followed by `arg_count` - /// locals for the function arguments, followed by any user-declared - /// variables and temporaries. - pub(super) locals: LocalDecls, - - /// The number of arguments this function takes. - pub(super) arg_count: usize, - - /// Debug information pertaining to user variables, including captures. - pub var_debug_info: Vec<VarDebugInfo>, - - /// Mark an argument (which must be a tuple) as getting passed as its individual components. - /// - /// This is used for the "rust-call" ABI such as closures. - pub(super) spread_arg: Option<Local>, - - /// The span that covers the entire function body. - pub span: Span, -} - -pub type BasicBlockIdx = usize; - -impl Body { - /// Constructs a `Body`. - /// - /// A constructor is required to build a `Body` from outside the crate - /// because the `arg_count` and `locals` fields are private. - pub fn new( - blocks: Vec<BasicBlock>, - locals: LocalDecls, - arg_count: usize, - var_debug_info: Vec<VarDebugInfo>, - spread_arg: Option<Local>, - span: Span, - ) -> Self { - // If locals doesn't contain enough entries, it can lead to panics in - // `ret_local`, `arg_locals`, and `inner_locals`. - assert!( - locals.len() > arg_count, - "A Body must contain at least a local for the return value and each of the function's arguments" - ); - Self { blocks, locals, arg_count, var_debug_info, spread_arg, span } - } - - /// Return local that holds this function's return value. - pub fn ret_local(&self) -> &LocalDecl { - &self.locals[RETURN_LOCAL] - } - - /// Locals in `self` that correspond to this function's arguments. - pub fn arg_locals(&self) -> &[LocalDecl] { - &self.locals[1..][..self.arg_count] - } - - /// Inner locals for this function. These are the locals that are - /// neither the return local nor the argument locals. - pub fn inner_locals(&self) -> &[LocalDecl] { - &self.locals[self.arg_count + 1..] - } - - /// Returns a mutable reference to the local that holds this function's return value. - pub(crate) fn ret_local_mut(&mut self) -> &mut LocalDecl { - &mut self.locals[RETURN_LOCAL] - } - - /// Returns a mutable slice of locals corresponding to this function's arguments. - pub(crate) fn arg_locals_mut(&mut self) -> &mut [LocalDecl] { - &mut self.locals[1..][..self.arg_count] - } - - /// Returns a mutable slice of inner locals for this function. - /// Inner locals are those that are neither the return local nor the argument locals. - pub(crate) fn inner_locals_mut(&mut self) -> &mut [LocalDecl] { - &mut self.locals[self.arg_count + 1..] - } - - /// Convenience function to get all the locals in this function. - /// - /// Locals are typically accessed via the more specific methods `ret_local`, - /// `arg_locals`, and `inner_locals`. - pub fn locals(&self) -> &[LocalDecl] { - &self.locals - } - - /// Get the local declaration for this local. - pub fn local_decl(&self, local: Local) -> Option<&LocalDecl> { - self.locals.get(local) - } - - /// Get an iterator for all local declarations. - pub fn local_decls(&self) -> impl Iterator<Item = (Local, &LocalDecl)> { - self.locals.iter().enumerate() - } - - /// Emit the body using the provided name for the signature. - pub fn dump<W: io::Write>(&self, w: &mut W, fn_name: &str) -> io::Result<()> { - function_body(w, self, fn_name) - } - - pub fn spread_arg(&self) -> Option<Local> { - self.spread_arg - } -} - -type LocalDecls = Vec<LocalDecl>; - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct LocalDecl { - pub ty: Ty, - pub span: Span, - pub mutability: Mutability, -} - -#[derive(Clone, PartialEq, Eq, Debug, Serialize)] -pub struct BasicBlock { - pub statements: Vec<Statement>, - pub terminator: Terminator, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct Terminator { - pub kind: TerminatorKind, - pub span: Span, -} - -impl Terminator { - pub fn successors(&self) -> Successors { - self.kind.successors() - } -} - -pub type Successors = Vec<BasicBlockIdx>; - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum TerminatorKind { - Goto { - target: BasicBlockIdx, - }, - SwitchInt { - discr: Operand, - targets: SwitchTargets, - }, - Resume, - Abort, - Return, - Unreachable, - Drop { - place: Place, - target: BasicBlockIdx, - unwind: UnwindAction, - }, - Call { - func: Operand, - args: Vec<Operand>, - destination: Place, - target: Option<BasicBlockIdx>, - unwind: UnwindAction, - }, - Assert { - cond: Operand, - expected: bool, - msg: AssertMessage, - target: BasicBlockIdx, - unwind: UnwindAction, - }, - InlineAsm { - template: String, - operands: Vec<InlineAsmOperand>, - options: String, - line_spans: String, - destination: Option<BasicBlockIdx>, - unwind: UnwindAction, - }, -} - -impl TerminatorKind { - pub fn successors(&self) -> Successors { - use self::TerminatorKind::*; - match *self { - Call { target: Some(t), unwind: UnwindAction::Cleanup(u), .. } - | Drop { target: t, unwind: UnwindAction::Cleanup(u), .. } - | Assert { target: t, unwind: UnwindAction::Cleanup(u), .. } - | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(u), .. } => { - vec![t, u] - } - Goto { target: t } - | Call { target: None, unwind: UnwindAction::Cleanup(t), .. } - | Call { target: Some(t), unwind: _, .. } - | Drop { target: t, unwind: _, .. } - | Assert { target: t, unwind: _, .. } - | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. } - | InlineAsm { destination: Some(t), unwind: _, .. } => { - vec![t] - } - - Return - | Resume - | Abort - | Unreachable - | Call { target: None, unwind: _, .. } - | InlineAsm { destination: None, unwind: _, .. } => { - vec![] - } - SwitchInt { ref targets, .. } => targets.all_targets(), - } - } - - pub fn unwind(&self) -> Option<&UnwindAction> { - match *self { - TerminatorKind::Goto { .. } - | TerminatorKind::Return - | TerminatorKind::Unreachable - | TerminatorKind::Resume - | TerminatorKind::Abort - | TerminatorKind::SwitchInt { .. } => None, - TerminatorKind::Call { ref unwind, .. } - | TerminatorKind::Assert { ref unwind, .. } - | TerminatorKind::Drop { ref unwind, .. } - | TerminatorKind::InlineAsm { ref unwind, .. } => Some(unwind), - } - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct InlineAsmOperand { - pub in_value: Option<Operand>, - pub out_place: Option<Place>, - // This field has a raw debug representation of MIR's InlineAsmOperand. - // For now we care about place/operand + the rest in a debug format. - pub raw_rpr: String, -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum UnwindAction { - Continue, - Unreachable, - Terminate, - Cleanup(BasicBlockIdx), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum AssertMessage { - BoundsCheck { len: Operand, index: Operand }, - Overflow(BinOp, Operand, Operand), - OverflowNeg(Operand), - DivisionByZero(Operand), - RemainderByZero(Operand), - ResumedAfterReturn(CoroutineKind), - ResumedAfterPanic(CoroutineKind), - ResumedAfterDrop(CoroutineKind), - MisalignedPointerDereference { required: Operand, found: Operand }, - NullPointerDereference, - InvalidEnumConstruction(Operand), -} - -impl AssertMessage { - pub fn description(&self) -> Result<&'static str, Error> { - match self { - AssertMessage::Overflow(BinOp::Add, _, _) => Ok("attempt to add with overflow"), - AssertMessage::Overflow(BinOp::Sub, _, _) => Ok("attempt to subtract with overflow"), - AssertMessage::Overflow(BinOp::Mul, _, _) => Ok("attempt to multiply with overflow"), - AssertMessage::Overflow(BinOp::Div, _, _) => Ok("attempt to divide with overflow"), - AssertMessage::Overflow(BinOp::Rem, _, _) => { - Ok("attempt to calculate the remainder with overflow") - } - AssertMessage::OverflowNeg(_) => Ok("attempt to negate with overflow"), - AssertMessage::Overflow(BinOp::Shr, _, _) => Ok("attempt to shift right with overflow"), - AssertMessage::Overflow(BinOp::Shl, _, _) => Ok("attempt to shift left with overflow"), - AssertMessage::Overflow(op, _, _) => Err(error!("`{:?}` cannot overflow", op)), - AssertMessage::DivisionByZero(_) => Ok("attempt to divide by zero"), - AssertMessage::RemainderByZero(_) => { - Ok("attempt to calculate the remainder with a divisor of zero") - } - AssertMessage::ResumedAfterReturn(CoroutineKind::Coroutine(_)) => { - Ok("coroutine resumed after completion") - } - AssertMessage::ResumedAfterReturn(CoroutineKind::Desugared( - CoroutineDesugaring::Async, - _, - )) => Ok("`async fn` resumed after completion"), - AssertMessage::ResumedAfterReturn(CoroutineKind::Desugared( - CoroutineDesugaring::Gen, - _, - )) => Ok("`async gen fn` resumed after completion"), - AssertMessage::ResumedAfterReturn(CoroutineKind::Desugared( - CoroutineDesugaring::AsyncGen, - _, - )) => Ok("`gen fn` should just keep returning `AssertMessage::None` after completion"), - AssertMessage::ResumedAfterPanic(CoroutineKind::Coroutine(_)) => { - Ok("coroutine resumed after panicking") - } - AssertMessage::ResumedAfterPanic(CoroutineKind::Desugared( - CoroutineDesugaring::Async, - _, - )) => Ok("`async fn` resumed after panicking"), - AssertMessage::ResumedAfterPanic(CoroutineKind::Desugared( - CoroutineDesugaring::Gen, - _, - )) => Ok("`async gen fn` resumed after panicking"), - AssertMessage::ResumedAfterPanic(CoroutineKind::Desugared( - CoroutineDesugaring::AsyncGen, - _, - )) => Ok("`gen fn` should just keep returning `AssertMessage::None` after panicking"), - - AssertMessage::ResumedAfterDrop(CoroutineKind::Coroutine(_)) => { - Ok("coroutine resumed after async drop") - } - AssertMessage::ResumedAfterDrop(CoroutineKind::Desugared( - CoroutineDesugaring::Async, - _, - )) => Ok("`async fn` resumed after async drop"), - AssertMessage::ResumedAfterDrop(CoroutineKind::Desugared( - CoroutineDesugaring::Gen, - _, - )) => Ok("`async gen fn` resumed after async drop"), - AssertMessage::ResumedAfterDrop(CoroutineKind::Desugared( - CoroutineDesugaring::AsyncGen, - _, - )) => Ok("`gen fn` should just keep returning `AssertMessage::None` after async drop"), - - AssertMessage::BoundsCheck { .. } => Ok("index out of bounds"), - AssertMessage::MisalignedPointerDereference { .. } => { - Ok("misaligned pointer dereference") - } - AssertMessage::NullPointerDereference => Ok("null pointer dereference occurred"), - AssertMessage::InvalidEnumConstruction(_) => { - Ok("trying to construct an enum from an invalid value") - } - } - } -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum BinOp { - Add, - AddUnchecked, - Sub, - SubUnchecked, - Mul, - MulUnchecked, - Div, - Rem, - BitXor, - BitAnd, - BitOr, - Shl, - ShlUnchecked, - Shr, - ShrUnchecked, - Eq, - Lt, - Le, - Ne, - Ge, - Gt, - Cmp, - Offset, -} - -impl BinOp { - /// Return the type of this operation for the given input Ty. - /// This function does not perform type checking, and it currently doesn't handle SIMD. - pub fn ty(&self, lhs_ty: Ty, rhs_ty: Ty) -> Ty { - with(|ctx| ctx.binop_ty(*self, lhs_ty, rhs_ty)) - } -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum UnOp { - Not, - Neg, - PtrMetadata, -} - -impl UnOp { - /// Return the type of this operation for the given input Ty. - /// This function does not perform type checking, and it currently doesn't handle SIMD. - pub fn ty(&self, arg_ty: Ty) -> Ty { - with(|ctx| ctx.unop_ty(*self, arg_ty)) - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum CoroutineKind { - Desugared(CoroutineDesugaring, CoroutineSource), - Coroutine(Movability), -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum CoroutineSource { - Block, - Closure, - Fn, -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum CoroutineDesugaring { - Async, - - Gen, - - AsyncGen, -} - -pub(crate) type LocalDefId = Opaque; -/// The rustc coverage data structures are heavily tied to internal details of the -/// coverage implementation that are likely to change, and are unlikely to be -/// useful to third-party tools for the foreseeable future. -pub(crate) type Coverage = Opaque; - -/// The FakeReadCause describes the type of pattern why a FakeRead statement exists. -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum FakeReadCause { - ForMatchGuard, - ForMatchedPlace(LocalDefId), - ForGuardBinding, - ForLet(LocalDefId), - ForIndex, -} - -/// Describes what kind of retag is to be performed -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)] -pub enum RetagKind { - FnEntry, - TwoPhase, - Raw, - Default, -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)] -pub enum Variance { - Covariant, - Invariant, - Contravariant, - Bivariant, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct CopyNonOverlapping { - pub src: Operand, - pub dst: Operand, - pub count: Operand, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum NonDivergingIntrinsic { - Assume(Operand), - CopyNonOverlapping(CopyNonOverlapping), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct Statement { - pub kind: StatementKind, - pub span: Span, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum StatementKind { - Assign(Place, Rvalue), - FakeRead(FakeReadCause, Place), - SetDiscriminant { place: Place, variant_index: VariantIdx }, - Deinit(Place), - StorageLive(Local), - StorageDead(Local), - Retag(RetagKind, Place), - PlaceMention(Place), - AscribeUserType { place: Place, projections: UserTypeProjection, variance: Variance }, - Coverage(Coverage), - Intrinsic(NonDivergingIntrinsic), - ConstEvalCounter, - Nop, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum Rvalue { - /// Creates a pointer with the indicated mutability to the place. - /// - /// This is generated by pointer casts like `&v as *const _` or raw address of expressions like - /// `&raw v` or `addr_of!(v)`. - AddressOf(RawPtrKind, Place), - - /// Creates an aggregate value, like a tuple or struct. - /// - /// This is needed because dataflow analysis needs to distinguish - /// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo` - /// has a destructor. - /// - /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Coroutine`. After - /// coroutine lowering, `Coroutine` aggregate kinds are disallowed too. - Aggregate(AggregateKind, Vec<Operand>), - - /// * `Offset` has the same semantics as `<*const T>::offset`, except that the second - /// parameter may be a `usize` as well. - /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats, - /// raw pointers, or function pointers and return a `bool`. The types of the operands must be - /// matching, up to the usual caveat of the lifetimes in function pointers. - /// * Left and right shift operations accept signed or unsigned integers not necessarily of the - /// same type and return a value of the same type as their LHS. Like in Rust, the RHS is - /// truncated as needed. - /// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching - /// types and return a value of that type. - /// * The remaining operations accept signed integers, unsigned integers, or floats with - /// matching types and return a value of that type. - BinaryOp(BinOp, Operand, Operand), - - /// Performs essentially all of the casts that can be performed via `as`. - /// - /// This allows for casts from/to a variety of types. - Cast(CastKind, Operand, Ty), - - /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition. - /// - /// For addition, subtraction, and multiplication on integers the error condition is set when - /// the infinite precision result would not be equal to the actual result. - CheckedBinaryOp(BinOp, Operand, Operand), - - /// A CopyForDeref is equivalent to a read from a place. - /// When such a read happens, it is guaranteed that the only use of the returned value is a - /// deref operation, immediately followed by one or more projections. - CopyForDeref(Place), - - /// Computes the discriminant of the place, returning it as an integer. - /// Returns zero for types without discriminant. - /// - /// The validity requirements for the underlying value are undecided for this rvalue, see - /// [#91095]. Note too that the value of the discriminant is not the same thing as the - /// variant index; - /// - /// [#91095]: https://github.com/rust-lang/rust/issues/91095 - Discriminant(Place), - - /// Yields the length of the place, as a `usize`. - /// - /// If the type of the place is an array, this is the array length. For slices (`[T]`, not - /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is - /// ill-formed for places of other types. - Len(Place), - - /// Creates a reference to the place. - Ref(Region, BorrowKind, Place), - - /// Creates an array where each element is the value of the operand. - /// - /// This is the cause of a bug in the case where the repetition count is zero because the value - /// is not dropped, see [#74836]. - /// - /// Corresponds to source code like `[x; 32]`. - /// - /// [#74836]: https://github.com/rust-lang/rust/issues/74836 - Repeat(Operand, TyConst), - - /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`. - /// - /// This is different from a normal transmute because dataflow analysis will treat the box as - /// initialized but its content as uninitialized. Like other pointer casts, this in general - /// affects alias analysis. - ShallowInitBox(Operand, Ty), - - /// Creates a pointer/reference to the given thread local. - /// - /// The yielded type is a `*mut T` if the static is mutable, otherwise if the static is extern a - /// `*const T`, and if neither of those apply a `&T`. - /// - /// **Note:** This is a runtime operation that actually executes code and is in this sense more - /// like a function call. Also, eliminating dead stores of this rvalue causes `fn main() {}` to - /// SIGILL for some reason that I (JakobDegen) never got a chance to look into. - /// - /// **Needs clarification**: Are there weird additional semantics here related to the runtime - /// nature of this operation? - ThreadLocalRef(stable_mir::CrateItem), - - /// Computes a value as described by the operation. - NullaryOp(NullOp, Ty), - - /// Exactly like `BinaryOp`, but less operands. - /// - /// Also does two's-complement arithmetic. Negation requires a signed integer or a float; - /// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds - /// return a value with the same type as their operand. - UnaryOp(UnOp, Operand), - - /// Yields the operand unchanged - Use(Operand), -} - -impl Rvalue { - pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> { - match self { - Rvalue::Use(operand) => operand.ty(locals), - Rvalue::Repeat(operand, count) => { - Ok(Ty::new_array_with_const_len(operand.ty(locals)?, count.clone())) - } - Rvalue::ThreadLocalRef(did) => Ok(did.ty()), - Rvalue::Ref(reg, bk, place) => { - let place_ty = place.ty(locals)?; - Ok(Ty::new_ref(reg.clone(), place_ty, bk.to_mutable_lossy())) - } - Rvalue::AddressOf(mutability, place) => { - let place_ty = place.ty(locals)?; - Ok(Ty::new_ptr(place_ty, mutability.to_mutable_lossy())) - } - Rvalue::Len(..) => Ok(Ty::usize_ty()), - Rvalue::Cast(.., ty) => Ok(*ty), - Rvalue::BinaryOp(op, lhs, rhs) => { - let lhs_ty = lhs.ty(locals)?; - let rhs_ty = rhs.ty(locals)?; - Ok(op.ty(lhs_ty, rhs_ty)) - } - Rvalue::CheckedBinaryOp(op, lhs, rhs) => { - let lhs_ty = lhs.ty(locals)?; - let rhs_ty = rhs.ty(locals)?; - let ty = op.ty(lhs_ty, rhs_ty); - Ok(Ty::new_tuple(&[ty, Ty::bool_ty()])) - } - Rvalue::UnaryOp(op, operand) => { - let arg_ty = operand.ty(locals)?; - Ok(op.ty(arg_ty)) - } - Rvalue::Discriminant(place) => { - let place_ty = place.ty(locals)?; - place_ty - .kind() - .discriminant_ty() - .ok_or_else(|| error!("Expected a `RigidTy` but found: {place_ty:?}")) - } - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { - Ok(Ty::usize_ty()) - } - Rvalue::NullaryOp(NullOp::ContractChecks, _) - | Rvalue::NullaryOp(NullOp::UbChecks, _) => Ok(Ty::bool_ty()), - Rvalue::Aggregate(ak, ops) => match *ak { - AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64), - AggregateKind::Tuple => Ok(Ty::new_tuple( - &ops.iter().map(|op| op.ty(locals)).collect::<Result<Vec<_>, _>>()?, - )), - AggregateKind::Adt(def, _, ref args, _, _) => Ok(def.ty_with_args(args)), - AggregateKind::Closure(def, ref args) => Ok(Ty::new_closure(def, args.clone())), - AggregateKind::Coroutine(def, ref args, mov) => { - Ok(Ty::new_coroutine(def, args.clone(), mov)) - } - AggregateKind::CoroutineClosure(def, ref args) => { - Ok(Ty::new_coroutine_closure(def, args.clone())) - } - AggregateKind::RawPtr(ty, mutability) => Ok(Ty::new_ptr(ty, mutability)), - }, - Rvalue::ShallowInitBox(_, ty) => Ok(Ty::new_box(*ty)), - Rvalue::CopyForDeref(place) => place.ty(locals), - } - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum AggregateKind { - Array(Ty), - Tuple, - Adt(AdtDef, VariantIdx, GenericArgs, Option<UserTypeAnnotationIndex>, Option<FieldIdx>), - Closure(ClosureDef, GenericArgs), - // FIXME(stable_mir): Movability here is redundant - Coroutine(CoroutineDef, GenericArgs, Movability), - CoroutineClosure(CoroutineClosureDef, GenericArgs), - RawPtr(Ty, Mutability), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum Operand { - Copy(Place), - Move(Place), - Constant(ConstOperand), -} - -#[derive(Clone, Eq, PartialEq, Serialize)] -pub struct Place { - pub local: Local, - /// projection out of a place (access a field, deref a pointer, etc) - pub projection: Vec<ProjectionElem>, -} - -impl From<Local> for Place { - fn from(local: Local) -> Self { - Place { local, projection: vec![] } - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct ConstOperand { - pub span: Span, - pub user_ty: Option<UserTypeAnnotationIndex>, - pub const_: MirConst, -} - -/// Debug information pertaining to a user variable. -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct VarDebugInfo { - /// The variable name. - pub name: Symbol, - - /// Source info of the user variable, including the scope - /// within which the variable is visible (to debuginfo). - pub source_info: SourceInfo, - - /// The user variable's data is split across several fragments, - /// each described by a `VarDebugInfoFragment`. - pub composite: Option<VarDebugInfoFragment>, - - /// Where the data for this user variable is to be found. - pub value: VarDebugInfoContents, - - /// When present, indicates what argument number this variable is in the function that it - /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the - /// argument number in the original function before it was inlined. - pub argument_index: Option<u16>, -} - -impl VarDebugInfo { - /// Return a local variable if this info is related to one. - pub fn local(&self) -> Option<Local> { - match &self.value { - VarDebugInfoContents::Place(place) if place.projection.is_empty() => Some(place.local), - VarDebugInfoContents::Place(_) | VarDebugInfoContents::Const(_) => None, - } - } - - /// Return a constant if this info is related to one. - pub fn constant(&self) -> Option<&ConstOperand> { - match &self.value { - VarDebugInfoContents::Place(_) => None, - VarDebugInfoContents::Const(const_op) => Some(const_op), - } - } -} - -pub type SourceScope = u32; - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct SourceInfo { - pub span: Span, - pub scope: SourceScope, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct VarDebugInfoFragment { - pub ty: Ty, - pub projection: Vec<ProjectionElem>, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum VarDebugInfoContents { - Place(Place), - Const(ConstOperand), -} - -// In MIR ProjectionElem is parameterized on the second Field argument and the Index argument. This -// is so it can be used for both Places (for which the projection elements are of type -// ProjectionElem<Local, Ty>) and user-provided type annotations (for which the projection elements -// are of type ProjectionElem<(), ()>). In SMIR we don't need this generality, so we just use -// ProjectionElem for Places. -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum ProjectionElem { - /// Dereference projections (e.g. `*_1`) project to the address referenced by the base place. - Deref, - - /// A field projection (e.g., `f` in `_1.f`) project to a field in the base place. The field is - /// referenced by source-order index rather than the name of the field. The fields type is also - /// given. - Field(FieldIdx, Ty), - - /// Index into a slice/array. The value of the index is computed at runtime using the `V` - /// argument. - /// - /// Note that this does not also dereference, and so it does not exactly correspond to slice - /// indexing in Rust. In other words, in the below Rust code: - /// - /// ```rust - /// let x = &[1, 2, 3, 4]; - /// let i = 2; - /// x[i]; - /// ``` - /// - /// The `x[i]` is turned into a `Deref` followed by an `Index`, not just an `Index`. The same - /// thing is true of the `ConstantIndex` and `Subslice` projections below. - Index(Local), - - /// Index into a slice/array given by offsets. - /// - /// These indices are generated by slice patterns. Easiest to explain by example: - /// - /// ```ignore (illustrative) - /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false }, - /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false }, - /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true }, - /// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true }, - /// ``` - ConstantIndex { - /// index or -index (in Python terms), depending on from_end - offset: u64, - /// The thing being indexed must be at least this long -- otherwise, the - /// projection is UB. - /// - /// For arrays this is always the exact length. - min_length: u64, - /// Counting backwards from end? This is always false when indexing an - /// array. - from_end: bool, - }, - - /// Projects a slice from the base place. - /// - /// These indices are generated by slice patterns. If `from_end` is true, this represents - /// `slice[from..slice.len() - to]`. Otherwise it represents `array[from..to]`. - Subslice { - from: u64, - to: u64, - /// Whether `to` counts from the start or end of the array/slice. - from_end: bool, - }, - - /// "Downcast" to a variant of an enum or a coroutine. - Downcast(VariantIdx), - - /// Like an explicit cast from an opaque type to a concrete type, but without - /// requiring an intermediate variable. - OpaqueCast(Ty), - - /// A `Subtype(T)` projection is applied to any `StatementKind::Assign` where - /// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping - /// explicit during optimizations and codegen. - /// - /// This projection doesn't impact the runtime behavior of the program except for potentially changing - /// some type metadata of the interpreter or codegen backend. - Subtype(Ty), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct UserTypeProjection { - pub base: UserTypeAnnotationIndex, - - pub projection: Opaque, -} - -pub type Local = usize; - -pub const RETURN_LOCAL: Local = 0; - -/// The source-order index of a field in a variant. -/// -/// For example, in the following types, -/// ```ignore(illustrative) -/// enum Demo1 { -/// Variant0 { a: bool, b: i32 }, -/// Variant1 { c: u8, d: u64 }, -/// } -/// struct Demo2 { e: u8, f: u16, g: u8 } -/// ``` -/// `a`'s `FieldIdx` is `0`, -/// `b`'s `FieldIdx` is `1`, -/// `c`'s `FieldIdx` is `0`, and -/// `g`'s `FieldIdx` is `2`. -pub type FieldIdx = usize; - -type UserTypeAnnotationIndex = usize; - -/// The possible branch sites of a [TerminatorKind::SwitchInt]. -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct SwitchTargets { - /// The conditional branches where the first element represents the value that guards this - /// branch, and the second element is the branch target. - branches: Vec<(u128, BasicBlockIdx)>, - /// The `otherwise` branch which will be taken in case none of the conditional branches are - /// satisfied. - otherwise: BasicBlockIdx, -} - -impl SwitchTargets { - /// All possible targets including the `otherwise` target. - pub fn all_targets(&self) -> Successors { - self.branches.iter().map(|(_, target)| *target).chain(Some(self.otherwise)).collect() - } - - /// The `otherwise` branch target. - pub fn otherwise(&self) -> BasicBlockIdx { - self.otherwise - } - - /// The conditional targets which are only taken if the pattern matches the given value. - pub fn branches(&self) -> impl Iterator<Item = (u128, BasicBlockIdx)> { - self.branches.iter().copied() - } - - /// The number of targets including `otherwise`. - pub fn len(&self) -> usize { - self.branches.len() + 1 - } - - /// Create a new SwitchTargets from the given branches and `otherwise` target. - pub fn new(branches: Vec<(u128, BasicBlockIdx)>, otherwise: BasicBlockIdx) -> SwitchTargets { - SwitchTargets { branches, otherwise } - } -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum BorrowKind { - /// Data must be immutable and is aliasable. - Shared, - - /// An immutable, aliasable borrow that is discarded after borrow-checking. Can behave either - /// like a normal shared borrow or like a special shallow borrow (see [`FakeBorrowKind`]). - Fake(FakeBorrowKind), - - /// Data is mutable and not aliasable. - Mut { - /// `true` if this borrow arose from method-call auto-ref - kind: MutBorrowKind, - }, -} - -impl BorrowKind { - pub fn to_mutable_lossy(self) -> Mutability { - match self { - BorrowKind::Mut { .. } => Mutability::Mut, - BorrowKind::Shared => Mutability::Not, - // FIXME: There's no type corresponding to a shallow borrow, so use `&` as an approximation. - BorrowKind::Fake(_) => Mutability::Not, - } - } -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum RawPtrKind { - Mut, - Const, - FakeForPtrMetadata, -} - -impl RawPtrKind { - pub fn to_mutable_lossy(self) -> Mutability { - match self { - RawPtrKind::Mut { .. } => Mutability::Mut, - RawPtrKind::Const => Mutability::Not, - // FIXME: There's no type corresponding to a shallow borrow, so use `&` as an approximation. - RawPtrKind::FakeForPtrMetadata => Mutability::Not, - } - } -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum MutBorrowKind { - Default, - TwoPhaseBorrow, - ClosureCapture, -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum FakeBorrowKind { - /// A shared (deep) borrow. Data must be immutable and is aliasable. - Deep, - /// The immediately borrowed place must be immutable, but projections from - /// it don't need to be. This is used to prevent match guards from replacing - /// the scrutinee. For example, a fake borrow of `a.b` doesn't - /// conflict with a mutable borrow of `a.b.c`. - Shallow, -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub enum Mutability { - Not, - Mut, -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum Safety { - Safe, - Unsafe, -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum PointerCoercion { - /// Go from a fn-item type to a fn-pointer type. - ReifyFnPointer, - - /// Go from a safe fn pointer to an unsafe fn pointer. - UnsafeFnPointer, - - /// Go from a non-capturing closure to a fn pointer or an unsafe fn pointer. - /// It cannot convert a closure that requires unsafe. - ClosureFnPointer(Safety), - - /// Go from a mut raw pointer to a const raw pointer. - MutToConstPointer, - - /// Go from `*const [T; N]` to `*const T` - ArrayToPointer, - - /// Unsize a pointer/reference value, e.g., `&[T; n]` to - /// `&[T]`. Note that the source could be a thin or wide pointer. - /// This will do things like convert thin pointers to wide - /// pointers, or convert structs containing thin pointers to - /// structs containing wide pointers, or convert between wide - /// pointers. - Unsize, -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub enum CastKind { - // FIXME(smir-rename): rename this to PointerExposeProvenance - PointerExposeAddress, - PointerWithExposedProvenance, - PointerCoercion(PointerCoercion), - IntToInt, - FloatToInt, - FloatToFloat, - IntToFloat, - PtrToPtr, - FnPtrToPtr, - Transmute, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum NullOp { - /// Returns the size of a value of that type. - SizeOf, - /// Returns the minimum alignment of a type. - AlignOf, - /// Returns the offset of a field. - OffsetOf(Vec<(VariantIdx, FieldIdx)>), - /// cfg!(ub_checks), but at codegen time - UbChecks, - /// cfg!(contract_checks), but at codegen time - ContractChecks, -} - -impl Operand { - /// Get the type of an operand relative to the local declaration. - /// - /// In order to retrieve the correct type, the `locals` argument must match the list of all - /// locals from the function body where this operand originates from. - /// - /// Errors indicate a malformed operand or incompatible locals list. - pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> { - match self { - Operand::Copy(place) | Operand::Move(place) => place.ty(locals), - Operand::Constant(c) => Ok(c.ty()), - } - } -} - -impl ConstOperand { - pub fn ty(&self) -> Ty { - self.const_.ty() - } -} - -impl Place { - /// Resolve down the chain of projections to get the type referenced at the end of it. - /// E.g.: - /// Calling `ty()` on `var.field` should return the type of `field`. - /// - /// In order to retrieve the correct type, the `locals` argument must match the list of all - /// locals from the function body where this place originates from. - pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> { - self.projection.iter().try_fold(locals[self.local].ty, |place_ty, elem| elem.ty(place_ty)) - } -} - -impl ProjectionElem { - /// Get the expected type after applying this projection to a given place type. - pub fn ty(&self, place_ty: Ty) -> Result<Ty, Error> { - let ty = place_ty; - match &self { - ProjectionElem::Deref => Self::deref_ty(ty), - ProjectionElem::Field(_idx, fty) => Ok(*fty), - ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => Self::index_ty(ty), - ProjectionElem::Subslice { from, to, from_end } => { - Self::subslice_ty(ty, *from, *to, *from_end) - } - ProjectionElem::Downcast(_) => Ok(ty), - ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty), - } - } - - fn index_ty(ty: Ty) -> Result<Ty, Error> { - ty.kind().builtin_index().ok_or_else(|| error!("Cannot index non-array type: {ty:?}")) - } - - fn subslice_ty(ty: Ty, from: u64, to: u64, from_end: bool) -> Result<Ty, Error> { - let ty_kind = ty.kind(); - match ty_kind { - TyKind::RigidTy(RigidTy::Slice(..)) => Ok(ty), - TyKind::RigidTy(RigidTy::Array(inner, _)) if !from_end => Ty::try_new_array( - inner, - to.checked_sub(from).ok_or_else(|| error!("Subslice overflow: {from}..{to}"))?, - ), - TyKind::RigidTy(RigidTy::Array(inner, size)) => { - let size = size.eval_target_usize()?; - let len = size - from - to; - Ty::try_new_array(inner, len) - } - _ => Err(Error(format!("Cannot subslice non-array type: `{ty_kind:?}`"))), - } - } - - fn deref_ty(ty: Ty) -> Result<Ty, Error> { - let deref_ty = ty - .kind() - .builtin_deref(true) - .ok_or_else(|| error!("Cannot dereference type: {ty:?}"))?; - Ok(deref_ty.ty) - } -} diff --git a/compiler/rustc_smir/src/stable_mir/mir/mono.rs b/compiler/rustc_smir/src/stable_mir/mir/mono.rs deleted file mode 100644 index 5f177416714..00000000000 --- a/compiler/rustc_smir/src/stable_mir/mir/mono.rs +++ /dev/null @@ -1,306 +0,0 @@ -use std::fmt::{Debug, Formatter}; -use std::io; - -use rustc_smir::bridge::SmirError; -use serde::Serialize; -use stable_mir::abi::FnAbi; -use stable_mir::crate_def::CrateDef; -use stable_mir::mir::Body; -use stable_mir::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, Ty}; -use stable_mir::{CrateItem, DefId, Error, IndexedVal, ItemKind, Opaque, Symbol, with}; - -use crate::{rustc_smir, stable_mir}; - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub enum MonoItem { - Fn(Instance), - Static(StaticDef), - GlobalAsm(Opaque), -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize)] -pub struct Instance { - /// The type of instance. - pub kind: InstanceKind, - /// An ID used to get the instance definition from the compiler. - /// Do not use this field directly. - pub def: InstanceDef, -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)] -pub enum InstanceKind { - /// A user defined item. - Item, - /// A compiler intrinsic function. - Intrinsic, - /// A virtual function definition stored in a VTable. - /// The `idx` field indicates the position in the VTable for this instance. - Virtual { idx: usize }, - /// A compiler generated shim. - Shim, -} - -impl Instance { - /// Get the arguments this instance was instantiated with. - pub fn args(&self) -> GenericArgs { - with(|cx| cx.instance_args(self.def)) - } - - /// Get the body of an Instance. - /// - /// The body will be eagerly monomorphized and all constants will already be evaluated. - /// - /// This method will return the intrinsic fallback body if one was defined. - pub fn body(&self) -> Option<Body> { - with(|context| context.instance_body(self.def)) - } - - /// Check whether this instance has a body available. - /// - /// For intrinsics with fallback body, this will return `true`. It is up to the user to decide - /// whether to specialize the intrinsic or to use its fallback body. - /// - /// For more information on fallback body, see <https://github.com/rust-lang/rust/issues/93145>. - /// - /// This call is much cheaper than `instance.body().is_some()`, since it doesn't try to build - /// the StableMIR body. - pub fn has_body(&self) -> bool { - with(|cx| cx.has_body(self.def.def_id())) - } - - pub fn is_foreign_item(&self) -> bool { - with(|cx| cx.is_foreign_item(self.def.def_id())) - } - - /// Get the instance type with generic instantiations applied and lifetimes erased. - pub fn ty(&self) -> Ty { - with(|context| context.instance_ty(self.def)) - } - - /// Retrieve information about this instance binary interface. - pub fn fn_abi(&self) -> Result<FnAbi, Error> { - with(|cx| cx.instance_abi(self.def)) - } - - /// Retrieve the instance's mangled name used for calling the given instance. - /// - /// This will also look up the correct name of instances from upstream crates. - pub fn mangled_name(&self) -> Symbol { - with(|context| context.instance_mangled_name(self.def)) - } - - /// Retrieve the instance name for diagnostic messages. - /// - /// This will return the specialized name, e.g., `std::vec::Vec<u8>::new`. - pub fn name(&self) -> Symbol { - with(|context| context.instance_name(self.def, false)) - } - - /// Return a trimmed name of the given instance including its args. - /// - /// If a symbol name can only be imported from one place for a type, and as - /// long as it was not glob-imported anywhere in the current crate, we trim its - /// path and print only the name. - pub fn trimmed_name(&self) -> Symbol { - with(|context| context.instance_name(self.def, true)) - } - - /// Retrieve the plain intrinsic name of an instance if it's an intrinsic. - /// - /// The plain name does not include type arguments (as `trimmed_name` does), - /// which is more convenient to match with intrinsic symbols. - pub fn intrinsic_name(&self) -> Option<Symbol> { - match self.kind { - InstanceKind::Intrinsic => { - Some(with(|context| context.intrinsic(self.def.def_id()).unwrap().fn_name())) - } - InstanceKind::Item | InstanceKind::Virtual { .. } | InstanceKind::Shim => None, - } - } - - /// Resolve an instance starting from a function definition and generic arguments. - pub fn resolve(def: FnDef, args: &GenericArgs) -> Result<Instance, Error> { - with(|context| { - context - .resolve_instance(def, args) - .ok_or_else(|| Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`"))) - }) - } - - /// Resolve the drop in place for a given type. - pub fn resolve_drop_in_place(ty: Ty) -> Instance { - with(|cx| cx.resolve_drop_in_place(ty)) - } - - /// Resolve an instance for a given function pointer. - pub fn resolve_for_fn_ptr(def: FnDef, args: &GenericArgs) -> Result<Instance, Error> { - with(|context| { - context - .resolve_for_fn_ptr(def, args) - .ok_or_else(|| Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`"))) - }) - } - - /// Resolve a closure with the expected kind. - pub fn resolve_closure( - def: ClosureDef, - args: &GenericArgs, - kind: ClosureKind, - ) -> Result<Instance, Error> { - with(|context| { - context - .resolve_closure(def, args, kind) - .ok_or_else(|| Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`"))) - }) - } - - /// Check whether this instance is an empty shim. - /// - /// Allow users to check if this shim can be ignored when called directly. - /// - /// We have decided not to export different types of Shims to StableMIR users, however, this - /// is a query that can be very helpful for users when processing DropGlue. - /// - /// When generating code for a Drop terminator, users can ignore an empty drop glue. - /// These shims are only needed to generate a valid Drop call done via VTable. - pub fn is_empty_shim(&self) -> bool { - self.kind == InstanceKind::Shim && with(|cx| cx.is_empty_drop_shim(self.def)) - } - - /// Try to constant evaluate the instance into a constant with the given type. - /// - /// This can be used to retrieve a constant that represents an intrinsic return such as - /// `type_id`. - pub fn try_const_eval(&self, const_ty: Ty) -> Result<Allocation, Error> { - with(|cx| cx.eval_instance(self.def, const_ty)) - } - - /// Emit the body of this instance if it has one. - pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> { - if let Some(body) = self.body() { body.dump(w, &self.name()) } else { Ok(()) } - } -} - -impl Debug for Instance { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Instance") - .field("kind", &self.kind) - .field("def", &self.mangled_name()) - .field("args", &self.args()) - .finish() - } -} - -/// Try to convert a crate item into an instance. -/// The item cannot be generic in order to be converted into an instance. -impl TryFrom<CrateItem> for Instance { - type Error = stable_mir::Error; - - fn try_from(item: CrateItem) -> Result<Self, Self::Error> { - with(|context| { - let def_id = item.def_id(); - if !context.requires_monomorphization(def_id) { - Ok(context.mono_instance(def_id)) - } else { - Err(Error::new("Item requires monomorphization".to_string())) - } - }) - } -} - -/// Try to convert an instance into a crate item. -/// Only user defined instances can be converted. -impl TryFrom<Instance> for CrateItem { - type Error = stable_mir::Error; - - fn try_from(value: Instance) -> Result<Self, Self::Error> { - with(|context| { - if value.kind == InstanceKind::Item && context.has_body(value.def.def_id()) { - Ok(CrateItem(context.instance_def_id(value.def))) - } else { - Err(Error::new(format!("Item kind `{:?}` cannot be converted", value.kind))) - } - }) - } -} - -impl From<Instance> for MonoItem { - fn from(value: Instance) -> Self { - MonoItem::Fn(value) - } -} - -impl From<StaticDef> for MonoItem { - fn from(value: StaticDef) -> Self { - MonoItem::Static(value) - } -} - -impl From<StaticDef> for CrateItem { - fn from(value: StaticDef) -> Self { - CrateItem(value.0) - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] -pub struct InstanceDef(usize); - -impl CrateDef for InstanceDef { - fn def_id(&self) -> DefId { - with(|context| context.instance_def_id(*self)) - } -} - -crate_def! { - /// Holds information about a static variable definition. - #[derive(Serialize)] - pub StaticDef; -} - -impl TryFrom<CrateItem> for StaticDef { - type Error = stable_mir::Error; - - fn try_from(value: CrateItem) -> Result<Self, Self::Error> { - if matches!(value.kind(), ItemKind::Static) { - Ok(StaticDef(value.0)) - } else { - Err(Error::new(format!("Expected a static item, but found: {value:?}"))) - } - } -} - -impl TryFrom<Instance> for StaticDef { - type Error = stable_mir::Error; - - fn try_from(value: Instance) -> Result<Self, Self::Error> { - StaticDef::try_from(CrateItem::try_from(value)?) - } -} - -impl From<StaticDef> for Instance { - fn from(value: StaticDef) -> Self { - // A static definition should always be convertible to an instance. - with(|cx| cx.mono_instance(value.def_id())) - } -} - -impl StaticDef { - /// Return the type of this static definition. - pub fn ty(&self) -> Ty { - with(|cx| cx.def_ty(self.0)) - } - - /// Evaluate a static's initializer, returning the allocation of the initializer's memory. - pub fn eval_initializer(&self) -> Result<Allocation, Error> { - with(|cx| cx.eval_static_initializer(*self)) - } -} - -impl IndexedVal for InstanceDef { - fn to_val(index: usize) -> Self { - InstanceDef(index) - } - fn to_index(&self) -> usize { - self.0 - } -} diff --git a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs deleted file mode 100644 index a7347e9b021..00000000000 --- a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs +++ /dev/null @@ -1,470 +0,0 @@ -//! Implement methods to pretty print stable MIR body. -use std::fmt::Debug; -use std::io::Write; -use std::{fmt, io, iter}; - -use fmt::{Display, Formatter}; -use stable_mir::mir::{ - Operand, Place, RawPtrKind, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents, -}; -use stable_mir::ty::{AdtKind, AssocKind, MirConst, Ty, TyConst}; -use stable_mir::{Body, CrateDef, IndexedVal, Mutability, with}; - -use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind}; -use crate::stable_mir; - -impl Display for Ty { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - with(|ctx| write!(f, "{}", ctx.ty_pretty(*self))) - } -} - -impl Display for AssocKind { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - AssocKind::Fn { has_self: true, .. } => write!(f, "method"), - AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"), - AssocKind::Const { .. } => write!(f, "associated const"), - AssocKind::Type { .. } => write!(f, "associated type"), - } - } -} - -impl Debug for Place { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - with(|ctx| write!(f, "{}", ctx.place_pretty(self))) - } -} - -pub(crate) fn function_body<W: Write>(writer: &mut W, body: &Body, name: &str) -> io::Result<()> { - write!(writer, "fn {name}(")?; - let mut sep = ""; - for (index, local) in body.arg_locals().iter().enumerate() { - write!(writer, "{}_{}: {}", sep, index + 1, local.ty)?; - sep = ", "; - } - write!(writer, ")")?; - - let return_local = body.ret_local(); - writeln!(writer, " -> {} {{", return_local.ty)?; - - body.locals().iter().enumerate().try_for_each(|(index, local)| -> io::Result<()> { - if index == 0 || index > body.arg_count { - writeln!(writer, " let {}_{}: {};", pretty_mut(local.mutability), index, local.ty) - } else { - Ok(()) - } - })?; - - body.var_debug_info.iter().try_for_each(|info| { - let content = match &info.value { - VarDebugInfoContents::Place(place) => { - format!("{place:?}") - } - VarDebugInfoContents::Const(constant) => pretty_mir_const(&constant.const_), - }; - writeln!(writer, " debug {} => {};", info.name, content) - })?; - - body.blocks - .iter() - .enumerate() - .map(|(index, block)| -> io::Result<()> { - writeln!(writer, " bb{index}: {{")?; - let _ = block - .statements - .iter() - .map(|statement| -> io::Result<()> { - pretty_statement(writer, &statement.kind)?; - Ok(()) - }) - .collect::<Vec<_>>(); - pretty_terminator(writer, &block.terminator.kind)?; - writeln!(writer, " }}").unwrap(); - Ok(()) - }) - .collect::<Result<Vec<_>, _>>()?; - writeln!(writer, "}}")?; - Ok(()) -} - -fn pretty_statement<W: Write>(writer: &mut W, statement: &StatementKind) -> io::Result<()> { - const INDENT: &str = " "; - match statement { - StatementKind::Assign(place, rval) => { - write!(writer, "{INDENT}{place:?} = ")?; - pretty_rvalue(writer, rval)?; - writeln!(writer, ";") - } - // FIXME: Add rest of the statements - StatementKind::FakeRead(cause, place) => { - writeln!(writer, "{INDENT}FakeRead({cause:?}, {place:?});") - } - StatementKind::SetDiscriminant { place, variant_index } => { - writeln!(writer, "{INDENT}discriminant({place:?} = {};", variant_index.to_index()) - } - StatementKind::Deinit(place) => writeln!(writer, "Deinit({place:?};"), - StatementKind::StorageLive(local) => { - writeln!(writer, "{INDENT}StorageLive(_{local});") - } - StatementKind::StorageDead(local) => { - writeln!(writer, "{INDENT}StorageDead(_{local});") - } - StatementKind::Retag(kind, place) => writeln!(writer, "Retag({kind:?}, {place:?});"), - StatementKind::PlaceMention(place) => { - writeln!(writer, "{INDENT}PlaceMention({place:?};") - } - StatementKind::ConstEvalCounter => { - writeln!(writer, "{INDENT}ConstEvalCounter;") - } - StatementKind::Nop => writeln!(writer, "{INDENT}nop;"), - StatementKind::AscribeUserType { .. } - | StatementKind::Coverage(_) - | StatementKind::Intrinsic(_) => { - // FIX-ME: Make them pretty. - writeln!(writer, "{INDENT}{statement:?};") - } - } -} - -fn pretty_terminator<W: Write>(writer: &mut W, terminator: &TerminatorKind) -> io::Result<()> { - pretty_terminator_head(writer, terminator)?; - let successors = terminator.successors(); - let successor_count = successors.len(); - let labels = pretty_successor_labels(terminator); - - let show_unwind = !matches!(terminator.unwind(), None | Some(UnwindAction::Cleanup(_))); - let fmt_unwind = |w: &mut W| -> io::Result<()> { - write!(w, "unwind ")?; - match terminator.unwind() { - None | Some(UnwindAction::Cleanup(_)) => unreachable!(), - Some(UnwindAction::Continue) => write!(w, "continue"), - Some(UnwindAction::Unreachable) => write!(w, "unreachable"), - Some(UnwindAction::Terminate) => write!(w, "terminate"), - } - }; - - match (successor_count, show_unwind) { - (0, false) => {} - (0, true) => { - write!(writer, " -> ")?; - fmt_unwind(writer)?; - } - (1, false) => write!(writer, " -> bb{:?}", successors[0])?, - _ => { - write!(writer, " -> [")?; - for (i, target) in successors.iter().enumerate() { - if i > 0 { - write!(writer, ", ")?; - } - write!(writer, "{}: bb{:?}", labels[i], target)?; - } - if show_unwind { - write!(writer, ", ")?; - fmt_unwind(writer)?; - } - write!(writer, "]")?; - } - }; - - writeln!(writer, ";") -} - -fn pretty_terminator_head<W: Write>(writer: &mut W, terminator: &TerminatorKind) -> io::Result<()> { - use self::TerminatorKind::*; - const INDENT: &str = " "; - match terminator { - Goto { .. } => write!(writer, "{INDENT}goto"), - SwitchInt { discr, .. } => { - write!(writer, "{INDENT}switchInt({})", pretty_operand(discr)) - } - Resume => write!(writer, "{INDENT}resume"), - Abort => write!(writer, "{INDENT}abort"), - Return => write!(writer, "{INDENT}return"), - Unreachable => write!(writer, "{INDENT}unreachable"), - Drop { place, .. } => write!(writer, "{INDENT}drop({place:?})"), - Call { func, args, destination, .. } => { - write!(writer, "{INDENT}{:?} = {}(", destination, pretty_operand(func))?; - let mut args_iter = args.iter(); - args_iter.next().map_or(Ok(()), |arg| write!(writer, "{}", pretty_operand(arg)))?; - args_iter.try_for_each(|arg| write!(writer, ", {}", pretty_operand(arg)))?; - write!(writer, ")") - } - Assert { cond, expected, msg, target: _, unwind: _ } => { - write!(writer, "{INDENT}assert(")?; - if !expected { - write!(writer, "!")?; - } - write!(writer, "{}, ", pretty_operand(cond))?; - pretty_assert_message(writer, msg)?; - write!(writer, ")") - } - InlineAsm { .. } => write!(writer, "{INDENT}InlineAsm"), - } -} - -fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec<String> { - use self::TerminatorKind::*; - match terminator { - Call { target: None, unwind: UnwindAction::Cleanup(_), .. } - | InlineAsm { destination: None, .. } => vec!["unwind".into()], - Resume | Abort | Return | Unreachable | Call { target: None, unwind: _, .. } => vec![], - Goto { .. } => vec!["".to_string()], - SwitchInt { targets, .. } => targets - .branches() - .map(|(val, _target)| format!("{val}")) - .chain(iter::once("otherwise".into())) - .collect(), - Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()], - Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => { - vec!["return".into(), "unwind".into()] - } - Drop { unwind: _, .. } | Call { target: Some(_), unwind: _, .. } => vec!["return".into()], - Assert { unwind: UnwindAction::Cleanup(_), .. } => { - vec!["success".into(), "unwind".into()] - } - Assert { unwind: _, .. } => vec!["success".into()], - InlineAsm { destination: Some(_), .. } => vec!["goto".into(), "unwind".into()], - } -} - -fn pretty_assert_message<W: Write>(writer: &mut W, msg: &AssertMessage) -> io::Result<()> { - match msg { - AssertMessage::BoundsCheck { len, index } => { - let pretty_len = pretty_operand(len); - let pretty_index = pretty_operand(index); - write!( - writer, - "\"index out of bounds: the length is {{}} but the index is {{}}\", {pretty_len}, {pretty_index}" - ) - } - AssertMessage::Overflow(BinOp::Add, l, r) => { - let pretty_l = pretty_operand(l); - let pretty_r = pretty_operand(r); - write!( - writer, - "\"attempt to compute `{{}} + {{}}`, which would overflow\", {pretty_l}, {pretty_r}" - ) - } - AssertMessage::Overflow(BinOp::Sub, l, r) => { - let pretty_l = pretty_operand(l); - let pretty_r = pretty_operand(r); - write!( - writer, - "\"attempt to compute `{{}} - {{}}`, which would overflow\", {pretty_l}, {pretty_r}" - ) - } - AssertMessage::Overflow(BinOp::Mul, l, r) => { - let pretty_l = pretty_operand(l); - let pretty_r = pretty_operand(r); - write!( - writer, - "\"attempt to compute `{{}} * {{}}`, which would overflow\", {pretty_l}, {pretty_r}" - ) - } - AssertMessage::Overflow(BinOp::Div, l, r) => { - let pretty_l = pretty_operand(l); - let pretty_r = pretty_operand(r); - write!( - writer, - "\"attempt to compute `{{}} / {{}}`, which would overflow\", {pretty_l}, {pretty_r}" - ) - } - AssertMessage::Overflow(BinOp::Rem, l, r) => { - let pretty_l = pretty_operand(l); - let pretty_r = pretty_operand(r); - write!( - writer, - "\"attempt to compute `{{}} % {{}}`, which would overflow\", {pretty_l}, {pretty_r}" - ) - } - AssertMessage::Overflow(BinOp::Shr, _, r) => { - let pretty_r = pretty_operand(r); - write!(writer, "\"attempt to shift right by `{{}}`, which would overflow\", {pretty_r}") - } - AssertMessage::Overflow(BinOp::Shl, _, r) => { - let pretty_r = pretty_operand(r); - write!(writer, "\"attempt to shift left by `{{}}`, which would overflow\", {pretty_r}") - } - AssertMessage::Overflow(op, _, _) => unreachable!("`{:?}` cannot overflow", op), - AssertMessage::OverflowNeg(op) => { - let pretty_op = pretty_operand(op); - write!(writer, "\"attempt to negate `{{}}`, which would overflow\", {pretty_op}") - } - AssertMessage::DivisionByZero(op) => { - let pretty_op = pretty_operand(op); - write!(writer, "\"attempt to divide `{{}}` by zero\", {pretty_op}") - } - AssertMessage::RemainderByZero(op) => { - let pretty_op = pretty_operand(op); - write!( - writer, - "\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {pretty_op}" - ) - } - AssertMessage::MisalignedPointerDereference { required, found } => { - let pretty_required = pretty_operand(required); - let pretty_found = pretty_operand(found); - write!( - writer, - "\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}" - ) - } - AssertMessage::NullPointerDereference => { - write!(writer, "\"null pointer dereference occurred\"") - } - AssertMessage::InvalidEnumConstruction(op) => { - let pretty_op = pretty_operand(op); - write!(writer, "\"trying to construct an enum from an invalid value {{}}\",{pretty_op}") - } - AssertMessage::ResumedAfterReturn(_) - | AssertMessage::ResumedAfterPanic(_) - | AssertMessage::ResumedAfterDrop(_) => { - write!(writer, "{}", msg.description().unwrap()) - } - } -} - -fn pretty_operand(operand: &Operand) -> String { - match operand { - Operand::Copy(copy) => { - format!("{copy:?}") - } - Operand::Move(mv) => { - format!("move {mv:?}") - } - Operand::Constant(cnst) => pretty_mir_const(&cnst.const_), - } -} - -fn pretty_mir_const(literal: &MirConst) -> String { - with(|cx| cx.mir_const_pretty(literal)) -} - -fn pretty_ty_const(ct: &TyConst) -> String { - with(|cx| cx.ty_const_pretty(ct.id)) -} - -fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> { - match rval { - Rvalue::AddressOf(mutability, place) => { - write!(writer, "&raw {} {:?}", pretty_raw_ptr_kind(*mutability), place) - } - Rvalue::Aggregate(aggregate_kind, operands) => { - // FIXME: Add pretty_aggregate function that returns a pretty string - pretty_aggregate(writer, aggregate_kind, operands) - } - Rvalue::BinaryOp(bin, op1, op2) => { - write!(writer, "{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2)) - } - Rvalue::Cast(_, op, ty) => { - write!(writer, "{} as {}", pretty_operand(op), ty) - } - Rvalue::CheckedBinaryOp(bin, op1, op2) => { - write!(writer, "Checked{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2)) - } - Rvalue::CopyForDeref(deref) => { - write!(writer, "CopyForDeref({deref:?})") - } - Rvalue::Discriminant(place) => { - write!(writer, "discriminant({place:?})") - } - Rvalue::Len(len) => { - write!(writer, "len({len:?})") - } - Rvalue::Ref(_, borrowkind, place) => { - let kind = match borrowkind { - BorrowKind::Shared => "&", - BorrowKind::Fake(FakeBorrowKind::Deep) => "&fake ", - BorrowKind::Fake(FakeBorrowKind::Shallow) => "&fake shallow ", - BorrowKind::Mut { .. } => "&mut ", - }; - write!(writer, "{kind}{place:?}") - } - Rvalue::Repeat(op, cnst) => { - write!(writer, "[{}; {}]", pretty_operand(op), pretty_ty_const(cnst)) - } - Rvalue::ShallowInitBox(_, _) => Ok(()), - Rvalue::ThreadLocalRef(item) => { - write!(writer, "thread_local_ref{item:?}") - } - Rvalue::NullaryOp(nul, ty) => { - write!(writer, "{nul:?}::<{ty}>() \" \"") - } - Rvalue::UnaryOp(un, op) => { - write!(writer, "{:?}({})", un, pretty_operand(op)) - } - Rvalue::Use(op) => write!(writer, "{}", pretty_operand(op)), - } -} - -fn pretty_aggregate<W: Write>( - writer: &mut W, - aggregate_kind: &AggregateKind, - operands: &Vec<Operand>, -) -> io::Result<()> { - let suffix = match aggregate_kind { - AggregateKind::Array(_) => { - write!(writer, "[")?; - "]" - } - AggregateKind::Tuple => { - write!(writer, "(")?; - ")" - } - AggregateKind::Adt(def, var, _, _, _) => { - if def.kind() == AdtKind::Enum { - write!(writer, "{}::{}", def.name(), def.variant(*var).unwrap().name())?; - } else { - write!(writer, "{}", def.variant(*var).unwrap().name())?; - } - if operands.is_empty() { - return Ok(()); - } - // FIXME: Change this once we have CtorKind in StableMIR. - write!(writer, "(")?; - ")" - } - AggregateKind::Closure(def, _) => { - write!(writer, "{{closure@{}}}(", def.span().diagnostic())?; - ")" - } - AggregateKind::Coroutine(def, _, _) => { - write!(writer, "{{coroutine@{}}}(", def.span().diagnostic())?; - ")" - } - AggregateKind::CoroutineClosure(def, _) => { - write!(writer, "{{coroutine-closure@{}}}(", def.span().diagnostic())?; - ")" - } - AggregateKind::RawPtr(ty, mutability) => { - write!( - writer, - "*{} {ty} from (", - if *mutability == Mutability::Mut { "mut" } else { "const" } - )?; - ")" - } - }; - let mut separator = ""; - for op in operands { - write!(writer, "{}{}", separator, pretty_operand(op))?; - separator = ", "; - } - write!(writer, "{suffix}") -} - -fn pretty_mut(mutability: Mutability) -> &'static str { - match mutability { - Mutability::Not => " ", - Mutability::Mut => "mut ", - } -} - -fn pretty_raw_ptr_kind(kind: RawPtrKind) -> &'static str { - match kind { - RawPtrKind::Const => "const", - RawPtrKind::Mut => "mut", - RawPtrKind::FakeForPtrMetadata => "const (fake)", - } -} diff --git a/compiler/rustc_smir/src/stable_mir/mir/visit.rs b/compiler/rustc_smir/src/stable_mir/mir/visit.rs deleted file mode 100644 index b7dd433eb09..00000000000 --- a/compiler/rustc_smir/src/stable_mir/mir/visit.rs +++ /dev/null @@ -1,590 +0,0 @@ -//! # The Stable MIR Visitor -//! -//! ## Overview -//! -//! We currently only support an immutable visitor. -//! The structure of this visitor is similar to the ones internal to `rustc`, -//! and it follows the following conventions: -//! -//! For every mir item, the trait has a `visit_<item>` and a `super_<item>` method. -//! - `visit_<item>`, by default, calls `super_<item>` -//! - `super_<item>`, by default, destructures the `<item>` and calls `visit_<sub_item>` for -//! all sub-items that compose the original item. -//! -//! In order to implement a visitor, override the `visit_*` methods for the types you are -//! interested in analyzing, and invoke (within that method call) -//! `self.super_*` to continue to the traverse. -//! Avoid calling `super` methods in other circumstances. -//! -//! For the most part, we do not destructure things external to the -//! MIR, e.g., types, spans, etc, but simply visit them and stop. -//! This avoids duplication with other visitors like `TypeFoldable`. -//! -//! ## Updating -//! -//! The code is written in a very deliberate style intended to minimize -//! the chance of things being overlooked. -//! -//! Use pattern matching to reference fields and ensure that all -//! matches are exhaustive. -//! -//! For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS. -//! That means you never write `..` to skip over fields, nor do you write `_` -//! to skip over variants in a `match`. -//! -//! The only place that `_` is acceptable is to match a field (or -//! variant argument) that does not require visiting. - -use stable_mir::mir::*; -use stable_mir::ty::{GenericArgs, MirConst, Region, Ty, TyConst}; -use stable_mir::{Error, Opaque, Span}; - -use crate::stable_mir; - -macro_rules! make_mir_visitor { - ($visitor_trait_name:ident, $($mutability:ident)?) => { - pub trait $visitor_trait_name { - fn visit_body(&mut self, body: &$($mutability)? Body) { - self.super_body(body) - } - - fn visit_basic_block(&mut self, bb: &$($mutability)? BasicBlock) { - self.super_basic_block(bb) - } - - fn visit_ret_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { - self.super_ret_decl(local, decl) - } - - fn visit_arg_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { - self.super_arg_decl(local, decl) - } - - fn visit_local_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { - self.super_local_decl(local, decl) - } - - fn visit_statement(&mut self, stmt: &$($mutability)? Statement, location: Location) { - self.super_statement(stmt, location) - } - - fn visit_terminator(&mut self, term: &$($mutability)? Terminator, location: Location) { - self.super_terminator(term, location) - } - - fn visit_span(&mut self, span: &$($mutability)? Span) { - self.super_span(span) - } - - fn visit_place(&mut self, place: &$($mutability)? Place, ptx: PlaceContext, location: Location) { - self.super_place(place, ptx, location) - } - - visit_place_fns!($($mutability)?); - - fn visit_local(&mut self, local: &$($mutability)? Local, ptx: PlaceContext, location: Location) { - let _ = (local, ptx, location); - } - - fn visit_rvalue(&mut self, rvalue: &$($mutability)? Rvalue, location: Location) { - self.super_rvalue(rvalue, location) - } - - fn visit_operand(&mut self, operand: &$($mutability)? Operand, location: Location) { - self.super_operand(operand, location) - } - - fn visit_user_type_projection(&mut self, projection: &$($mutability)? UserTypeProjection) { - self.super_user_type_projection(projection) - } - - fn visit_ty(&mut self, ty: &$($mutability)? Ty, location: Location) { - let _ = location; - self.super_ty(ty) - } - - fn visit_const_operand(&mut self, constant: &$($mutability)? ConstOperand, location: Location) { - self.super_const_operand(constant, location) - } - - fn visit_mir_const(&mut self, constant: &$($mutability)? MirConst, location: Location) { - self.super_mir_const(constant, location) - } - - fn visit_ty_const(&mut self, constant: &$($mutability)? TyConst, location: Location) { - let _ = location; - self.super_ty_const(constant) - } - - fn visit_region(&mut self, region: &$($mutability)? Region, location: Location) { - let _ = location; - self.super_region(region) - } - - fn visit_args(&mut self, args: &$($mutability)? GenericArgs, location: Location) { - let _ = location; - self.super_args(args) - } - - fn visit_assert_msg(&mut self, msg: &$($mutability)? AssertMessage, location: Location) { - self.super_assert_msg(msg, location) - } - - fn visit_var_debug_info(&mut self, var_debug_info: &$($mutability)? VarDebugInfo) { - self.super_var_debug_info(var_debug_info); - } - - fn super_body(&mut self, body: &$($mutability)? Body) { - super_body!(self, body, $($mutability)?); - } - - fn super_basic_block(&mut self, bb: &$($mutability)? BasicBlock) { - let BasicBlock { statements, terminator } = bb; - for stmt in statements { - self.visit_statement(stmt, Location(stmt.span)); - } - self.visit_terminator(terminator, Location(terminator.span)); - } - - fn super_local_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { - let _ = local; - let LocalDecl { ty, span, .. } = decl; - self.visit_ty(ty, Location(*span)); - } - - fn super_ret_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { - self.super_local_decl(local, decl) - } - - fn super_arg_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { - self.super_local_decl(local, decl) - } - - fn super_statement(&mut self, stmt: &$($mutability)? Statement, location: Location) { - let Statement { kind, span } = stmt; - self.visit_span(span); - match kind { - StatementKind::Assign(place, rvalue) => { - self.visit_place(place, PlaceContext::MUTATING, location); - self.visit_rvalue(rvalue, location); - } - StatementKind::FakeRead(_, place) | StatementKind::PlaceMention(place) => { - self.visit_place(place, PlaceContext::NON_MUTATING, location); - } - StatementKind::SetDiscriminant { place, .. } - | StatementKind::Deinit(place) - | StatementKind::Retag(_, place) => { - self.visit_place(place, PlaceContext::MUTATING, location); - } - StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { - self.visit_local(local, PlaceContext::NON_USE, location); - } - StatementKind::AscribeUserType { place, projections, variance: _ } => { - self.visit_place(place, PlaceContext::NON_USE, location); - self.visit_user_type_projection(projections); - } - StatementKind::Coverage(coverage) => visit_opaque(coverage), - StatementKind::Intrinsic(intrisic) => match intrisic { - NonDivergingIntrinsic::Assume(operand) => { - self.visit_operand(operand, location); - } - NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { - src, - dst, - count, - }) => { - self.visit_operand(src, location); - self.visit_operand(dst, location); - self.visit_operand(count, location); - } - }, - StatementKind::ConstEvalCounter | StatementKind::Nop => {} - } - } - - fn super_terminator(&mut self, term: &$($mutability)? Terminator, location: Location) { - let Terminator { kind, span } = term; - self.visit_span(span); - match kind { - TerminatorKind::Goto { .. } - | TerminatorKind::Resume - | TerminatorKind::Abort - | TerminatorKind::Unreachable => {} - TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => { - self.visit_operand(cond, location); - self.visit_assert_msg(msg, location); - } - TerminatorKind::Drop { place, target: _, unwind: _ } => { - self.visit_place(place, PlaceContext::MUTATING, location); - } - TerminatorKind::Call { func, args, destination, target: _, unwind: _ } => { - self.visit_operand(func, location); - for arg in args { - self.visit_operand(arg, location); - } - self.visit_place(destination, PlaceContext::MUTATING, location); - } - TerminatorKind::InlineAsm { operands, .. } => { - for op in operands { - let InlineAsmOperand { in_value, out_place, raw_rpr: _ } = op; - if let Some(input) = in_value { - self.visit_operand(input, location); - } - if let Some(output) = out_place { - self.visit_place(output, PlaceContext::MUTATING, location); - } - } - } - TerminatorKind::Return => { - let $($mutability)? local = RETURN_LOCAL; - self.visit_local(&$($mutability)? local, PlaceContext::NON_MUTATING, location); - } - TerminatorKind::SwitchInt { discr, targets: _ } => { - self.visit_operand(discr, location); - } - } - } - - fn super_span(&mut self, span: &$($mutability)? Span) { - let _ = span; - } - - fn super_rvalue(&mut self, rvalue: &$($mutability)? Rvalue, location: Location) { - match rvalue { - Rvalue::AddressOf(mutability, place) => { - let pcx = PlaceContext { is_mut: *mutability == RawPtrKind::Mut }; - self.visit_place(place, pcx, location); - } - Rvalue::Aggregate(_, operands) => { - for op in operands { - self.visit_operand(op, location); - } - } - Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { - self.visit_operand(lhs, location); - self.visit_operand(rhs, location); - } - Rvalue::Cast(_, op, ty) => { - self.visit_operand(op, location); - self.visit_ty(ty, location); - } - Rvalue::CopyForDeref(place) | Rvalue::Discriminant(place) | Rvalue::Len(place) => { - self.visit_place(place, PlaceContext::NON_MUTATING, location); - } - Rvalue::Ref(region, kind, place) => { - self.visit_region(region, location); - let pcx = PlaceContext { is_mut: matches!(kind, BorrowKind::Mut { .. }) }; - self.visit_place(place, pcx, location); - } - Rvalue::Repeat(op, constant) => { - self.visit_operand(op, location); - self.visit_ty_const(constant, location); - } - Rvalue::ShallowInitBox(op, ty) => { - self.visit_ty(ty, location); - self.visit_operand(op, location) - } - Rvalue::ThreadLocalRef(_) => {} - Rvalue::NullaryOp(_, ty) => { - self.visit_ty(ty, location); - } - Rvalue::UnaryOp(_, op) | Rvalue::Use(op) => { - self.visit_operand(op, location); - } - } - } - - fn super_operand(&mut self, operand: &$($mutability)? Operand, location: Location) { - match operand { - Operand::Copy(place) | Operand::Move(place) => { - self.visit_place(place, PlaceContext::NON_MUTATING, location) - } - Operand::Constant(constant) => { - self.visit_const_operand(constant, location); - } - } - } - - fn super_user_type_projection(&mut self, projection: &$($mutability)? UserTypeProjection) { - // This is a no-op on mir::Visitor. - let _ = projection; - } - - fn super_ty(&mut self, ty: &$($mutability)? Ty) { - let _ = ty; - } - - fn super_const_operand(&mut self, constant: &$($mutability)? ConstOperand, location: Location) { - let ConstOperand { span, user_ty: _, const_ } = constant; - self.visit_span(span); - self.visit_mir_const(const_, location); - } - - fn super_mir_const(&mut self, constant: &$($mutability)? MirConst, location: Location) { - let MirConst { kind: _, ty, id: _ } = constant; - self.visit_ty(ty, location); - } - - fn super_ty_const(&mut self, constant: &$($mutability)? TyConst) { - let _ = constant; - } - - fn super_region(&mut self, region: &$($mutability)? Region) { - let _ = region; - } - - fn super_args(&mut self, args: &$($mutability)? GenericArgs) { - let _ = args; - } - - fn super_var_debug_info(&mut self, var_debug_info: &$($mutability)? VarDebugInfo) { - let VarDebugInfo { source_info, composite, value, name: _, argument_index: _ } = - var_debug_info; - self.visit_span(&$($mutability)? source_info.span); - let location = Location(source_info.span); - if let Some(composite) = composite { - self.visit_ty(&$($mutability)? composite.ty, location); - } - match value { - VarDebugInfoContents::Place(place) => { - self.visit_place(place, PlaceContext::NON_USE, location); - } - VarDebugInfoContents::Const(constant) => { - self.visit_mir_const(&$($mutability)? constant.const_, location); - } - } - } - - fn super_assert_msg(&mut self, msg: &$($mutability)? AssertMessage, location: Location) { - match msg { - AssertMessage::BoundsCheck { len, index } => { - self.visit_operand(len, location); - self.visit_operand(index, location); - } - AssertMessage::Overflow(_, left, right) => { - self.visit_operand(left, location); - self.visit_operand(right, location); - } - AssertMessage::OverflowNeg(op) - | AssertMessage::DivisionByZero(op) - | AssertMessage::RemainderByZero(op) - | AssertMessage::InvalidEnumConstruction(op) => { - self.visit_operand(op, location); - } - AssertMessage::ResumedAfterReturn(_) - | AssertMessage::ResumedAfterPanic(_) - | AssertMessage::NullPointerDereference - | AssertMessage::ResumedAfterDrop(_) => { - //nothing to visit - } - AssertMessage::MisalignedPointerDereference { required, found } => { - self.visit_operand(required, location); - self.visit_operand(found, location); - } - } - } - } - }; -} - -macro_rules! super_body { - ($self:ident, $body:ident, mut) => { - for bb in $body.blocks.iter_mut() { - $self.visit_basic_block(bb); - } - - $self.visit_ret_decl(RETURN_LOCAL, $body.ret_local_mut()); - - for (idx, arg) in $body.arg_locals_mut().iter_mut().enumerate() { - $self.visit_arg_decl(idx + 1, arg) - } - - let local_start = $body.arg_count + 1; - for (idx, arg) in $body.inner_locals_mut().iter_mut().enumerate() { - $self.visit_local_decl(idx + local_start, arg) - } - - for info in $body.var_debug_info.iter_mut() { - $self.visit_var_debug_info(info); - } - - $self.visit_span(&mut $body.span) - }; - - ($self:ident, $body:ident, ) => { - let Body { blocks, locals: _, arg_count, var_debug_info, spread_arg: _, span } = $body; - - for bb in blocks { - $self.visit_basic_block(bb); - } - - $self.visit_ret_decl(RETURN_LOCAL, $body.ret_local()); - - for (idx, arg) in $body.arg_locals().iter().enumerate() { - $self.visit_arg_decl(idx + 1, arg) - } - - let local_start = arg_count + 1; - for (idx, arg) in $body.inner_locals().iter().enumerate() { - $self.visit_local_decl(idx + local_start, arg) - } - - for info in var_debug_info.iter() { - $self.visit_var_debug_info(info); - } - - $self.visit_span(span) - }; -} - -macro_rules! visit_place_fns { - (mut) => { - fn super_place(&mut self, place: &mut Place, ptx: PlaceContext, location: Location) { - self.visit_local(&mut place.local, ptx, location); - - for elem in place.projection.iter_mut() { - self.visit_projection_elem(elem, ptx, location); - } - } - - // We don't have to replicate the `process_projection()` like we did in - // `rustc_middle::mir::visit.rs` here because the `projection` field in `Place` - // of Stable-MIR is not an immutable borrow, unlike in `Place` of MIR. - fn visit_projection_elem( - &mut self, - elem: &mut ProjectionElem, - ptx: PlaceContext, - location: Location, - ) { - self.super_projection_elem(elem, ptx, location) - } - - fn super_projection_elem( - &mut self, - elem: &mut ProjectionElem, - ptx: PlaceContext, - location: Location, - ) { - match elem { - ProjectionElem::Deref => {} - ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location), - ProjectionElem::Index(local) => self.visit_local(local, ptx, location), - ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } => {} - ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {} - ProjectionElem::Downcast(_idx) => {} - ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location), - ProjectionElem::Subtype(ty) => self.visit_ty(ty, location), - } - } - }; - - () => { - fn super_place(&mut self, place: &Place, ptx: PlaceContext, location: Location) { - self.visit_local(&place.local, ptx, location); - - for (idx, elem) in place.projection.iter().enumerate() { - let place_ref = - PlaceRef { local: place.local, projection: &place.projection[..idx] }; - self.visit_projection_elem(place_ref, elem, ptx, location); - } - } - - fn visit_projection_elem<'a>( - &mut self, - place_ref: PlaceRef<'a>, - elem: &ProjectionElem, - ptx: PlaceContext, - location: Location, - ) { - let _ = place_ref; - self.super_projection_elem(elem, ptx, location); - } - - fn super_projection_elem( - &mut self, - elem: &ProjectionElem, - ptx: PlaceContext, - location: Location, - ) { - match elem { - ProjectionElem::Deref => {} - ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location), - ProjectionElem::Index(local) => self.visit_local(local, ptx, location), - ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } => {} - ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {} - ProjectionElem::Downcast(_idx) => {} - ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location), - ProjectionElem::Subtype(ty) => self.visit_ty(ty, location), - } - } - }; -} - -make_mir_visitor!(MirVisitor,); -make_mir_visitor!(MutMirVisitor, mut); - -/// This function is a no-op that gets used to ensure this visitor is kept up-to-date. -/// -/// The idea is that whenever we replace an Opaque type by a real type, the compiler will fail -/// when trying to invoke `visit_opaque`. -/// -/// If you are here because your compilation is broken, replace the failing call to `visit_opaque()` -/// by a `visit_<CONSTRUCT>` for your construct. -fn visit_opaque(_: &Opaque) {} - -/// The location of a statement / terminator in the code and the CFG. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct Location(Span); - -impl Location { - pub fn span(&self) -> Span { - self.0 - } -} - -/// Location of the statement at the given index for a given basic block. Assumes that `stmt_idx` -/// and `bb_idx` are valid for a given body. -pub fn statement_location(body: &Body, bb_idx: &BasicBlockIdx, stmt_idx: usize) -> Location { - let bb = &body.blocks[*bb_idx]; - let stmt = &bb.statements[stmt_idx]; - Location(stmt.span) -} - -/// Location of the terminator for a given basic block. Assumes that `bb_idx` is valid for a given -/// body. -pub fn terminator_location(body: &Body, bb_idx: &BasicBlockIdx) -> Location { - let bb = &body.blocks[*bb_idx]; - let terminator = &bb.terminator; - Location(terminator.span) -} - -/// Reference to a place used to represent a partial projection. -pub struct PlaceRef<'a> { - pub local: Local, - pub projection: &'a [ProjectionElem], -} - -impl PlaceRef<'_> { - /// Get the type of this place. - pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> { - self.projection.iter().try_fold(locals[self.local].ty, |place_ty, elem| elem.ty(place_ty)) - } -} - -/// Information about a place's usage. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct PlaceContext { - /// Whether the access is mutable or not. Keep this private so we can increment the type in a - /// backward compatible manner. - is_mut: bool, -} - -impl PlaceContext { - const MUTATING: Self = PlaceContext { is_mut: true }; - const NON_MUTATING: Self = PlaceContext { is_mut: false }; - const NON_USE: Self = PlaceContext { is_mut: false }; - - pub fn is_mutating(&self) -> bool { - self.is_mut - } -} diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs deleted file mode 100644 index 70c09c12854..00000000000 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ /dev/null @@ -1,304 +0,0 @@ -//! Module that is temporarily parasitic on the `rustc_smir` crate, -//! -//! This module is designed to resolve circular dependency that would happen -//! if we gradually invert the dependency order between `rustc_smir` and `stable_mir`. -//! -//! Once refactoring is complete, we will migrate it back to the `stable_mir` crate. - -//! The WIP stable interface to rustc internals. -//! -//! For more information see <https://github.com/rust-lang/project-stable-mir> -//! -//! # Note -//! -//! This API is still completely unstable and subject to change. - -// #![doc( -// html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", -// test(attr(allow(unused_variables), deny(warnings))) -// )] -//! -//! This crate shall contain all type definitions and APIs that we expect third-party tools to invoke to -//! interact with the compiler. -//! -//! The goal is to eventually be published on -//! [crates.io](https://crates.io). - -use std::fmt::Debug; -use std::{fmt, io}; - -pub(crate) use rustc_smir::IndexedVal; -use rustc_smir::Tables; -use rustc_smir::context::SmirCtxt; -use serde::Serialize; -use stable_mir::compiler_interface::with; -pub use stable_mir::crate_def::{CrateDef, CrateDefItems, CrateDefType, DefId}; -pub use stable_mir::error::*; -use stable_mir::mir::mono::StaticDef; -use stable_mir::mir::{Body, Mutability}; -use stable_mir::ty::{ - AssocItem, FnDef, ForeignModuleDef, ImplDef, ProvenanceMap, Span, TraitDef, Ty, -}; -use stable_mir::unstable::Stable; - -use crate::{rustc_smir, stable_mir}; - -pub mod abi; -mod alloc; -pub(crate) mod unstable; -#[macro_use] -pub mod crate_def; -pub mod compiler_interface; -#[macro_use] -pub mod error; -pub mod mir; -pub mod target; -pub mod ty; -pub mod visitor; - -/// Use String for now but we should replace it. -pub type Symbol = String; - -/// The number that identifies a crate. -pub type CrateNum = usize; - -impl Debug for DefId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("DefId").field("id", &self.0).field("name", &self.name()).finish() - } -} - -impl IndexedVal for DefId { - fn to_val(index: usize) -> Self { - DefId(index) - } - - fn to_index(&self) -> usize { - self.0 - } -} - -/// A list of crate items. -pub type CrateItems = Vec<CrateItem>; - -/// A list of trait decls. -pub type TraitDecls = Vec<TraitDef>; - -/// A list of impl trait decls. -pub type ImplTraitDecls = Vec<ImplDef>; - -/// A list of associated items. -pub type AssocItems = Vec<AssocItem>; - -/// Holds information about a crate. -#[derive(Clone, PartialEq, Eq, Debug, Serialize)] -pub struct Crate { - pub id: CrateNum, - pub name: Symbol, - pub is_local: bool, -} - -impl Crate { - /// The list of foreign modules in this crate. - pub fn foreign_modules(&self) -> Vec<ForeignModuleDef> { - with(|cx| cx.foreign_modules(self.id)) - } - - /// The list of traits declared in this crate. - pub fn trait_decls(&self) -> TraitDecls { - with(|cx| cx.trait_decls(self.id)) - } - - /// The list of trait implementations in this crate. - pub fn trait_impls(&self) -> ImplTraitDecls { - with(|cx| cx.trait_impls(self.id)) - } - - /// Return a list of function definitions from this crate independent on their visibility. - pub fn fn_defs(&self) -> Vec<FnDef> { - with(|cx| cx.crate_functions(self.id)) - } - - /// Return a list of static items defined in this crate independent on their visibility. - pub fn statics(&self) -> Vec<StaticDef> { - with(|cx| cx.crate_statics(self.id)) - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] -pub enum ItemKind { - Fn, - Static, - Const, - Ctor(CtorKind), -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] -pub enum CtorKind { - Const, - Fn, -} - -pub type Filename = String; - -crate_def_with_ty! { - /// Holds information about an item in a crate. - #[derive(Serialize)] - pub CrateItem; -} - -impl CrateItem { - /// This will return the body of an item or panic if it's not available. - pub fn expect_body(&self) -> mir::Body { - with(|cx| cx.mir_body(self.0)) - } - - /// Return the body of an item if available. - pub fn body(&self) -> Option<mir::Body> { - with(|cx| cx.has_body(self.0).then(|| cx.mir_body(self.0))) - } - - /// Check if a body is available for this item. - pub fn has_body(&self) -> bool { - with(|cx| cx.has_body(self.0)) - } - - pub fn span(&self) -> Span { - with(|cx| cx.span_of_an_item(self.0)) - } - - pub fn kind(&self) -> ItemKind { - with(|cx| cx.item_kind(*self)) - } - - pub fn requires_monomorphization(&self) -> bool { - with(|cx| cx.requires_monomorphization(self.0)) - } - - pub fn ty(&self) -> Ty { - with(|cx| cx.def_ty(self.0)) - } - - pub fn is_foreign_item(&self) -> bool { - with(|cx| cx.is_foreign_item(self.0)) - } - - /// Emit MIR for this item body. - pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> { - self.body() - .ok_or_else(|| io::Error::other(format!("No body found for `{}`", self.name())))? - .dump(w, &self.name()) - } -} - -/// Return the function where execution starts if the current -/// crate defines that. This is usually `main`, but could be -/// `start` if the crate is a no-std crate. -pub fn entry_fn() -> Option<CrateItem> { - with(|cx| cx.entry_fn()) -} - -/// Access to the local crate. -pub fn local_crate() -> Crate { - with(|cx| cx.local_crate()) -} - -/// Try to find a crate or crates if multiple crates exist from given name. -pub fn find_crates(name: &str) -> Vec<Crate> { - with(|cx| cx.find_crates(name)) -} - -/// Try to find a crate with the given name. -pub fn external_crates() -> Vec<Crate> { - with(|cx| cx.external_crates()) -} - -/// Retrieve all items in the local crate that have a MIR associated with them. -pub fn all_local_items() -> CrateItems { - with(|cx| cx.all_local_items()) -} - -pub fn all_trait_decls() -> TraitDecls { - with(|cx| cx.all_trait_decls()) -} - -pub fn all_trait_impls() -> ImplTraitDecls { - with(|cx| cx.all_trait_impls()) -} - -/// A type that provides internal information but that can still be used for debug purpose. -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub struct Opaque(String); - -impl std::fmt::Display for Opaque { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl std::fmt::Debug for Opaque { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -pub fn opaque<T: Debug>(value: &T) -> Opaque { - Opaque(format!("{value:?}")) -} - -macro_rules! bridge_impl { - ($name: ident, $ty: ty) => { - impl rustc_smir::bridge::$name<compiler_interface::BridgeTys> for $ty { - fn new(def: stable_mir::DefId) -> Self { - Self(def) - } - } - }; -} - -bridge_impl!(CrateItem, stable_mir::CrateItem); -bridge_impl!(AdtDef, stable_mir::ty::AdtDef); -bridge_impl!(ForeignModuleDef, stable_mir::ty::ForeignModuleDef); -bridge_impl!(ForeignDef, stable_mir::ty::ForeignDef); -bridge_impl!(FnDef, stable_mir::ty::FnDef); -bridge_impl!(ClosureDef, stable_mir::ty::ClosureDef); -bridge_impl!(CoroutineDef, stable_mir::ty::CoroutineDef); -bridge_impl!(CoroutineClosureDef, stable_mir::ty::CoroutineClosureDef); -bridge_impl!(AliasDef, stable_mir::ty::AliasDef); -bridge_impl!(ParamDef, stable_mir::ty::ParamDef); -bridge_impl!(BrNamedDef, stable_mir::ty::BrNamedDef); -bridge_impl!(TraitDef, stable_mir::ty::TraitDef); -bridge_impl!(GenericDef, stable_mir::ty::GenericDef); -bridge_impl!(ConstDef, stable_mir::ty::ConstDef); -bridge_impl!(ImplDef, stable_mir::ty::ImplDef); -bridge_impl!(RegionDef, stable_mir::ty::RegionDef); -bridge_impl!(CoroutineWitnessDef, stable_mir::ty::CoroutineWitnessDef); -bridge_impl!(AssocDef, stable_mir::ty::AssocDef); -bridge_impl!(OpaqueDef, stable_mir::ty::OpaqueDef); -bridge_impl!(StaticDef, stable_mir::mir::mono::StaticDef); - -impl rustc_smir::bridge::Prov<compiler_interface::BridgeTys> for stable_mir::ty::Prov { - fn new(aid: stable_mir::mir::alloc::AllocId) -> Self { - Self(aid) - } -} - -impl rustc_smir::bridge::Allocation<compiler_interface::BridgeTys> for stable_mir::ty::Allocation { - fn new<'tcx>( - bytes: Vec<Option<u8>>, - ptrs: Vec<(usize, rustc_middle::mir::interpret::AllocId)>, - align: u64, - mutability: rustc_middle::mir::Mutability, - tables: &mut Tables<'tcx, compiler_interface::BridgeTys>, - cx: &SmirCtxt<'tcx, compiler_interface::BridgeTys>, - ) -> Self { - Self { - bytes, - provenance: ProvenanceMap { - ptrs: ptrs.iter().map(|(i, aid)| (*i, tables.prov(*aid))).collect(), - }, - align, - mutability: mutability.stable(tables, cx), - } - } -} diff --git a/compiler/rustc_smir/src/stable_mir/target.rs b/compiler/rustc_smir/src/stable_mir/target.rs deleted file mode 100644 index 6cf1e9feb01..00000000000 --- a/compiler/rustc_smir/src/stable_mir/target.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! Provide information about the machine that this is being compiled into. - -use serde::Serialize; -use stable_mir::compiler_interface::with; - -use crate::stable_mir; - -/// The properties of the target machine being compiled into. -#[derive(Clone, PartialEq, Eq, Serialize)] -pub struct MachineInfo { - pub endian: Endian, - pub pointer_width: MachineSize, -} - -impl MachineInfo { - pub fn target() -> MachineInfo { - with(|cx| cx.target_info()) - } - - pub fn target_endianness() -> Endian { - with(|cx| cx.target_info().endian) - } - - pub fn target_pointer_width() -> MachineSize { - with(|cx| cx.target_info().pointer_width) - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Serialize)] -pub enum Endian { - Little, - Big, -} - -/// Represent the size of a component. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] -pub struct MachineSize { - num_bits: usize, -} - -impl MachineSize { - #[inline(always)] - pub fn bytes(self) -> usize { - self.num_bits / 8 - } - - #[inline(always)] - pub fn bits(self) -> usize { - self.num_bits - } - - #[inline(always)] - pub fn from_bits(num_bits: usize) -> MachineSize { - MachineSize { num_bits } - } - - #[inline] - pub fn unsigned_int_max(self) -> Option<u128> { - (self.num_bits <= 128).then(|| u128::MAX >> (128 - self.bits())) - } -} diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs deleted file mode 100644 index 004a7c02234..00000000000 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ /dev/null @@ -1,1656 +0,0 @@ -use std::fmt::{self, Debug, Display, Formatter}; -use std::ops::Range; - -use serde::Serialize; -use stable_mir::abi::{FnAbi, Layout}; -use stable_mir::crate_def::{CrateDef, CrateDefItems, CrateDefType}; -use stable_mir::mir::alloc::{AllocId, read_target_int, read_target_uint}; -use stable_mir::mir::mono::StaticDef; -use stable_mir::target::MachineInfo; -use stable_mir::{Filename, IndexedVal, Opaque}; - -use super::abi::ReprOptions; -use super::mir::{Body, Mutability, Safety}; -use super::{DefId, Error, Symbol, with}; -use crate::stable_mir; - -#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)] -pub struct Ty(usize); - -impl Debug for Ty { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("Ty").field("id", &self.0).field("kind", &self.kind()).finish() - } -} - -/// Constructors for `Ty`. -impl Ty { - /// Create a new type from a given kind. - pub fn from_rigid_kind(kind: RigidTy) -> Ty { - with(|cx| cx.new_rigid_ty(kind)) - } - - /// Create a new array type. - pub fn try_new_array(elem_ty: Ty, size: u64) -> Result<Ty, Error> { - Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, TyConst::try_from_target_usize(size)?))) - } - - /// Create a new array type from Const length. - pub fn new_array_with_const_len(elem_ty: Ty, len: TyConst) -> Ty { - Ty::from_rigid_kind(RigidTy::Array(elem_ty, len)) - } - - /// Create a new pointer type. - pub fn new_ptr(pointee_ty: Ty, mutability: Mutability) -> Ty { - Ty::from_rigid_kind(RigidTy::RawPtr(pointee_ty, mutability)) - } - - /// Create a new reference type. - pub fn new_ref(reg: Region, pointee_ty: Ty, mutability: Mutability) -> Ty { - Ty::from_rigid_kind(RigidTy::Ref(reg, pointee_ty, mutability)) - } - - /// Create a new pointer type. - pub fn new_tuple(tys: &[Ty]) -> Ty { - Ty::from_rigid_kind(RigidTy::Tuple(Vec::from(tys))) - } - - /// Create a new closure type. - pub fn new_closure(def: ClosureDef, args: GenericArgs) -> Ty { - Ty::from_rigid_kind(RigidTy::Closure(def, args)) - } - - /// Create a new coroutine type. - pub fn new_coroutine(def: CoroutineDef, args: GenericArgs, mov: Movability) -> Ty { - Ty::from_rigid_kind(RigidTy::Coroutine(def, args, mov)) - } - - /// Create a new closure type. - pub fn new_coroutine_closure(def: CoroutineClosureDef, args: GenericArgs) -> Ty { - Ty::from_rigid_kind(RigidTy::CoroutineClosure(def, args)) - } - - /// Create a new box type that represents `Box<T>`, for the given inner type `T`. - pub fn new_box(inner_ty: Ty) -> Ty { - with(|cx| cx.new_box_ty(inner_ty)) - } - - /// Create a type representing `usize`. - pub fn usize_ty() -> Ty { - Ty::from_rigid_kind(RigidTy::Uint(UintTy::Usize)) - } - - /// Create a type representing `bool`. - pub fn bool_ty() -> Ty { - Ty::from_rigid_kind(RigidTy::Bool) - } - - /// Create a type representing a signed integer. - pub fn signed_ty(inner: IntTy) -> Ty { - Ty::from_rigid_kind(RigidTy::Int(inner)) - } - - /// Create a type representing an unsigned integer. - pub fn unsigned_ty(inner: UintTy) -> Ty { - Ty::from_rigid_kind(RigidTy::Uint(inner)) - } - - /// Get a type layout. - pub fn layout(self) -> Result<Layout, Error> { - with(|cx| cx.ty_layout(self)) - } -} - -impl Ty { - pub fn kind(&self) -> TyKind { - with(|context| context.ty_kind(*self)) - } -} - -/// Represents a pattern in the type system -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum Pattern { - Range { start: Option<TyConst>, end: Option<TyConst>, include_end: bool }, -} - -/// Represents a constant in the type system -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct TyConst { - pub(crate) kind: TyConstKind, - pub id: TyConstId, -} - -impl TyConst { - pub fn new(kind: TyConstKind, id: TyConstId) -> TyConst { - Self { kind, id } - } - - /// Retrieve the constant kind. - pub fn kind(&self) -> &TyConstKind { - &self.kind - } - - /// Creates an interned usize constant. - pub fn try_from_target_usize(val: u64) -> Result<Self, Error> { - with(|cx| cx.try_new_ty_const_uint(val.into(), UintTy::Usize)) - } - - /// Try to evaluate to a target `usize`. - pub fn eval_target_usize(&self) -> Result<u64, Error> { - with(|cx| cx.eval_target_usize_ty(self)) - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum TyConstKind { - Param(ParamConst), - Bound(DebruijnIndex, BoundVar), - Unevaluated(ConstDef, GenericArgs), - - // FIXME: These should be a valtree - Value(Ty, Allocation), - ZSTValue(Ty), -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] -pub struct TyConstId(usize); - -/// Represents a constant in MIR -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct MirConst { - /// The constant kind. - pub(crate) kind: ConstantKind, - /// The constant type. - pub(crate) ty: Ty, - /// Used for internal tracking of the internal constant. - pub id: MirConstId, -} - -impl MirConst { - /// Build a constant. Note that this should only be used by the compiler. - pub fn new(kind: ConstantKind, ty: Ty, id: MirConstId) -> MirConst { - MirConst { kind, ty, id } - } - - /// Retrieve the constant kind. - pub fn kind(&self) -> &ConstantKind { - &self.kind - } - - /// Get the constant type. - pub fn ty(&self) -> Ty { - self.ty - } - - /// Try to evaluate to a target `usize`. - pub fn eval_target_usize(&self) -> Result<u64, Error> { - with(|cx| cx.eval_target_usize(self)) - } - - /// Create a constant that represents a new zero-sized constant of type T. - /// Fails if the type is not a ZST or if it doesn't have a known size. - pub fn try_new_zero_sized(ty: Ty) -> Result<MirConst, Error> { - with(|cx| cx.try_new_const_zst(ty)) - } - - /// Build a new constant that represents the given string. - /// - /// Note that there is no guarantee today about duplication of the same constant. - /// I.e.: Calling this function multiple times with the same argument may or may not return - /// the same allocation. - pub fn from_str(value: &str) -> MirConst { - with(|cx| cx.new_const_str(value)) - } - - /// Build a new constant that represents the given boolean value. - pub fn from_bool(value: bool) -> MirConst { - with(|cx| cx.new_const_bool(value)) - } - - /// Build a new constant that represents the given unsigned integer. - pub fn try_from_uint(value: u128, uint_ty: UintTy) -> Result<MirConst, Error> { - with(|cx| cx.try_new_const_uint(value, uint_ty)) - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] -pub struct MirConstId(usize); - -type Ident = Opaque; - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct Region { - pub kind: RegionKind, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum RegionKind { - ReEarlyParam(EarlyParamRegion), - ReBound(DebruijnIndex, BoundRegion), - ReStatic, - RePlaceholder(Placeholder<BoundRegion>), - ReErased, -} - -pub(crate) type DebruijnIndex = u32; - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct EarlyParamRegion { - pub index: u32, - pub name: Symbol, -} - -pub(crate) type BoundVar = u32; - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct BoundRegion { - pub var: BoundVar, - pub kind: BoundRegionKind, -} - -pub(crate) type UniverseIndex = u32; - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct Placeholder<T> { - pub universe: UniverseIndex, - pub bound: T, -} - -#[derive(Clone, Copy, PartialEq, Eq, Serialize)] -pub struct Span(usize); - -impl Debug for Span { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("Span") - .field("id", &self.0) - .field("repr", &with(|cx| cx.span_to_string(*self))) - .finish() - } -} - -impl Span { - /// Return filename for diagnostic purposes - pub fn get_filename(&self) -> Filename { - with(|c| c.get_filename(self)) - } - - /// Return lines that correspond to this `Span` - pub fn get_lines(&self) -> LineInfo { - with(|c| c.get_lines(self)) - } - - /// Return the span location to be printed in diagnostic messages. - /// - /// This may leak local file paths and should not be used to build artifacts that may be - /// distributed. - pub fn diagnostic(&self) -> String { - with(|c| c.span_to_string(*self)) - } -} - -#[derive(Clone, Copy, Debug, Serialize)] -/// Information you get from `Span` in a struct form. -/// Line and col start from 1. -pub struct LineInfo { - pub start_line: usize, - pub start_col: usize, - pub end_line: usize, - pub end_col: usize, -} - -impl LineInfo { - pub fn from(lines: (usize, usize, usize, usize)) -> Self { - LineInfo { start_line: lines.0, start_col: lines.1, end_line: lines.2, end_col: lines.3 } - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum TyKind { - RigidTy(RigidTy), - Alias(AliasKind, AliasTy), - Param(ParamTy), - Bound(usize, BoundTy), -} - -impl TyKind { - pub fn rigid(&self) -> Option<&RigidTy> { - if let TyKind::RigidTy(inner) = self { Some(inner) } else { None } - } - - #[inline] - pub fn is_unit(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Tuple(data)) if data.is_empty()) - } - - #[inline] - pub fn is_bool(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Bool)) - } - - #[inline] - pub fn is_char(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Char)) - } - - #[inline] - pub fn is_trait(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Dynamic(_, _, DynKind::Dyn))) - } - - #[inline] - pub fn is_enum(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Enum) - } - - #[inline] - pub fn is_struct(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Struct) - } - - #[inline] - pub fn is_union(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Union) - } - - #[inline] - pub fn is_adt(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Adt(..))) - } - - #[inline] - pub fn is_ref(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Ref(..))) - } - - #[inline] - pub fn is_fn(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::FnDef(..))) - } - - #[inline] - pub fn is_fn_ptr(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::FnPtr(..))) - } - - #[inline] - pub fn is_primitive(&self) -> bool { - matches!( - self, - TyKind::RigidTy( - RigidTy::Bool - | RigidTy::Char - | RigidTy::Int(_) - | RigidTy::Uint(_) - | RigidTy::Float(_) - ) - ) - } - - #[inline] - pub fn is_float(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Float(_))) - } - - #[inline] - pub fn is_integral(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Int(_) | RigidTy::Uint(_))) - } - - #[inline] - pub fn is_numeric(&self) -> bool { - self.is_integral() || self.is_float() - } - - #[inline] - pub fn is_signed(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Int(_))) - } - - #[inline] - pub fn is_str(&self) -> bool { - *self == TyKind::RigidTy(RigidTy::Str) - } - - #[inline] - pub fn is_cstr(&self) -> bool { - let TyKind::RigidTy(RigidTy::Adt(def, _)) = self else { - return false; - }; - with(|cx| cx.adt_is_cstr(*def)) - } - - #[inline] - pub fn is_slice(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Slice(_))) - } - - #[inline] - pub fn is_array(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Array(..))) - } - - #[inline] - pub fn is_mutable_ptr(&self) -> bool { - matches!( - self, - TyKind::RigidTy(RigidTy::RawPtr(_, Mutability::Mut)) - | TyKind::RigidTy(RigidTy::Ref(_, _, Mutability::Mut)) - ) - } - - #[inline] - pub fn is_raw_ptr(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::RawPtr(..))) - } - - /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer). - #[inline] - pub fn is_any_ptr(&self) -> bool { - self.is_ref() || self.is_raw_ptr() || self.is_fn_ptr() - } - - #[inline] - pub fn is_coroutine(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Coroutine(..))) - } - - #[inline] - pub fn is_closure(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Closure(..))) - } - - #[inline] - pub fn is_box(&self) -> bool { - match self { - TyKind::RigidTy(RigidTy::Adt(def, _)) => def.is_box(), - _ => false, - } - } - - #[inline] - pub fn is_simd(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.is_simd()) - } - - pub fn trait_principal(&self) -> Option<Binder<ExistentialTraitRef>> { - if let TyKind::RigidTy(RigidTy::Dynamic(predicates, _, _)) = self { - if let Some(Binder { value: ExistentialPredicate::Trait(trait_ref), bound_vars }) = - predicates.first() - { - Some(Binder { value: trait_ref.clone(), bound_vars: bound_vars.clone() }) - } else { - None - } - } else { - None - } - } - - /// Returns the type of `ty[i]` for builtin types. - pub fn builtin_index(&self) -> Option<Ty> { - match self.rigid()? { - RigidTy::Array(ty, _) | RigidTy::Slice(ty) => Some(*ty), - _ => None, - } - } - - /// Returns the type and mutability of `*ty` for builtin types. - /// - /// The parameter `explicit` indicates if this is an *explicit* dereference. - /// Some types -- notably raw ptrs -- can only be dereferenced explicitly. - pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut> { - match self.rigid()? { - RigidTy::Adt(def, args) if def.is_box() => { - Some(TypeAndMut { ty: *args.0.first()?.ty()?, mutability: Mutability::Not }) - } - RigidTy::Ref(_, ty, mutability) => { - Some(TypeAndMut { ty: *ty, mutability: *mutability }) - } - RigidTy::RawPtr(ty, mutability) if explicit => { - Some(TypeAndMut { ty: *ty, mutability: *mutability }) - } - _ => None, - } - } - - /// Get the function signature for function like types (Fn, FnPtr, and Closure) - pub fn fn_sig(&self) -> Option<PolyFnSig> { - match self { - TyKind::RigidTy(RigidTy::FnDef(def, args)) => Some(with(|cx| cx.fn_sig(*def, args))), - TyKind::RigidTy(RigidTy::FnPtr(sig)) => Some(sig.clone()), - TyKind::RigidTy(RigidTy::Closure(_def, args)) => Some(with(|cx| cx.closure_sig(args))), - _ => None, - } - } - - /// Get the discriminant type for this type. - pub fn discriminant_ty(&self) -> Option<Ty> { - self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty))) - } - - /// Deconstruct a function type if this is one. - pub fn fn_def(&self) -> Option<(FnDef, &GenericArgs)> { - if let TyKind::RigidTy(RigidTy::FnDef(def, args)) = self { - Some((*def, args)) - } else { - None - } - } -} - -pub struct TypeAndMut { - pub ty: Ty, - pub mutability: Mutability, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum RigidTy { - Bool, - Char, - Int(IntTy), - Uint(UintTy), - Float(FloatTy), - Adt(AdtDef, GenericArgs), - Foreign(ForeignDef), - Str, - Array(Ty, TyConst), - Pat(Ty, Pattern), - Slice(Ty), - RawPtr(Ty, Mutability), - Ref(Region, Ty, Mutability), - FnDef(FnDef, GenericArgs), - FnPtr(PolyFnSig), - Closure(ClosureDef, GenericArgs), - // FIXME(stable_mir): Movability here is redundant - Coroutine(CoroutineDef, GenericArgs, Movability), - CoroutineClosure(CoroutineClosureDef, GenericArgs), - Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind), - Never, - Tuple(Vec<Ty>), - CoroutineWitness(CoroutineWitnessDef, GenericArgs), -} - -impl RigidTy { - /// Get the discriminant type for this type. - pub fn discriminant_ty(&self) -> Ty { - with(|cx| cx.rigid_ty_discriminant_ty(self)) - } -} - -impl From<RigidTy> for TyKind { - fn from(value: RigidTy) -> Self { - TyKind::RigidTy(value) - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] -pub enum IntTy { - Isize, - I8, - I16, - I32, - I64, - I128, -} - -impl IntTy { - pub fn num_bytes(self) -> usize { - match self { - IntTy::Isize => MachineInfo::target_pointer_width().bytes(), - IntTy::I8 => 1, - IntTy::I16 => 2, - IntTy::I32 => 4, - IntTy::I64 => 8, - IntTy::I128 => 16, - } - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] -pub enum UintTy { - Usize, - U8, - U16, - U32, - U64, - U128, -} - -impl UintTy { - pub fn num_bytes(self) -> usize { - match self { - UintTy::Usize => MachineInfo::target_pointer_width().bytes(), - UintTy::U8 => 1, - UintTy::U16 => 2, - UintTy::U32 => 4, - UintTy::U64 => 8, - UintTy::U128 => 16, - } - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] -pub enum FloatTy { - F16, - F32, - F64, - F128, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] -pub enum Movability { - Static, - Movable, -} - -crate_def! { - #[derive(Serialize)] - pub ForeignModuleDef; -} - -impl ForeignModuleDef { - pub fn module(&self) -> ForeignModule { - with(|cx| cx.foreign_module(*self)) - } -} - -pub struct ForeignModule { - pub def_id: ForeignModuleDef, - pub abi: Abi, -} - -impl ForeignModule { - pub fn items(&self) -> Vec<ForeignDef> { - with(|cx| cx.foreign_items(self.def_id)) - } -} - -crate_def_with_ty! { - /// Hold information about a ForeignItem in a crate. - #[derive(Serialize)] - pub ForeignDef; -} - -impl ForeignDef { - pub fn kind(&self) -> ForeignItemKind { - with(|cx| cx.foreign_item_kind(*self)) - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] -pub enum ForeignItemKind { - Fn(FnDef), - Static(StaticDef), - Type(Ty), -} - -crate_def_with_ty! { - /// Hold information about a function definition in a crate. - #[derive(Serialize)] - pub FnDef; -} - -impl FnDef { - // Get the function body if available. - pub fn body(&self) -> Option<Body> { - with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0))) - } - - // Check if the function body is available. - pub fn has_body(&self) -> bool { - with(|ctx| ctx.has_body(self.0)) - } - - /// Get the information of the intrinsic if this function is a definition of one. - pub fn as_intrinsic(&self) -> Option<IntrinsicDef> { - with(|cx| cx.intrinsic(self.def_id())) - } - - /// Check if the function is an intrinsic. - #[inline] - pub fn is_intrinsic(&self) -> bool { - self.as_intrinsic().is_some() - } - - /// Get the function signature for this function definition. - pub fn fn_sig(&self) -> PolyFnSig { - let kind = self.ty().kind(); - kind.fn_sig().unwrap() - } -} - -crate_def_with_ty! { - #[derive(Serialize)] - pub IntrinsicDef; -} - -impl IntrinsicDef { - /// Returns the plain name of the intrinsic. - /// e.g., `transmute` for `core::intrinsics::transmute`. - pub fn fn_name(&self) -> Symbol { - with(|cx| cx.intrinsic_name(*self)) - } - - /// Returns whether the intrinsic has no meaningful body and all backends - /// need to shim all calls to it. - pub fn must_be_overridden(&self) -> bool { - with(|cx| !cx.has_body(self.0)) - } -} - -impl From<IntrinsicDef> for FnDef { - fn from(def: IntrinsicDef) -> Self { - FnDef(def.0) - } -} - -crate_def! { - #[derive(Serialize)] - pub ClosureDef; -} - -impl ClosureDef { - /// Retrieves the body of the closure definition. Returns None if the body - /// isn't available. - pub fn body(&self) -> Option<Body> { - with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0))) - } -} - -crate_def! { - #[derive(Serialize)] - pub CoroutineDef; -} - -impl CoroutineDef { - /// Retrieves the body of the coroutine definition. Returns None if the body - /// isn't available. - pub fn body(&self) -> Option<Body> { - with(|cx| cx.has_body(self.0).then(|| cx.mir_body(self.0))) - } - - pub fn discriminant_for_variant(&self, args: &GenericArgs, idx: VariantIdx) -> Discr { - with(|cx| cx.coroutine_discr_for_variant(*self, args, idx)) - } -} - -crate_def! { - #[derive(Serialize)] - pub CoroutineClosureDef; -} - -crate_def! { - #[derive(Serialize)] - pub ParamDef; -} - -crate_def! { - #[derive(Serialize)] - pub BrNamedDef; -} - -crate_def! { - #[derive(Serialize)] - pub AdtDef; -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] -pub enum AdtKind { - Enum, - Union, - Struct, -} - -impl AdtDef { - pub fn kind(&self) -> AdtKind { - with(|cx| cx.adt_kind(*self)) - } - - /// Retrieve the type of this Adt. - pub fn ty(&self) -> Ty { - with(|cx| cx.def_ty(self.0)) - } - - /// Retrieve the type of this Adt by instantiating and normalizing it with the given arguments. - /// - /// This will assume the type can be instantiated with these arguments. - pub fn ty_with_args(&self, args: &GenericArgs) -> Ty { - with(|cx| cx.def_ty_with_args(self.0, args)) - } - - pub fn is_box(&self) -> bool { - with(|cx| cx.adt_is_box(*self)) - } - - pub fn is_simd(&self) -> bool { - with(|cx| cx.adt_is_simd(*self)) - } - - /// The number of variants in this ADT. - pub fn num_variants(&self) -> usize { - with(|cx| cx.adt_variants_len(*self)) - } - - /// Retrieve the variants in this ADT. - pub fn variants(&self) -> Vec<VariantDef> { - self.variants_iter().collect() - } - - /// Iterate over the variants in this ADT. - pub fn variants_iter(&self) -> impl Iterator<Item = VariantDef> { - (0..self.num_variants()) - .map(|idx| VariantDef { idx: VariantIdx::to_val(idx), adt_def: *self }) - } - - pub fn variant(&self, idx: VariantIdx) -> Option<VariantDef> { - (idx.to_index() < self.num_variants()).then_some(VariantDef { idx, adt_def: *self }) - } - - pub fn repr(&self) -> ReprOptions { - with(|cx| cx.adt_repr(*self)) - } - - pub fn discriminant_for_variant(&self, idx: VariantIdx) -> Discr { - with(|cx| cx.adt_discr_for_variant(*self, idx)) - } -} - -pub struct Discr { - pub val: u128, - pub ty: Ty, -} - -/// Definition of a variant, which can be either a struct / union field or an enum variant. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] -pub struct VariantDef { - /// The variant index. - /// - /// ## Warning - /// Do not access this field directly! - pub idx: VariantIdx, - /// The data type where this variant comes from. - /// For now, we use this to retrieve information about the variant itself so we don't need to - /// cache more information. - /// - /// ## Warning - /// Do not access this field directly! - pub adt_def: AdtDef, -} - -impl VariantDef { - pub fn name(&self) -> Symbol { - with(|cx| cx.variant_name(*self)) - } - - /// Retrieve all the fields in this variant. - // We expect user to cache this and use it directly since today it is expensive to generate all - // fields name. - pub fn fields(&self) -> Vec<FieldDef> { - with(|cx| cx.variant_fields(*self)) - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct FieldDef { - /// The field definition. - /// - /// ## Warning - /// Do not access this field directly! This is public for the compiler to have access to it. - pub def: DefId, - - /// The field name. - pub name: Symbol, -} - -impl FieldDef { - /// Retrieve the type of this field instantiating and normalizing it with the given arguments. - /// - /// This will assume the type can be instantiated with these arguments. - pub fn ty_with_args(&self, args: &GenericArgs) -> Ty { - with(|cx| cx.def_ty_with_args(self.def, args)) - } - - /// Retrieve the type of this field. - pub fn ty(&self) -> Ty { - with(|cx| cx.def_ty(self.def)) - } -} - -impl Display for AdtKind { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.write_str(match self { - AdtKind::Enum => "enum", - AdtKind::Union => "union", - AdtKind::Struct => "struct", - }) - } -} - -impl AdtKind { - pub fn is_enum(&self) -> bool { - matches!(self, AdtKind::Enum) - } - - pub fn is_struct(&self) -> bool { - matches!(self, AdtKind::Struct) - } - - pub fn is_union(&self) -> bool { - matches!(self, AdtKind::Union) - } -} - -crate_def! { - #[derive(Serialize)] - pub AliasDef; -} - -crate_def! { - /// A trait's definition. - #[derive(Serialize)] - pub TraitDef; -} - -impl_crate_def_items! { - TraitDef; -} - -impl TraitDef { - pub fn declaration(trait_def: &TraitDef) -> TraitDecl { - with(|cx| cx.trait_decl(trait_def)) - } -} - -crate_def! { - #[derive(Serialize)] - pub GenericDef; -} - -crate_def_with_ty! { - #[derive(Serialize)] - pub ConstDef; -} - -crate_def! { - /// A trait impl definition. - #[derive(Serialize)] - pub ImplDef; -} - -impl_crate_def_items! { - ImplDef; -} - -impl ImplDef { - /// Retrieve information about this implementation. - pub fn trait_impl(&self) -> ImplTrait { - with(|cx| cx.trait_impl(self)) - } -} - -crate_def! { - #[derive(Serialize)] - pub RegionDef; -} - -crate_def! { - #[derive(Serialize)] - pub CoroutineWitnessDef; -} - -/// A list of generic arguments. -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct GenericArgs(pub Vec<GenericArgKind>); - -impl std::ops::Index<ParamTy> for GenericArgs { - type Output = Ty; - - fn index(&self, index: ParamTy) -> &Self::Output { - self.0[index.index as usize].expect_ty() - } -} - -impl std::ops::Index<ParamConst> for GenericArgs { - type Output = TyConst; - - fn index(&self, index: ParamConst) -> &Self::Output { - self.0[index.index as usize].expect_const() - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum GenericArgKind { - Lifetime(Region), - Type(Ty), - Const(TyConst), -} - -impl GenericArgKind { - /// Panic if this generic argument is not a type, otherwise - /// return the type. - #[track_caller] - pub fn expect_ty(&self) -> &Ty { - match self { - GenericArgKind::Type(ty) => ty, - _ => panic!("{self:?}"), - } - } - - /// Panic if this generic argument is not a const, otherwise - /// return the const. - #[track_caller] - pub fn expect_const(&self) -> &TyConst { - match self { - GenericArgKind::Const(c) => c, - _ => panic!("{self:?}"), - } - } - - /// Return the generic argument type if applicable, otherwise return `None`. - pub fn ty(&self) -> Option<&Ty> { - match self { - GenericArgKind::Type(ty) => Some(ty), - _ => None, - } - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum TermKind { - Type(Ty), - Const(TyConst), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum AliasKind { - Projection, - Inherent, - Opaque, - Free, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct AliasTy { - pub def_id: AliasDef, - pub args: GenericArgs, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct AliasTerm { - pub def_id: AliasDef, - pub args: GenericArgs, -} - -pub type PolyFnSig = Binder<FnSig>; - -impl PolyFnSig { - /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. - /// - /// NB: this doesn't handle virtual calls - those should use `Instance::fn_abi` - /// instead, where the instance is an `InstanceKind::Virtual`. - pub fn fn_ptr_abi(self) -> Result<FnAbi, Error> { - with(|cx| cx.fn_ptr_abi(self)) - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct FnSig { - pub inputs_and_output: Vec<Ty>, - pub c_variadic: bool, - pub safety: Safety, - pub abi: Abi, -} - -impl FnSig { - pub fn output(&self) -> Ty { - self.inputs_and_output[self.inputs_and_output.len() - 1] - } - - pub fn inputs(&self) -> &[Ty] { - &self.inputs_and_output[..self.inputs_and_output.len() - 1] - } -} - -#[derive(Clone, PartialEq, Eq, Debug, Serialize)] -pub enum Abi { - Rust, - C { unwind: bool }, - Cdecl { unwind: bool }, - Stdcall { unwind: bool }, - Fastcall { unwind: bool }, - Vectorcall { unwind: bool }, - Thiscall { unwind: bool }, - Aapcs { unwind: bool }, - Win64 { unwind: bool }, - SysV64 { unwind: bool }, - PtxKernel, - Msp430Interrupt, - X86Interrupt, - GpuKernel, - EfiApi, - AvrInterrupt, - AvrNonBlockingInterrupt, - CCmseNonSecureCall, - CCmseNonSecureEntry, - System { unwind: bool }, - RustCall, - Unadjusted, - RustCold, - RiscvInterruptM, - RiscvInterruptS, - RustInvalid, - Custom, -} - -/// A binder represents a possibly generic type and its bound vars. -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct Binder<T> { - pub value: T, - pub bound_vars: Vec<BoundVariableKind>, -} - -impl<T> Binder<T> { - /// Create a new binder with the given bound vars. - pub fn bind_with_vars(value: T, bound_vars: Vec<BoundVariableKind>) -> Self { - Binder { value, bound_vars } - } - - /// Create a new binder with no bounded variable. - pub fn dummy(value: T) -> Self { - Binder { value, bound_vars: vec![] } - } - - pub fn skip_binder(self) -> T { - self.value - } - - pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U> - where - F: FnOnce(&T) -> U, - { - let Binder { value, bound_vars } = self; - let new_value = f(value); - Binder { value: new_value, bound_vars: bound_vars.clone() } - } - - pub fn map_bound<F, U>(self, f: F) -> Binder<U> - where - F: FnOnce(T) -> U, - { - let Binder { value, bound_vars } = self; - let new_value = f(value); - Binder { value: new_value, bound_vars } - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct EarlyBinder<T> { - pub value: T, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum BoundVariableKind { - Ty(BoundTyKind), - Region(BoundRegionKind), - Const, -} - -#[derive(Clone, PartialEq, Eq, Debug, Serialize)] -pub enum BoundTyKind { - Anon, - Param(ParamDef, String), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum BoundRegionKind { - BrAnon, - BrNamed(BrNamedDef, String), - BrEnv, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum DynKind { - Dyn, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum ExistentialPredicate { - Trait(ExistentialTraitRef), - Projection(ExistentialProjection), - AutoTrait(TraitDef), -} - -/// An existential reference to a trait where `Self` is not included. -/// -/// The `generic_args` will include any other known argument. -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct ExistentialTraitRef { - pub def_id: TraitDef, - pub generic_args: GenericArgs, -} - -impl Binder<ExistentialTraitRef> { - pub fn with_self_ty(&self, self_ty: Ty) -> Binder<TraitRef> { - self.map_bound_ref(|trait_ref| trait_ref.with_self_ty(self_ty)) - } -} - -impl ExistentialTraitRef { - pub fn with_self_ty(&self, self_ty: Ty) -> TraitRef { - TraitRef::new(self.def_id, self_ty, &self.generic_args) - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct ExistentialProjection { - pub def_id: TraitDef, - pub generic_args: GenericArgs, - pub term: TermKind, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct ParamTy { - pub index: u32, - pub name: String, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct BoundTy { - pub var: usize, - pub kind: BoundTyKind, -} - -pub type Bytes = Vec<Option<u8>>; - -/// Size in bytes. -pub type Size = usize; - -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] -pub struct Prov(pub AllocId); - -pub type Align = u64; -pub type Promoted = u32; -pub type InitMaskMaterialized = Vec<u64>; - -/// Stores the provenance information of pointers stored in memory. -#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)] -pub struct ProvenanceMap { - /// Provenance in this map applies from the given offset for an entire pointer-size worth of - /// bytes. Two entries in this map are always at least a pointer size apart. - pub ptrs: Vec<(Size, Prov)>, -} - -#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)] -pub struct Allocation { - pub bytes: Bytes, - pub provenance: ProvenanceMap, - pub align: Align, - pub mutability: Mutability, -} - -impl Allocation { - /// Get a vector of bytes for an Allocation that has been fully initialized - pub fn raw_bytes(&self) -> Result<Vec<u8>, Error> { - self.bytes - .iter() - .copied() - .collect::<Option<Vec<_>>>() - .ok_or_else(|| error!("Found uninitialized bytes: `{:?}`", self.bytes)) - } - - /// Read a uint value from the specified range. - pub fn read_partial_uint(&self, range: Range<usize>) -> Result<u128, Error> { - if range.end - range.start > 16 { - return Err(error!("Allocation is bigger than largest integer")); - } - if range.end > self.bytes.len() { - return Err(error!( - "Range is out of bounds. Allocation length is `{}`, but requested range `{:?}`", - self.bytes.len(), - range - )); - } - let raw = self.bytes[range] - .iter() - .copied() - .collect::<Option<Vec<_>>>() - .ok_or_else(|| error!("Found uninitialized bytes: `{:?}`", self.bytes))?; - read_target_uint(&raw) - } - - /// Read this allocation and try to convert it to an unassigned integer. - pub fn read_uint(&self) -> Result<u128, Error> { - if self.bytes.len() > 16 { - return Err(error!("Allocation is bigger than largest integer")); - } - let raw = self.raw_bytes()?; - read_target_uint(&raw) - } - - /// Read this allocation and try to convert it to a signed integer. - pub fn read_int(&self) -> Result<i128, Error> { - if self.bytes.len() > 16 { - return Err(error!("Allocation is bigger than largest integer")); - } - let raw = self.raw_bytes()?; - read_target_int(&raw) - } - - /// Read this allocation and try to convert it to a boolean. - pub fn read_bool(&self) -> Result<bool, Error> { - match self.read_int()? { - 0 => Ok(false), - 1 => Ok(true), - val => Err(error!("Unexpected value for bool: `{val}`")), - } - } - - /// Read this allocation as a pointer and return whether it represents a `null` pointer. - pub fn is_null(&self) -> Result<bool, Error> { - let len = self.bytes.len(); - let ptr_len = MachineInfo::target_pointer_width().bytes(); - if len != ptr_len { - return Err(error!("Expected width of pointer (`{ptr_len}`), but found: `{len}`")); - } - Ok(self.read_uint()? == 0 && self.provenance.ptrs.is_empty()) - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum ConstantKind { - Ty(TyConst), - Allocated(Allocation), - Unevaluated(UnevaluatedConst), - Param(ParamConst), - /// Store ZST constants. - /// We have to special handle these constants since its type might be generic. - ZeroSized, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct ParamConst { - pub index: u32, - pub name: String, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct UnevaluatedConst { - pub def: ConstDef, - pub args: GenericArgs, - pub promoted: Option<Promoted>, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] -pub enum TraitSpecializationKind { - None, - Marker, - AlwaysApplicable, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct TraitDecl { - pub def_id: TraitDef, - pub safety: Safety, - pub paren_sugar: bool, - pub has_auto_impl: bool, - pub is_marker: bool, - pub is_coinductive: bool, - pub skip_array_during_method_dispatch: bool, - pub skip_boxed_slice_during_method_dispatch: bool, - pub specialization_kind: TraitSpecializationKind, - pub must_implement_one_of: Option<Vec<Ident>>, - pub implement_via_object: bool, - pub deny_explicit_impl: bool, -} - -impl TraitDecl { - pub fn generics_of(&self) -> Generics { - with(|cx| cx.generics_of(self.def_id.0)) - } - - pub fn predicates_of(&self) -> GenericPredicates { - with(|cx| cx.predicates_of(self.def_id.0)) - } - - pub fn explicit_predicates_of(&self) -> GenericPredicates { - with(|cx| cx.explicit_predicates_of(self.def_id.0)) - } -} - -pub type ImplTrait = EarlyBinder<TraitRef>; - -/// A complete reference to a trait, i.e., one where `Self` is known. -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct TraitRef { - pub def_id: TraitDef, - /// The generic arguments for this definition. - /// The first element must always be type, and it represents `Self`. - args: GenericArgs, -} - -impl TraitRef { - pub fn new(def_id: TraitDef, self_ty: Ty, gen_args: &GenericArgs) -> TraitRef { - let mut args = vec![GenericArgKind::Type(self_ty)]; - args.extend_from_slice(&gen_args.0); - TraitRef { def_id, args: GenericArgs(args) } - } - - pub fn try_new(def_id: TraitDef, args: GenericArgs) -> Result<TraitRef, ()> { - match &args.0[..] { - [GenericArgKind::Type(_), ..] => Ok(TraitRef { def_id, args }), - _ => Err(()), - } - } - - pub fn args(&self) -> &GenericArgs { - &self.args - } - - pub fn self_ty(&self) -> Ty { - let GenericArgKind::Type(self_ty) = self.args.0[0] else { - panic!("Self must be a type, but found: {:?}", self.args.0[0]) - }; - self_ty - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct Generics { - pub parent: Option<GenericDef>, - pub parent_count: usize, - pub params: Vec<GenericParamDef>, - pub param_def_id_to_index: Vec<(GenericDef, u32)>, - pub has_self: bool, - pub has_late_bound_regions: Option<Span>, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum GenericParamDefKind { - Lifetime, - Type { has_default: bool, synthetic: bool }, - Const { has_default: bool }, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct GenericParamDef { - pub name: super::Symbol, - pub def_id: GenericDef, - pub index: u32, - pub pure_wrt_drop: bool, - pub kind: GenericParamDefKind, -} - -pub struct GenericPredicates { - pub parent: Option<TraitDef>, - pub predicates: Vec<(PredicateKind, Span)>, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum PredicateKind { - Clause(ClauseKind), - DynCompatible(TraitDef), - SubType(SubtypePredicate), - Coerce(CoercePredicate), - ConstEquate(TyConst, TyConst), - Ambiguous, - AliasRelate(TermKind, TermKind, AliasRelationDirection), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum ClauseKind { - Trait(TraitPredicate), - RegionOutlives(RegionOutlivesPredicate), - TypeOutlives(TypeOutlivesPredicate), - Projection(ProjectionPredicate), - ConstArgHasType(TyConst, Ty), - WellFormed(TermKind), - ConstEvaluatable(TyConst), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum ClosureKind { - Fn, - FnMut, - FnOnce, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct SubtypePredicate { - pub a: Ty, - pub b: Ty, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct CoercePredicate { - pub a: Ty, - pub b: Ty, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum AliasRelationDirection { - Equate, - Subtype, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct TraitPredicate { - pub trait_ref: TraitRef, - pub polarity: PredicatePolarity, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct OutlivesPredicate<A, B>(pub A, pub B); - -pub type RegionOutlivesPredicate = OutlivesPredicate<Region, Region>; -pub type TypeOutlivesPredicate = OutlivesPredicate<Ty, Region>; - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct ProjectionPredicate { - pub projection_term: AliasTerm, - pub term: TermKind, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum ImplPolarity { - Positive, - Negative, - Reservation, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum PredicatePolarity { - Positive, - Negative, -} - -macro_rules! index_impl { - ($name:ident) => { - impl stable_mir::IndexedVal for $name { - fn to_val(index: usize) -> Self { - $name(index) - } - fn to_index(&self) -> usize { - self.0 - } - } - }; -} - -index_impl!(TyConstId); -index_impl!(MirConstId); -index_impl!(Ty); -index_impl!(Span); - -/// The source-order index of a variant in a type. -/// -/// For example, in the following types, -/// ```ignore(illustrative) -/// enum Demo1 { -/// Variant0 { a: bool, b: i32 }, -/// Variant1 { c: u8, d: u64 }, -/// } -/// struct Demo2 { e: u8, f: u16, g: u8 } -/// ``` -/// `a` is in the variant with the `VariantIdx` of `0`, -/// `c` is in the variant with the `VariantIdx` of `1`, and -/// `g` is in the variant with the `VariantIdx` of `0`. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] -pub struct VariantIdx(usize); - -index_impl!(VariantIdx); - -crate_def! { - /// Hold information about an Opaque definition, particularly useful in `RPITIT`. - #[derive(Serialize)] - pub OpaqueDef; -} - -crate_def! { - #[derive(Serialize)] - pub AssocDef; -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub struct AssocItem { - pub def_id: AssocDef, - pub kind: AssocKind, - pub container: AssocItemContainer, - - /// If this is an item in an impl of a trait then this is the `DefId` of - /// the associated item on the trait that this implements. - pub trait_item_def_id: Option<AssocDef>, -} - -#[derive(Clone, PartialEq, Debug, Eq, Serialize)] -pub enum AssocTypeData { - Normal(Symbol), - /// The associated type comes from an RPITIT. It has no name, and the - /// `ImplTraitInTraitData` provides additional information about its - /// source. - Rpitit(ImplTraitInTraitData), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum AssocKind { - Const { name: Symbol }, - Fn { name: Symbol, has_self: bool }, - Type { data: AssocTypeData }, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum AssocItemContainer { - Trait, - Impl, -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] -pub enum ImplTraitInTraitData { - Trait { fn_def_id: FnDef, opaque_def_id: OpaqueDef }, - Impl { fn_def_id: FnDef }, -} - -impl AssocItem { - pub fn is_impl_trait_in_trait(&self) -> bool { - matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) }) - } -} diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs deleted file mode 100644 index 37c93af392e..00000000000 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs +++ /dev/null @@ -1,824 +0,0 @@ -//! 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 rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy}; -use rustc_smir::Tables; -use stable_mir::abi::Layout; -use stable_mir::compiler_interface::BridgeTys; -use stable_mir::mir::alloc::AllocId; -use stable_mir::mir::mono::{Instance, MonoItem, StaticDef}; -use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, RawPtrKind, Safety, UnOp}; -use stable_mir::ty::{ - Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, DynKind, - ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, - GenericArgKind, GenericArgs, IntTy, MirConst, Movability, Pattern, Region, RigidTy, Span, - TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx, -}; -use stable_mir::unstable::{InternalCx, RustcInternal}; -use stable_mir::{CrateItem, CrateNum, DefId, IndexedVal}; - -use crate::{rustc_smir, stable_mir}; - -impl RustcInternal for CrateItem { - type T<'tcx> = rustc_span::def_id::DefId; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - self.0.internal(tables, tcx) - } -} - -impl RustcInternal for CrateNum { - type T<'tcx> = rustc_span::def_id::CrateNum; - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - rustc_span::def_id::CrateNum::from_usize(*self) - } -} - -impl RustcInternal for DefId { - type T<'tcx> = rustc_span::def_id::DefId; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - tcx.lift(tables.def_ids[*self]).unwrap() - } -} - -impl RustcInternal for GenericArgs { - type T<'tcx> = rustc_ty::GenericArgsRef<'tcx>; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - InternalCx::mk_args_from_iter(tcx, self.0.iter().map(|arg| arg.internal(tables, tcx))) - } -} - -impl RustcInternal for GenericArgKind { - type T<'tcx> = rustc_ty::GenericArg<'tcx>; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - let arg: rustc_ty::GenericArg<'tcx> = match self { - GenericArgKind::Lifetime(reg) => reg.internal(tables, tcx).into(), - GenericArgKind::Type(ty) => ty.internal(tables, tcx).into(), - GenericArgKind::Const(cnst) => cnst.internal(tables, tcx).into(), - }; - tcx.lift(arg).unwrap() - } -} - -impl RustcInternal for Region { - type T<'tcx> = rustc_ty::Region<'tcx>; - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - // Cannot recover region. Use erased for now. - tcx.lifetimes_re_erased() - } -} - -impl RustcInternal for Ty { - type T<'tcx> = InternalTy<'tcx>; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - tcx.lift(tables.types[*self]).unwrap() - } -} - -impl RustcInternal for TyConst { - type T<'tcx> = InternalConst<'tcx>; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - tcx.lift(tables.ty_consts[self.id]).unwrap() - } -} - -impl RustcInternal for Pattern { - type T<'tcx> = rustc_ty::Pattern<'tcx>; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - tcx.mk_pat(match self { - Pattern::Range { start, end, include_end: _ } => rustc_ty::PatternKind::Range { - start: start.as_ref().unwrap().internal(tables, tcx), - end: end.as_ref().unwrap().internal(tables, tcx), - }, - }) - } -} - -impl RustcInternal for RigidTy { - type T<'tcx> = rustc_ty::TyKind<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - RigidTy::Bool => rustc_ty::TyKind::Bool, - RigidTy::Char => rustc_ty::TyKind::Char, - RigidTy::Int(int_ty) => rustc_ty::TyKind::Int(int_ty.internal(tables, tcx)), - RigidTy::Uint(uint_ty) => rustc_ty::TyKind::Uint(uint_ty.internal(tables, tcx)), - RigidTy::Float(float_ty) => rustc_ty::TyKind::Float(float_ty.internal(tables, tcx)), - RigidTy::Never => rustc_ty::TyKind::Never, - RigidTy::Array(ty, cnst) => { - rustc_ty::TyKind::Array(ty.internal(tables, tcx), cnst.internal(tables, tcx)) - } - RigidTy::Pat(ty, pat) => { - rustc_ty::TyKind::Pat(ty.internal(tables, tcx), pat.internal(tables, tcx)) - } - RigidTy::Adt(def, args) => { - rustc_ty::TyKind::Adt(def.internal(tables, tcx), args.internal(tables, tcx)) - } - RigidTy::Str => rustc_ty::TyKind::Str, - RigidTy::Slice(ty) => rustc_ty::TyKind::Slice(ty.internal(tables, tcx)), - RigidTy::RawPtr(ty, mutability) => { - rustc_ty::TyKind::RawPtr(ty.internal(tables, tcx), mutability.internal(tables, tcx)) - } - RigidTy::Ref(region, ty, mutability) => rustc_ty::TyKind::Ref( - region.internal(tables, tcx), - ty.internal(tables, tcx), - mutability.internal(tables, tcx), - ), - RigidTy::Foreign(def) => rustc_ty::TyKind::Foreign(def.0.internal(tables, tcx)), - RigidTy::FnDef(def, args) => { - rustc_ty::TyKind::FnDef(def.0.internal(tables, tcx), args.internal(tables, tcx)) - } - RigidTy::FnPtr(sig) => { - let (sig_tys, hdr) = sig.internal(tables, tcx).split(); - rustc_ty::TyKind::FnPtr(sig_tys, hdr) - } - RigidTy::Closure(def, args) => { - rustc_ty::TyKind::Closure(def.0.internal(tables, tcx), args.internal(tables, tcx)) - } - RigidTy::Coroutine(def, args, _mov) => { - rustc_ty::TyKind::Coroutine(def.0.internal(tables, tcx), args.internal(tables, tcx)) - } - RigidTy::CoroutineClosure(def, args) => rustc_ty::TyKind::CoroutineClosure( - def.0.internal(tables, tcx), - args.internal(tables, tcx), - ), - RigidTy::CoroutineWitness(def, args) => rustc_ty::TyKind::CoroutineWitness( - def.0.internal(tables, tcx), - args.internal(tables, tcx), - ), - RigidTy::Dynamic(predicate, region, dyn_kind) => rustc_ty::TyKind::Dynamic( - tcx.mk_poly_existential_predicates(&predicate.internal(tables, tcx)), - region.internal(tables, tcx), - dyn_kind.internal(tables, tcx), - ), - RigidTy::Tuple(tys) => { - rustc_ty::TyKind::Tuple(tcx.mk_type_list(&tys.internal(tables, tcx))) - } - } - } -} - -impl RustcInternal for IntTy { - type T<'tcx> = rustc_ty::IntTy; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - IntTy::Isize => rustc_ty::IntTy::Isize, - IntTy::I8 => rustc_ty::IntTy::I8, - IntTy::I16 => rustc_ty::IntTy::I16, - IntTy::I32 => rustc_ty::IntTy::I32, - IntTy::I64 => rustc_ty::IntTy::I64, - IntTy::I128 => rustc_ty::IntTy::I128, - } - } -} - -impl RustcInternal for UintTy { - type T<'tcx> = rustc_ty::UintTy; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - UintTy::Usize => rustc_ty::UintTy::Usize, - UintTy::U8 => rustc_ty::UintTy::U8, - UintTy::U16 => rustc_ty::UintTy::U16, - UintTy::U32 => rustc_ty::UintTy::U32, - UintTy::U64 => rustc_ty::UintTy::U64, - UintTy::U128 => rustc_ty::UintTy::U128, - } - } -} - -impl RustcInternal for FloatTy { - type T<'tcx> = rustc_ty::FloatTy; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - FloatTy::F16 => rustc_ty::FloatTy::F16, - FloatTy::F32 => rustc_ty::FloatTy::F32, - FloatTy::F64 => rustc_ty::FloatTy::F64, - FloatTy::F128 => rustc_ty::FloatTy::F128, - } - } -} - -impl RustcInternal for Mutability { - type T<'tcx> = rustc_ty::Mutability; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - Mutability::Not => rustc_ty::Mutability::Not, - Mutability::Mut => rustc_ty::Mutability::Mut, - } - } -} - -impl RustcInternal for Movability { - type T<'tcx> = rustc_ty::Movability; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - Movability::Static => rustc_ty::Movability::Static, - Movability::Movable => rustc_ty::Movability::Movable, - } - } -} - -impl RustcInternal for RawPtrKind { - type T<'tcx> = rustc_middle::mir::RawPtrKind; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - RawPtrKind::Mut => rustc_middle::mir::RawPtrKind::Mut, - RawPtrKind::Const => rustc_middle::mir::RawPtrKind::Const, - RawPtrKind::FakeForPtrMetadata => rustc_middle::mir::RawPtrKind::FakeForPtrMetadata, - } - } -} - -impl RustcInternal for FnSig { - type T<'tcx> = rustc_ty::FnSig<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - tcx.lift(rustc_ty::FnSig { - inputs_and_output: tcx.mk_type_list(&self.inputs_and_output.internal(tables, tcx)), - c_variadic: self.c_variadic, - safety: self.safety.internal(tables, tcx), - abi: self.abi.internal(tables, tcx), - }) - .unwrap() - } -} - -impl RustcInternal for VariantIdx { - type T<'tcx> = rustc_abi::VariantIdx; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - rustc_abi::VariantIdx::from(self.to_index()) - } -} - -impl RustcInternal for VariantDef { - type T<'tcx> = &'tcx rustc_ty::VariantDef; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - self.adt_def.internal(tables, tcx).variant(self.idx.internal(tables, tcx)) - } -} - -impl RustcInternal for MirConst { - type T<'tcx> = rustc_middle::mir::Const<'tcx>; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - let constant = tables.mir_consts[self.id]; - match constant { - rustc_middle::mir::Const::Ty(ty, ct) => { - rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap(), tcx.lift(ct).unwrap()) - } - rustc_middle::mir::Const::Unevaluated(uneval, ty) => { - rustc_middle::mir::Const::Unevaluated( - tcx.lift(uneval).unwrap(), - tcx.lift(ty).unwrap(), - ) - } - rustc_middle::mir::Const::Val(const_val, ty) => { - rustc_middle::mir::Const::Val(tcx.lift(const_val).unwrap(), tcx.lift(ty).unwrap()) - } - } - } -} - -impl RustcInternal for MonoItem { - type T<'tcx> = rustc_middle::mir::mono::MonoItem<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - use rustc_middle::mir::mono as rustc_mono; - match self { - MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables, tcx)), - MonoItem::Static(def) => rustc_mono::MonoItem::Static(def.internal(tables, tcx)), - MonoItem::GlobalAsm(_) => { - unimplemented!() - } - } - } -} - -impl RustcInternal for Instance { - type T<'tcx> = rustc_ty::Instance<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - tcx.lift(tables.instances[self.def]).unwrap() - } -} - -impl RustcInternal for StaticDef { - type T<'tcx> = rustc_span::def_id::DefId; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - self.0.internal(tables, tcx) - } -} - -#[allow(rustc::usage_of_qualified_ty)] -impl<T> RustcInternal for Binder<T> -where - T: RustcInternal, - for<'tcx> T::T<'tcx>: rustc_ty::TypeVisitable<rustc_ty::TyCtxt<'tcx>>, -{ - type T<'tcx> = rustc_ty::Binder<'tcx, T::T<'tcx>>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - rustc_ty::Binder::bind_with_vars( - self.value.internal(tables, tcx), - tcx.mk_bound_variable_kinds_from_iter( - self.bound_vars.iter().map(|bound| bound.internal(tables, tcx)), - ), - ) - } -} - -impl RustcInternal for BoundVariableKind { - type T<'tcx> = rustc_ty::BoundVariableKind; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - BoundVariableKind::Ty(kind) => rustc_ty::BoundVariableKind::Ty(match kind { - BoundTyKind::Anon => rustc_ty::BoundTyKind::Anon, - BoundTyKind::Param(def, _symbol) => { - rustc_ty::BoundTyKind::Param(def.0.internal(tables, tcx)) - } - }), - BoundVariableKind::Region(kind) => rustc_ty::BoundVariableKind::Region(match kind { - BoundRegionKind::BrAnon => rustc_ty::BoundRegionKind::Anon, - BoundRegionKind::BrNamed(def, _symbol) => { - rustc_ty::BoundRegionKind::Named(def.0.internal(tables, tcx)) - } - BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::ClosureEnv, - }), - BoundVariableKind::Const => rustc_ty::BoundVariableKind::Const, - } - } -} - -impl RustcInternal for DynKind { - type T<'tcx> = rustc_ty::DynKind; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - DynKind::Dyn => rustc_ty::DynKind::Dyn, - } - } -} - -impl RustcInternal for ExistentialPredicate { - type T<'tcx> = rustc_ty::ExistentialPredicate<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - ExistentialPredicate::Trait(trait_ref) => { - rustc_ty::ExistentialPredicate::Trait(trait_ref.internal(tables, tcx)) - } - ExistentialPredicate::Projection(proj) => { - rustc_ty::ExistentialPredicate::Projection(proj.internal(tables, tcx)) - } - ExistentialPredicate::AutoTrait(trait_def) => { - rustc_ty::ExistentialPredicate::AutoTrait(trait_def.0.internal(tables, tcx)) - } - } - } -} - -impl RustcInternal for ExistentialProjection { - type T<'tcx> = rustc_ty::ExistentialProjection<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - use rustc_smir::context::SmirExistentialProjection; - tcx.new_from_args( - self.def_id.0.internal(tables, tcx), - self.generic_args.internal(tables, tcx), - self.term.internal(tables, tcx), - ) - } -} - -impl RustcInternal for TermKind { - type T<'tcx> = rustc_ty::Term<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - TermKind::Type(ty) => ty.internal(tables, tcx).into(), - TermKind::Const(cnst) => cnst.internal(tables, tcx).into(), - } - } -} - -impl RustcInternal for ExistentialTraitRef { - type T<'tcx> = rustc_ty::ExistentialTraitRef<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - use rustc_smir::context::SmirExistentialTraitRef; - tcx.new_from_args( - self.def_id.0.internal(tables, tcx), - self.generic_args.internal(tables, tcx), - ) - } -} - -impl RustcInternal for TraitRef { - type T<'tcx> = rustc_ty::TraitRef<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - use rustc_smir::context::SmirTraitRef; - tcx.new_from_args(self.def_id.0.internal(tables, tcx), self.args().internal(tables, tcx)) - } -} - -impl RustcInternal for AllocId { - type T<'tcx> = rustc_middle::mir::interpret::AllocId; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - tcx.lift(tables.alloc_ids[*self]).unwrap() - } -} - -impl RustcInternal for ClosureKind { - type T<'tcx> = rustc_ty::ClosureKind; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - ClosureKind::Fn => rustc_ty::ClosureKind::Fn, - ClosureKind::FnMut => rustc_ty::ClosureKind::FnMut, - ClosureKind::FnOnce => rustc_ty::ClosureKind::FnOnce, - } - } -} - -impl RustcInternal for AdtDef { - type T<'tcx> = rustc_ty::AdtDef<'tcx>; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - InternalCx::adt_def(tcx, self.0.internal(tables, tcx)) - } -} - -impl RustcInternal for Abi { - type T<'tcx> = rustc_abi::ExternAbi; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match *self { - Abi::Rust => rustc_abi::ExternAbi::Rust, - Abi::C { unwind } => rustc_abi::ExternAbi::C { unwind }, - Abi::Cdecl { unwind } => rustc_abi::ExternAbi::Cdecl { unwind }, - Abi::Stdcall { unwind } => rustc_abi::ExternAbi::Stdcall { unwind }, - Abi::Fastcall { unwind } => rustc_abi::ExternAbi::Fastcall { unwind }, - Abi::Vectorcall { unwind } => rustc_abi::ExternAbi::Vectorcall { unwind }, - Abi::Thiscall { unwind } => rustc_abi::ExternAbi::Thiscall { unwind }, - Abi::Aapcs { unwind } => rustc_abi::ExternAbi::Aapcs { unwind }, - Abi::CCmseNonSecureCall => rustc_abi::ExternAbi::CmseNonSecureCall, - Abi::CCmseNonSecureEntry => rustc_abi::ExternAbi::CmseNonSecureEntry, - Abi::Win64 { unwind } => rustc_abi::ExternAbi::Win64 { unwind }, - Abi::SysV64 { unwind } => rustc_abi::ExternAbi::SysV64 { unwind }, - Abi::PtxKernel => rustc_abi::ExternAbi::PtxKernel, - Abi::Msp430Interrupt => rustc_abi::ExternAbi::Msp430Interrupt, - Abi::X86Interrupt => rustc_abi::ExternAbi::X86Interrupt, - Abi::GpuKernel => rustc_abi::ExternAbi::GpuKernel, - Abi::EfiApi => rustc_abi::ExternAbi::EfiApi, - Abi::AvrInterrupt => rustc_abi::ExternAbi::AvrInterrupt, - Abi::AvrNonBlockingInterrupt => rustc_abi::ExternAbi::AvrNonBlockingInterrupt, - Abi::System { unwind } => rustc_abi::ExternAbi::System { unwind }, - Abi::RustCall => rustc_abi::ExternAbi::RustCall, - Abi::Unadjusted => rustc_abi::ExternAbi::Unadjusted, - Abi::RustCold => rustc_abi::ExternAbi::RustCold, - Abi::RustInvalid => rustc_abi::ExternAbi::RustInvalid, - Abi::RiscvInterruptM => rustc_abi::ExternAbi::RiscvInterruptM, - Abi::RiscvInterruptS => rustc_abi::ExternAbi::RiscvInterruptS, - Abi::Custom => rustc_abi::ExternAbi::Custom, - } - } -} - -impl RustcInternal for Safety { - type T<'tcx> = rustc_hir::Safety; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - Safety::Unsafe => rustc_hir::Safety::Unsafe, - Safety::Safe => rustc_hir::Safety::Safe, - } - } -} -impl RustcInternal for Span { - type T<'tcx> = rustc_span::Span; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - tables.spans[*self] - } -} - -impl RustcInternal for Layout { - type T<'tcx> = rustc_abi::Layout<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - tcx.lift(tables.layouts[*self]).unwrap() - } -} - -impl RustcInternal for Place { - type T<'tcx> = rustc_middle::mir::Place<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - rustc_middle::mir::Place { - local: rustc_middle::mir::Local::from_usize(self.local), - projection: tcx.mk_place_elems(&self.projection.internal(tables, tcx)), - } - } -} - -impl RustcInternal for ProjectionElem { - type T<'tcx> = rustc_middle::mir::PlaceElem<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - ProjectionElem::Deref => rustc_middle::mir::PlaceElem::Deref, - ProjectionElem::Field(idx, ty) => { - rustc_middle::mir::PlaceElem::Field((*idx).into(), ty.internal(tables, tcx)) - } - ProjectionElem::Index(idx) => rustc_middle::mir::PlaceElem::Index((*idx).into()), - ProjectionElem::ConstantIndex { offset, min_length, from_end } => { - rustc_middle::mir::PlaceElem::ConstantIndex { - offset: *offset, - min_length: *min_length, - from_end: *from_end, - } - } - ProjectionElem::Subslice { from, to, from_end } => { - rustc_middle::mir::PlaceElem::Subslice { from: *from, to: *to, from_end: *from_end } - } - ProjectionElem::Downcast(idx) => { - rustc_middle::mir::PlaceElem::Downcast(None, idx.internal(tables, tcx)) - } - ProjectionElem::OpaqueCast(ty) => { - rustc_middle::mir::PlaceElem::OpaqueCast(ty.internal(tables, tcx)) - } - ProjectionElem::Subtype(ty) => { - rustc_middle::mir::PlaceElem::Subtype(ty.internal(tables, tcx)) - } - } - } -} - -impl RustcInternal for BinOp { - type T<'tcx> = rustc_middle::mir::BinOp; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - BinOp::Add => rustc_middle::mir::BinOp::Add, - BinOp::AddUnchecked => rustc_middle::mir::BinOp::AddUnchecked, - BinOp::Sub => rustc_middle::mir::BinOp::Sub, - BinOp::SubUnchecked => rustc_middle::mir::BinOp::SubUnchecked, - BinOp::Mul => rustc_middle::mir::BinOp::Mul, - BinOp::MulUnchecked => rustc_middle::mir::BinOp::MulUnchecked, - BinOp::Div => rustc_middle::mir::BinOp::Div, - BinOp::Rem => rustc_middle::mir::BinOp::Rem, - BinOp::BitXor => rustc_middle::mir::BinOp::BitXor, - BinOp::BitAnd => rustc_middle::mir::BinOp::BitAnd, - BinOp::BitOr => rustc_middle::mir::BinOp::BitOr, - BinOp::Shl => rustc_middle::mir::BinOp::Shl, - BinOp::ShlUnchecked => rustc_middle::mir::BinOp::ShlUnchecked, - BinOp::Shr => rustc_middle::mir::BinOp::Shr, - BinOp::ShrUnchecked => rustc_middle::mir::BinOp::ShrUnchecked, - BinOp::Eq => rustc_middle::mir::BinOp::Eq, - BinOp::Lt => rustc_middle::mir::BinOp::Lt, - BinOp::Le => rustc_middle::mir::BinOp::Le, - BinOp::Ne => rustc_middle::mir::BinOp::Ne, - BinOp::Ge => rustc_middle::mir::BinOp::Ge, - BinOp::Gt => rustc_middle::mir::BinOp::Gt, - BinOp::Cmp => rustc_middle::mir::BinOp::Cmp, - BinOp::Offset => rustc_middle::mir::BinOp::Offset, - } - } -} - -impl RustcInternal for UnOp { - type T<'tcx> = rustc_middle::mir::UnOp; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - UnOp::Not => rustc_middle::mir::UnOp::Not, - UnOp::Neg => rustc_middle::mir::UnOp::Neg, - UnOp::PtrMetadata => rustc_middle::mir::UnOp::PtrMetadata, - } - } -} - -impl<T> RustcInternal for &T -where - T: RustcInternal, -{ - type T<'tcx> = T::T<'tcx>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - (*self).internal(tables, tcx) - } -} - -impl<T> RustcInternal for Option<T> -where - T: RustcInternal, -{ - type T<'tcx> = Option<T::T<'tcx>>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - self.as_ref().map(|inner| inner.internal(tables, tcx)) - } -} - -impl<T> RustcInternal for Vec<T> -where - T: RustcInternal, -{ - type T<'tcx> = Vec<T::T<'tcx>>; - - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - self.iter().map(|e| e.internal(tables, tcx)).collect() - } -} diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/mod.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/mod.rs deleted file mode 100644 index 6e1b85671f8..00000000000 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/mod.rs +++ /dev/null @@ -1,111 +0,0 @@ -//! This module holds the logic to convert rustc internal ADTs into stable mir ADTs. -//! -//! The conversion from stable to internal is not meant to be complete, -//! and it should be added as when needed to be passed as input to rustc_smir functions. -//! -//! For contributors, please make sure to avoid calling rustc's internal functions and queries. -//! These should be done via `rustc_smir` APIs, but it's possible to access ADT fields directly. - -use std::ops::RangeInclusive; - -use rustc_smir::Tables; -use rustc_smir::context::SmirCtxt; -use stable_mir::compiler_interface::BridgeTys; - -use super::Stable; -use crate::{rustc_smir, stable_mir}; - -mod internal; -mod stable; - -impl<'tcx, T> Stable<'tcx> for &T -where - T: Stable<'tcx>, -{ - type T = T::T; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - (*self).stable(tables, cx) - } -} - -impl<'tcx, T> Stable<'tcx> for Option<T> -where - T: Stable<'tcx>, -{ - type T = Option<T::T>; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - self.as_ref().map(|value| value.stable(tables, cx)) - } -} - -impl<'tcx, T, E> Stable<'tcx> for Result<T, E> -where - T: Stable<'tcx>, - E: Stable<'tcx>, -{ - type T = Result<T::T, E::T>; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - Ok(val) => Ok(val.stable(tables, cx)), - Err(error) => Err(error.stable(tables, cx)), - } - } -} - -impl<'tcx, T> Stable<'tcx> for &[T] -where - T: Stable<'tcx>, -{ - type T = Vec<T::T>; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - self.iter().map(|e| e.stable(tables, cx)).collect() - } -} - -impl<'tcx, T, U> Stable<'tcx> for (T, U) -where - T: Stable<'tcx>, - U: Stable<'tcx>, -{ - type T = (T::T, U::T); - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - (self.0.stable(tables, cx), self.1.stable(tables, cx)) - } -} - -impl<'tcx, T> Stable<'tcx> for RangeInclusive<T> -where - T: Stable<'tcx>, -{ - type T = RangeInclusive<T::T>; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - RangeInclusive::new(self.start().stable(tables, cx), self.end().stable(tables, cx)) - } -} diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/abi.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/abi.rs deleted file mode 100644 index d8823a0d10c..00000000000 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/abi.rs +++ /dev/null @@ -1,411 +0,0 @@ -//! Conversion of internal Rust compiler `rustc_target` and `rustc_abi` items to stable ones. - -#![allow(rustc::usage_of_qualified_ty)] - -use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call}; -use rustc_middle::ty; -use rustc_smir::Tables; -use rustc_smir::context::SmirCtxt; -use rustc_target::callconv; -use stable_mir::abi::{ - AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength, - IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar, - TagEncoding, TyAndLayout, ValueAbi, VariantsShape, WrappingRange, -}; -use stable_mir::compiler_interface::BridgeTys; -use stable_mir::target::MachineSize as Size; -use stable_mir::ty::{Align, VariantIdx}; -use stable_mir::unstable::Stable; -use stable_mir::{IndexedVal, opaque}; - -use crate::{rustc_smir, stable_mir}; - -impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx { - type T = VariantIdx; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - VariantIdx::to_val(self.as_usize()) - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::Endian { - type T = stable_mir::target::Endian; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - rustc_abi::Endian::Little => stable_mir::target::Endian::Little, - rustc_abi::Endian::Big => stable_mir::target::Endian::Big, - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::TyAndLayout<'tcx, ty::Ty<'tcx>> { - type T = TyAndLayout; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - TyAndLayout { ty: self.ty.stable(tables, cx), layout: self.layout.stable(tables, cx) } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::Layout<'tcx> { - type T = Layout; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - tables.layout_id(cx.lift(*self).unwrap()) - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi::VariantIdx> { - type T = LayoutShape; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - LayoutShape { - fields: self.fields.stable(tables, cx), - variants: self.variants.stable(tables, cx), - abi: self.backend_repr.stable(tables, cx), - abi_align: self.align.abi.stable(tables, cx), - size: self.size.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> { - type T = FnAbi; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - assert!(self.args.len() >= self.fixed_count as usize); - assert!(!self.c_variadic || matches!(self.conv, CanonAbi::C)); - FnAbi { - args: self.args.as_ref().stable(tables, cx), - ret: self.ret.stable(tables, cx), - fixed_count: self.fixed_count, - conv: self.conv.stable(tables, cx), - c_variadic: self.c_variadic, - } - } -} - -impl<'tcx> Stable<'tcx> for callconv::ArgAbi<'tcx, ty::Ty<'tcx>> { - type T = ArgAbi; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - ArgAbi { - ty: self.layout.ty.stable(tables, cx), - layout: self.layout.layout.stable(tables, cx), - mode: self.mode.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for CanonAbi { - type T = CallConvention; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - CanonAbi::C => CallConvention::C, - CanonAbi::Rust => CallConvention::Rust, - CanonAbi::RustCold => CallConvention::Cold, - CanonAbi::Custom => CallConvention::Custom, - CanonAbi::Arm(arm_call) => match arm_call { - ArmCall::Aapcs => CallConvention::ArmAapcs, - ArmCall::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall, - ArmCall::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry, - }, - CanonAbi::GpuKernel => CallConvention::GpuKernel, - CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind { - InterruptKind::Avr => CallConvention::AvrInterrupt, - InterruptKind::AvrNonBlocking => CallConvention::AvrNonBlockingInterrupt, - InterruptKind::Msp430 => CallConvention::Msp430Intr, - InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => { - CallConvention::RiscvInterrupt - } - InterruptKind::X86 => CallConvention::X86Intr, - }, - CanonAbi::X86(x86_call) => match x86_call { - X86Call::Fastcall => CallConvention::X86Fastcall, - X86Call::Stdcall => CallConvention::X86Stdcall, - X86Call::SysV64 => CallConvention::X86_64SysV, - X86Call::Thiscall => CallConvention::X86ThisCall, - X86Call::Vectorcall => CallConvention::X86VectorCall, - X86Call::Win64 => CallConvention::X86_64Win64, - }, - } - } -} - -impl<'tcx> Stable<'tcx> for callconv::PassMode { - type T = PassMode; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - callconv::PassMode::Ignore => PassMode::Ignore, - callconv::PassMode::Direct(attr) => PassMode::Direct(opaque(attr)), - callconv::PassMode::Pair(first, second) => { - PassMode::Pair(opaque(first), opaque(second)) - } - callconv::PassMode::Cast { pad_i32, cast } => { - PassMode::Cast { pad_i32: *pad_i32, cast: opaque(cast) } - } - callconv::PassMode::Indirect { attrs, meta_attrs, on_stack } => PassMode::Indirect { - attrs: opaque(attrs), - meta_attrs: opaque(meta_attrs), - on_stack: *on_stack, - }, - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_abi::FieldIdx> { - type T = FieldsShape; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - rustc_abi::FieldsShape::Primitive => FieldsShape::Primitive, - rustc_abi::FieldsShape::Union(count) => FieldsShape::Union(*count), - rustc_abi::FieldsShape::Array { stride, count } => { - FieldsShape::Array { stride: stride.stable(tables, cx), count: *count } - } - rustc_abi::FieldsShape::Arbitrary { offsets, .. } => { - FieldsShape::Arbitrary { offsets: offsets.iter().as_slice().stable(tables, cx) } - } - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::VariantIdx> { - type T = VariantsShape; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - rustc_abi::Variants::Single { index } => { - VariantsShape::Single { index: index.stable(tables, cx) } - } - rustc_abi::Variants::Empty => VariantsShape::Empty, - rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => { - VariantsShape::Multiple { - tag: tag.stable(tables, cx), - tag_encoding: tag_encoding.stable(tables, cx), - tag_field: tag_field.stable(tables, cx), - variants: variants.iter().as_slice().stable(tables, cx), - } - } - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> { - type T = TagEncoding; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - rustc_abi::TagEncoding::Direct => TagEncoding::Direct, - rustc_abi::TagEncoding::Niche { untagged_variant, niche_variants, niche_start } => { - TagEncoding::Niche { - untagged_variant: untagged_variant.stable(tables, cx), - niche_variants: niche_variants.stable(tables, cx), - niche_start: *niche_start, - } - } - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { - type T = ValueAbi; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match *self { - rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables, cx)), - rustc_abi::BackendRepr::ScalarPair(first, second) => { - ValueAbi::ScalarPair(first.stable(tables, cx), second.stable(tables, cx)) - } - rustc_abi::BackendRepr::SimdVector { element, count } => { - ValueAbi::Vector { element: element.stable(tables, cx), count } - } - rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized }, - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::Size { - type T = Size; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - Size::from_bits(self.bits_usize()) - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::Align { - type T = Align; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - self.bytes() - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::Scalar { - type T = Scalar; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - rustc_abi::Scalar::Initialized { value, valid_range } => Scalar::Initialized { - value: value.stable(tables, cx), - valid_range: valid_range.stable(tables, cx), - }, - rustc_abi::Scalar::Union { value } => Scalar::Union { value: value.stable(tables, cx) }, - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::Primitive { - type T = Primitive; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - rustc_abi::Primitive::Int(length, signed) => { - Primitive::Int { length: length.stable(tables, cx), signed: *signed } - } - rustc_abi::Primitive::Float(length) => { - Primitive::Float { length: length.stable(tables, cx) } - } - rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables, cx)), - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::AddressSpace { - type T = AddressSpace; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - AddressSpace(self.0) - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::Integer { - type T = IntegerLength; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - rustc_abi::Integer::I8 => IntegerLength::I8, - rustc_abi::Integer::I16 => IntegerLength::I16, - rustc_abi::Integer::I32 => IntegerLength::I32, - rustc_abi::Integer::I64 => IntegerLength::I64, - rustc_abi::Integer::I128 => IntegerLength::I128, - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::Float { - type T = FloatLength; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - rustc_abi::Float::F16 => FloatLength::F16, - rustc_abi::Float::F32 => FloatLength::F32, - rustc_abi::Float::F64 => FloatLength::F64, - rustc_abi::Float::F128 => FloatLength::F128, - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange { - type T = WrappingRange; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - WrappingRange { start: self.start, end: self.end } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::ReprFlags { - type T = ReprFlags; - - fn stable<'cx>( - &self, - _tables: &mut Tables<'cx, BridgeTys>, - _cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - ReprFlags { - is_simd: self.intersects(Self::IS_SIMD), - is_c: self.intersects(Self::IS_C), - is_transparent: self.intersects(Self::IS_TRANSPARENT), - is_linear: self.intersects(Self::IS_LINEAR), - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::IntegerType { - type T = IntegerType; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - rustc_abi::IntegerType::Pointer(signed) => IntegerType::Pointer { is_signed: *signed }, - rustc_abi::IntegerType::Fixed(integer, signed) => { - IntegerType::Fixed { length: integer.stable(tables, cx), is_signed: *signed } - } - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::ReprOptions { - type T = ReprOptions; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - ReprOptions { - int: self.int.map(|int| int.stable(tables, cx)), - align: self.align.map(|align| align.stable(tables, cx)), - pack: self.pack.map(|pack| pack.stable(tables, cx)), - flags: self.flags.stable(tables, cx), - } - } -} diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mir.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mir.rs deleted file mode 100644 index 99f9f456567..00000000000 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mir.rs +++ /dev/null @@ -1,950 +0,0 @@ -//! Conversion of internal Rust compiler `mir` items to stable ones. - -use rustc_middle::mir::mono::MonoItem; -use rustc_middle::{bug, mir}; -use rustc_smir::Tables; -use rustc_smir::bridge::SmirError; -use rustc_smir::context::SmirCtxt; -use stable_mir::compiler_interface::BridgeTys; -use stable_mir::mir::alloc::GlobalAlloc; -use stable_mir::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment}; -use stable_mir::ty::{Allocation, ConstantKind, MirConst}; -use stable_mir::unstable::Stable; -use stable_mir::{Error, alloc, opaque}; - -use crate::{rustc_smir, stable_mir}; - -impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { - type T = stable_mir::mir::Body; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - stable_mir::mir::Body::new( - self.basic_blocks - .iter() - .map(|block| stable_mir::mir::BasicBlock { - terminator: block.terminator().stable(tables, cx), - statements: block - .statements - .iter() - .map(|statement| statement.stable(tables, cx)) - .collect(), - }) - .collect(), - self.local_decls - .iter() - .map(|decl| stable_mir::mir::LocalDecl { - ty: decl.ty.stable(tables, cx), - span: decl.source_info.span.stable(tables, cx), - mutability: decl.mutability.stable(tables, cx), - }) - .collect(), - self.arg_count, - self.var_debug_info.iter().map(|info| info.stable(tables, cx)).collect(), - self.spread_arg.stable(tables, cx), - self.span.stable(tables, cx), - ) - } -} - -impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> { - type T = stable_mir::mir::VarDebugInfo; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - stable_mir::mir::VarDebugInfo { - name: self.name.to_string(), - source_info: self.source_info.stable(tables, cx), - composite: self.composite.as_ref().map(|composite| composite.stable(tables, cx)), - value: self.value.stable(tables, cx), - argument_index: self.argument_index, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { - type T = stable_mir::mir::Statement; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - Statement { - kind: self.kind.stable(tables, cx), - span: self.source_info.span.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::SourceInfo { - type T = stable_mir::mir::SourceInfo; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - stable_mir::mir::SourceInfo { span: self.span.stable(tables, cx), scope: self.scope.into() } - } -} - -impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> { - type T = stable_mir::mir::VarDebugInfoFragment; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - VarDebugInfoFragment { - ty: self.ty.stable(tables, cx), - projection: self.projection.iter().map(|e| e.stable(tables, cx)).collect(), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> { - type T = stable_mir::mir::VarDebugInfoContents; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - mir::VarDebugInfoContents::Place(place) => { - stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables, cx)) - } - mir::VarDebugInfoContents::Const(const_operand) => { - let op = ConstOperand { - span: const_operand.span.stable(tables, cx), - user_ty: const_operand.user_ty.map(|index| index.as_usize()), - const_: const_operand.const_.stable(tables, cx), - }; - stable_mir::mir::VarDebugInfoContents::Const(op) - } - } - } -} - -impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> { - type T = stable_mir::mir::StatementKind; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - mir::StatementKind::Assign(assign) => stable_mir::mir::StatementKind::Assign( - assign.0.stable(tables, cx), - assign.1.stable(tables, cx), - ), - mir::StatementKind::FakeRead(fake_read_place) => { - stable_mir::mir::StatementKind::FakeRead( - fake_read_place.0.stable(tables, cx), - fake_read_place.1.stable(tables, cx), - ) - } - mir::StatementKind::SetDiscriminant { place, variant_index } => { - stable_mir::mir::StatementKind::SetDiscriminant { - place: place.as_ref().stable(tables, cx), - variant_index: variant_index.stable(tables, cx), - } - } - mir::StatementKind::Deinit(place) => { - stable_mir::mir::StatementKind::Deinit(place.stable(tables, cx)) - } - - mir::StatementKind::StorageLive(place) => { - stable_mir::mir::StatementKind::StorageLive(place.stable(tables, cx)) - } - - mir::StatementKind::StorageDead(place) => { - stable_mir::mir::StatementKind::StorageDead(place.stable(tables, cx)) - } - mir::StatementKind::Retag(retag, place) => stable_mir::mir::StatementKind::Retag( - retag.stable(tables, cx), - place.stable(tables, cx), - ), - mir::StatementKind::PlaceMention(place) => { - stable_mir::mir::StatementKind::PlaceMention(place.stable(tables, cx)) - } - mir::StatementKind::AscribeUserType(place_projection, variance) => { - stable_mir::mir::StatementKind::AscribeUserType { - place: place_projection.as_ref().0.stable(tables, cx), - projections: place_projection.as_ref().1.stable(tables, cx), - variance: variance.stable(tables, cx), - } - } - mir::StatementKind::Coverage(coverage) => { - stable_mir::mir::StatementKind::Coverage(opaque(coverage)) - } - mir::StatementKind::Intrinsic(intrinstic) => { - stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables, cx)) - } - mir::StatementKind::ConstEvalCounter => { - stable_mir::mir::StatementKind::ConstEvalCounter - } - // BackwardIncompatibleDropHint has no semantics, so it is translated to Nop. - mir::StatementKind::BackwardIncompatibleDropHint { .. } => { - stable_mir::mir::StatementKind::Nop - } - mir::StatementKind::Nop => stable_mir::mir::StatementKind::Nop, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { - type T = stable_mir::mir::Rvalue; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::mir::Rvalue::*; - match self { - Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables, cx)), - Repeat(op, len) => { - let len = len.stable(tables, cx); - stable_mir::mir::Rvalue::Repeat(op.stable(tables, cx), len) - } - Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref( - region.stable(tables, cx), - kind.stable(tables, cx), - place.stable(tables, cx), - ), - ThreadLocalRef(def_id) => { - stable_mir::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id)) - } - RawPtr(mutability, place) => stable_mir::mir::Rvalue::AddressOf( - mutability.stable(tables, cx), - place.stable(tables, cx), - ), - Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables, cx)), - Cast(cast_kind, op, ty) => stable_mir::mir::Rvalue::Cast( - cast_kind.stable(tables, cx), - op.stable(tables, cx), - ty.stable(tables, cx), - ), - BinaryOp(bin_op, ops) => { - if let Some(bin_op) = bin_op.overflowing_to_wrapping() { - stable_mir::mir::Rvalue::CheckedBinaryOp( - bin_op.stable(tables, cx), - ops.0.stable(tables, cx), - ops.1.stable(tables, cx), - ) - } else { - stable_mir::mir::Rvalue::BinaryOp( - bin_op.stable(tables, cx), - ops.0.stable(tables, cx), - ops.1.stable(tables, cx), - ) - } - } - NullaryOp(null_op, ty) => stable_mir::mir::Rvalue::NullaryOp( - null_op.stable(tables, cx), - ty.stable(tables, cx), - ), - UnaryOp(un_op, op) => { - stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables, cx), op.stable(tables, cx)) - } - Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables, cx)), - Aggregate(agg_kind, operands) => { - let operands = operands.iter().map(|op| op.stable(tables, cx)).collect(); - stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables, cx), operands) - } - ShallowInitBox(op, ty) => stable_mir::mir::Rvalue::ShallowInitBox( - op.stable(tables, cx), - ty.stable(tables, cx), - ), - CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables, cx)), - WrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::Mutability { - type T = stable_mir::mir::Mutability; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_hir::Mutability::*; - match *self { - Not => stable_mir::mir::Mutability::Not, - Mut => stable_mir::mir::Mutability::Mut, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::RawPtrKind { - type T = stable_mir::mir::RawPtrKind; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use mir::RawPtrKind::*; - match *self { - Const => stable_mir::mir::RawPtrKind::Const, - Mut => stable_mir::mir::RawPtrKind::Mut, - FakeForPtrMetadata => stable_mir::mir::RawPtrKind::FakeForPtrMetadata, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::BorrowKind { - type T = stable_mir::mir::BorrowKind; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::mir::BorrowKind::*; - match *self { - Shared => stable_mir::mir::BorrowKind::Shared, - Fake(kind) => stable_mir::mir::BorrowKind::Fake(kind.stable(tables, cx)), - Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables, cx) }, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::MutBorrowKind { - type T = stable_mir::mir::MutBorrowKind; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::mir::MutBorrowKind::*; - match *self { - Default => stable_mir::mir::MutBorrowKind::Default, - TwoPhaseBorrow => stable_mir::mir::MutBorrowKind::TwoPhaseBorrow, - ClosureCapture => stable_mir::mir::MutBorrowKind::ClosureCapture, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind { - type T = stable_mir::mir::FakeBorrowKind; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::mir::FakeBorrowKind::*; - match *self { - Deep => stable_mir::mir::FakeBorrowKind::Deep, - Shallow => stable_mir::mir::FakeBorrowKind::Shallow, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> { - type T = stable_mir::mir::NullOp; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::mir::NullOp::*; - match self { - SizeOf => stable_mir::mir::NullOp::SizeOf, - AlignOf => stable_mir::mir::NullOp::AlignOf, - OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf( - indices.iter().map(|idx| idx.stable(tables, cx)).collect(), - ), - UbChecks => stable_mir::mir::NullOp::UbChecks, - ContractChecks => stable_mir::mir::NullOp::ContractChecks, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::CastKind { - type T = stable_mir::mir::CastKind; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::mir::CastKind::*; - match self { - PointerExposeProvenance => stable_mir::mir::CastKind::PointerExposeAddress, - PointerWithExposedProvenance => stable_mir::mir::CastKind::PointerWithExposedProvenance, - PointerCoercion(c, _) => { - stable_mir::mir::CastKind::PointerCoercion(c.stable(tables, cx)) - } - IntToInt => stable_mir::mir::CastKind::IntToInt, - FloatToInt => stable_mir::mir::CastKind::FloatToInt, - FloatToFloat => stable_mir::mir::CastKind::FloatToFloat, - IntToFloat => stable_mir::mir::CastKind::IntToFloat, - PtrToPtr => stable_mir::mir::CastKind::PtrToPtr, - FnPtrToPtr => stable_mir::mir::CastKind::FnPtrToPtr, - Transmute => stable_mir::mir::CastKind::Transmute, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::FakeReadCause { - type T = stable_mir::mir::FakeReadCause; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::mir::FakeReadCause::*; - match self { - ForMatchGuard => stable_mir::mir::FakeReadCause::ForMatchGuard, - ForMatchedPlace(local_def_id) => { - stable_mir::mir::FakeReadCause::ForMatchedPlace(opaque(local_def_id)) - } - ForGuardBinding => stable_mir::mir::FakeReadCause::ForGuardBinding, - ForLet(local_def_id) => stable_mir::mir::FakeReadCause::ForLet(opaque(local_def_id)), - ForIndex => stable_mir::mir::FakeReadCause::ForIndex, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> { - type T = stable_mir::mir::Operand; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::mir::Operand::*; - match self { - Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables, cx)), - Move(place) => stable_mir::mir::Operand::Move(place.stable(tables, cx)), - Constant(c) => stable_mir::mir::Operand::Constant(c.stable(tables, cx)), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> { - type T = stable_mir::mir::ConstOperand; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - stable_mir::mir::ConstOperand { - span: self.span.stable(tables, cx), - user_ty: self.user_ty.map(|u| u.as_usize()).or(None), - const_: self.const_.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::Place<'tcx> { - type T = stable_mir::mir::Place; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - stable_mir::mir::Place { - local: self.local.as_usize(), - projection: self.projection.iter().map(|e| e.stable(tables, cx)).collect(), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> { - type T = stable_mir::mir::ProjectionElem; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::mir::ProjectionElem::*; - match self { - Deref => stable_mir::mir::ProjectionElem::Deref, - Field(idx, ty) => stable_mir::mir::ProjectionElem::Field( - idx.stable(tables, cx), - ty.stable(tables, cx), - ), - Index(local) => stable_mir::mir::ProjectionElem::Index(local.stable(tables, cx)), - ConstantIndex { offset, min_length, from_end } => { - stable_mir::mir::ProjectionElem::ConstantIndex { - offset: *offset, - min_length: *min_length, - from_end: *from_end, - } - } - Subslice { from, to, from_end } => stable_mir::mir::ProjectionElem::Subslice { - from: *from, - to: *to, - from_end: *from_end, - }, - // MIR includes an `Option<Symbol>` argument for `Downcast` that is the name of the - // variant, used for printing MIR. However this information should also be accessible - // via a lookup using the `VariantIdx`. The `Option<Symbol>` argument is therefore - // dropped when converting to Stable MIR. A brief justification for this decision can be - // found at https://github.com/rust-lang/rust/pull/117517#issuecomment-1811683486 - Downcast(_, idx) => stable_mir::mir::ProjectionElem::Downcast(idx.stable(tables, cx)), - OpaqueCast(ty) => stable_mir::mir::ProjectionElem::OpaqueCast(ty.stable(tables, cx)), - Subtype(ty) => stable_mir::mir::ProjectionElem::Subtype(ty.stable(tables, cx)), - UnwrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::UserTypeProjection { - type T = stable_mir::mir::UserTypeProjection; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - UserTypeProjection { base: self.base.as_usize(), projection: opaque(&self.projs) } - } -} - -impl<'tcx> Stable<'tcx> for mir::Local { - type T = stable_mir::mir::Local; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - self.as_usize() - } -} - -impl<'tcx> Stable<'tcx> for mir::RetagKind { - type T = stable_mir::mir::RetagKind; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::mir::RetagKind; - match self { - RetagKind::FnEntry => stable_mir::mir::RetagKind::FnEntry, - RetagKind::TwoPhase => stable_mir::mir::RetagKind::TwoPhase, - RetagKind::Raw => stable_mir::mir::RetagKind::Raw, - RetagKind::Default => stable_mir::mir::RetagKind::Default, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::UnwindAction { - type T = stable_mir::mir::UnwindAction; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::mir::UnwindAction; - match self { - UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue, - UnwindAction::Unreachable => stable_mir::mir::UnwindAction::Unreachable, - UnwindAction::Terminate(_) => stable_mir::mir::UnwindAction::Terminate, - UnwindAction::Cleanup(bb) => stable_mir::mir::UnwindAction::Cleanup(bb.as_usize()), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> { - type T = stable_mir::mir::NonDivergingIntrinsic; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::mir::NonDivergingIntrinsic; - use stable_mir::mir::CopyNonOverlapping; - match self { - NonDivergingIntrinsic::Assume(op) => { - stable_mir::mir::NonDivergingIntrinsic::Assume(op.stable(tables, cx)) - } - NonDivergingIntrinsic::CopyNonOverlapping(copy_non_overlapping) => { - stable_mir::mir::NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { - src: copy_non_overlapping.src.stable(tables, cx), - dst: copy_non_overlapping.dst.stable(tables, cx), - count: copy_non_overlapping.count.stable(tables, cx), - }) - } - } - } -} - -impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> { - type T = stable_mir::mir::AssertMessage; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::mir::AssertKind; - match self { - AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck { - len: len.stable(tables, cx), - index: index.stable(tables, cx), - }, - AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow( - bin_op.stable(tables, cx), - op1.stable(tables, cx), - op2.stable(tables, cx), - ), - AssertKind::OverflowNeg(op) => { - stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables, cx)) - } - AssertKind::DivisionByZero(op) => { - stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables, cx)) - } - AssertKind::RemainderByZero(op) => { - stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables, cx)) - } - AssertKind::ResumedAfterReturn(coroutine) => { - stable_mir::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables, cx)) - } - AssertKind::ResumedAfterPanic(coroutine) => { - stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables, cx)) - } - AssertKind::ResumedAfterDrop(coroutine) => { - stable_mir::mir::AssertMessage::ResumedAfterDrop(coroutine.stable(tables, cx)) - } - AssertKind::MisalignedPointerDereference { required, found } => { - stable_mir::mir::AssertMessage::MisalignedPointerDereference { - required: required.stable(tables, cx), - found: found.stable(tables, cx), - } - } - AssertKind::NullPointerDereference => { - stable_mir::mir::AssertMessage::NullPointerDereference - } - AssertKind::InvalidEnumConstruction(source) => { - stable_mir::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx)) - } - } - } -} - -impl<'tcx> Stable<'tcx> for mir::BinOp { - type T = stable_mir::mir::BinOp; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::mir::BinOp; - match self { - BinOp::Add => stable_mir::mir::BinOp::Add, - BinOp::AddUnchecked => stable_mir::mir::BinOp::AddUnchecked, - BinOp::AddWithOverflow => bug!("AddWithOverflow should have been translated already"), - BinOp::Sub => stable_mir::mir::BinOp::Sub, - BinOp::SubUnchecked => stable_mir::mir::BinOp::SubUnchecked, - BinOp::SubWithOverflow => bug!("AddWithOverflow should have been translated already"), - BinOp::Mul => stable_mir::mir::BinOp::Mul, - BinOp::MulUnchecked => stable_mir::mir::BinOp::MulUnchecked, - BinOp::MulWithOverflow => bug!("AddWithOverflow should have been translated already"), - BinOp::Div => stable_mir::mir::BinOp::Div, - BinOp::Rem => stable_mir::mir::BinOp::Rem, - BinOp::BitXor => stable_mir::mir::BinOp::BitXor, - BinOp::BitAnd => stable_mir::mir::BinOp::BitAnd, - BinOp::BitOr => stable_mir::mir::BinOp::BitOr, - BinOp::Shl => stable_mir::mir::BinOp::Shl, - BinOp::ShlUnchecked => stable_mir::mir::BinOp::ShlUnchecked, - BinOp::Shr => stable_mir::mir::BinOp::Shr, - BinOp::ShrUnchecked => stable_mir::mir::BinOp::ShrUnchecked, - BinOp::Eq => stable_mir::mir::BinOp::Eq, - BinOp::Lt => stable_mir::mir::BinOp::Lt, - BinOp::Le => stable_mir::mir::BinOp::Le, - BinOp::Ne => stable_mir::mir::BinOp::Ne, - BinOp::Ge => stable_mir::mir::BinOp::Ge, - BinOp::Gt => stable_mir::mir::BinOp::Gt, - BinOp::Cmp => stable_mir::mir::BinOp::Cmp, - BinOp::Offset => stable_mir::mir::BinOp::Offset, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::UnOp { - type T = stable_mir::mir::UnOp; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::mir::UnOp; - match self { - UnOp::Not => stable_mir::mir::UnOp::Not, - UnOp::Neg => stable_mir::mir::UnOp::Neg, - UnOp::PtrMetadata => stable_mir::mir::UnOp::PtrMetadata, - } - } -} - -impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { - type T = stable_mir::mir::AggregateKind; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - mir::AggregateKind::Array(ty) => { - stable_mir::mir::AggregateKind::Array(ty.stable(tables, cx)) - } - mir::AggregateKind::Tuple => stable_mir::mir::AggregateKind::Tuple, - mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => { - stable_mir::mir::AggregateKind::Adt( - tables.adt_def(*def_id), - var_idx.stable(tables, cx), - generic_arg.stable(tables, cx), - user_ty_index.map(|idx| idx.index()), - field_idx.map(|idx| idx.index()), - ) - } - mir::AggregateKind::Closure(def_id, generic_arg) => { - stable_mir::mir::AggregateKind::Closure( - tables.closure_def(*def_id), - generic_arg.stable(tables, cx), - ) - } - mir::AggregateKind::Coroutine(def_id, generic_arg) => { - stable_mir::mir::AggregateKind::Coroutine( - tables.coroutine_def(*def_id), - generic_arg.stable(tables, cx), - cx.coroutine_movability(*def_id).stable(tables, cx), - ) - } - mir::AggregateKind::CoroutineClosure(def_id, generic_args) => { - stable_mir::mir::AggregateKind::CoroutineClosure( - tables.coroutine_closure_def(*def_id), - generic_args.stable(tables, cx), - ) - } - mir::AggregateKind::RawPtr(ty, mutability) => stable_mir::mir::AggregateKind::RawPtr( - ty.stable(tables, cx), - mutability.stable(tables, cx), - ), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> { - type T = stable_mir::mir::InlineAsmOperand; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::mir::InlineAsmOperand; - - let (in_value, out_place) = match self { - InlineAsmOperand::In { value, .. } => (Some(value.stable(tables, cx)), None), - InlineAsmOperand::Out { place, .. } => { - (None, place.map(|place| place.stable(tables, cx))) - } - InlineAsmOperand::InOut { in_value, out_place, .. } => { - (Some(in_value.stable(tables, cx)), out_place.map(|place| place.stable(tables, cx))) - } - InlineAsmOperand::Const { .. } - | InlineAsmOperand::SymFn { .. } - | InlineAsmOperand::SymStatic { .. } - | InlineAsmOperand::Label { .. } => (None, None), - }; - - stable_mir::mir::InlineAsmOperand { in_value, out_place, raw_rpr: format!("{self:?}") } - } -} - -impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { - type T = stable_mir::mir::Terminator; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::mir::Terminator; - Terminator { - kind: self.kind.stable(tables, cx), - span: self.source_info.span.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { - type T = stable_mir::mir::TerminatorKind; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::mir::TerminatorKind; - match self { - mir::TerminatorKind::Goto { target } => { - TerminatorKind::Goto { target: target.as_usize() } - } - mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt { - discr: discr.stable(tables, cx), - targets: { - let branches = targets.iter().map(|(val, target)| (val, target.as_usize())); - stable_mir::mir::SwitchTargets::new( - branches.collect(), - targets.otherwise().as_usize(), - ) - }, - }, - mir::TerminatorKind::UnwindResume => TerminatorKind::Resume, - mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort, - mir::TerminatorKind::Return => TerminatorKind::Return, - mir::TerminatorKind::Unreachable => TerminatorKind::Unreachable, - mir::TerminatorKind::Drop { - place, - target, - unwind, - replace: _, - drop: _, - async_fut: _, - } => TerminatorKind::Drop { - place: place.stable(tables, cx), - target: target.as_usize(), - unwind: unwind.stable(tables, cx), - }, - mir::TerminatorKind::Call { - func, - args, - destination, - target, - unwind, - call_source: _, - fn_span: _, - } => TerminatorKind::Call { - func: func.stable(tables, cx), - args: args.iter().map(|arg| arg.node.stable(tables, cx)).collect(), - destination: destination.stable(tables, cx), - target: target.map(|t| t.as_usize()), - unwind: unwind.stable(tables, cx), - }, - mir::TerminatorKind::TailCall { func: _, args: _, fn_span: _ } => todo!(), - mir::TerminatorKind::Assert { cond, expected, msg, target, unwind } => { - TerminatorKind::Assert { - cond: cond.stable(tables, cx), - expected: *expected, - msg: msg.stable(tables, cx), - target: target.as_usize(), - unwind: unwind.stable(tables, cx), - } - } - mir::TerminatorKind::InlineAsm { - asm_macro: _, - template, - operands, - options, - line_spans, - targets, - unwind, - } => TerminatorKind::InlineAsm { - template: format!("{template:?}"), - operands: operands.iter().map(|operand| operand.stable(tables, cx)).collect(), - options: format!("{options:?}"), - line_spans: format!("{line_spans:?}"), - // FIXME: Figure out how to do labels in SMIR - destination: targets.first().map(|d| d.as_usize()), - unwind: unwind.stable(tables, cx), - }, - mir::TerminatorKind::Yield { .. } - | mir::TerminatorKind::CoroutineDrop - | mir::TerminatorKind::FalseEdge { .. } - | mir::TerminatorKind::FalseUnwind { .. } => unreachable!(), - } - } -} - -impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> { - type T = Allocation; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - self.inner().stable(tables, cx) - } -} - -impl<'tcx> Stable<'tcx> for mir::interpret::Allocation { - type T = stable_mir::ty::Allocation; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_smir::context::SmirAllocRange; - alloc::allocation_filter( - self, - cx.alloc_range(rustc_abi::Size::ZERO, self.size()), - tables, - cx, - ) - } -} - -impl<'tcx> Stable<'tcx> for mir::interpret::AllocId { - type T = stable_mir::mir::alloc::AllocId; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - _: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - tables.create_alloc_id(*self) - } -} - -impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> { - type T = GlobalAlloc; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - mir::interpret::GlobalAlloc::Function { instance, .. } => { - GlobalAlloc::Function(instance.stable(tables, cx)) - } - mir::interpret::GlobalAlloc::VTable(ty, dyn_ty) => { - // FIXME: Should we record the whole vtable? - GlobalAlloc::VTable(ty.stable(tables, cx), dyn_ty.principal().stable(tables, cx)) - } - mir::interpret::GlobalAlloc::Static(def) => { - GlobalAlloc::Static(tables.static_def(*def)) - } - mir::interpret::GlobalAlloc::Memory(alloc) => { - GlobalAlloc::Memory(alloc.stable(tables, cx)) - } - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { - type T = stable_mir::ty::MirConst; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let id = tables.intern_mir_const(cx.lift(*self).unwrap()); - match *self { - mir::Const::Ty(ty, c) => MirConst::new( - stable_mir::ty::ConstantKind::Ty(c.stable(tables, cx)), - ty.stable(tables, cx), - id, - ), - mir::Const::Unevaluated(unev_const, ty) => { - let kind = - stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { - def: tables.const_def(unev_const.def), - args: unev_const.args.stable(tables, cx), - promoted: unev_const.promoted.map(|u| u.as_u32()), - }); - let ty = ty.stable(tables, cx); - MirConst::new(kind, ty, id) - } - mir::Const::Val(mir::ConstValue::ZeroSized, ty) => { - let ty = ty.stable(tables, cx); - MirConst::new(ConstantKind::ZeroSized, ty, id) - } - mir::Const::Val(val, ty) => { - let ty = cx.lift(ty).unwrap(); - let val = cx.lift(val).unwrap(); - let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables, cx)); - let ty = ty.stable(tables, cx); - MirConst::new(kind, ty, id) - } - } - } -} - -impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled { - type T = Error; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - Error::new(format!("{self:?}")) - } -} - -impl<'tcx> Stable<'tcx> for MonoItem<'tcx> { - type T = stable_mir::mir::mono::MonoItem; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::mir::mono::MonoItem as StableMonoItem; - match self { - MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables, cx)), - MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)), - MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)), - } - } -} diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mod.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mod.rs deleted file mode 100644 index 799917c6e17..00000000000 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mod.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! Conversion of internal Rust compiler items to stable ones. - -use rustc_abi::FieldIdx; -use rustc_smir::Tables; -use rustc_smir::context::SmirCtxt; -use stable_mir::compiler_interface::BridgeTys; - -use super::Stable; -use crate::{rustc_smir, stable_mir}; - -mod abi; -mod mir; -mod ty; - -impl<'tcx> Stable<'tcx> for rustc_hir::Safety { - type T = stable_mir::mir::Safety; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - rustc_hir::Safety::Unsafe => stable_mir::mir::Safety::Unsafe, - rustc_hir::Safety::Safe => stable_mir::mir::Safety::Safe, - } - } -} - -impl<'tcx> Stable<'tcx> for FieldIdx { - type T = usize; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - self.as_usize() - } -} - -impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource { - type T = stable_mir::mir::CoroutineSource; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_hir::CoroutineSource; - match self { - CoroutineSource::Block => stable_mir::mir::CoroutineSource::Block, - CoroutineSource::Closure => stable_mir::mir::CoroutineSource::Closure, - CoroutineSource::Fn => stable_mir::mir::CoroutineSource::Fn, - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind { - type T = stable_mir::mir::CoroutineKind; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_hir::{CoroutineDesugaring, CoroutineKind}; - match *self { - CoroutineKind::Desugared(CoroutineDesugaring::Async, source) => { - stable_mir::mir::CoroutineKind::Desugared( - stable_mir::mir::CoroutineDesugaring::Async, - source.stable(tables, cx), - ) - } - CoroutineKind::Desugared(CoroutineDesugaring::Gen, source) => { - stable_mir::mir::CoroutineKind::Desugared( - stable_mir::mir::CoroutineDesugaring::Gen, - source.stable(tables, cx), - ) - } - CoroutineKind::Coroutine(movability) => { - stable_mir::mir::CoroutineKind::Coroutine(movability.stable(tables, cx)) - } - CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, source) => { - stable_mir::mir::CoroutineKind::Desugared( - stable_mir::mir::CoroutineDesugaring::AsyncGen, - source.stable(tables, cx), - ) - } - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_span::Symbol { - type T = stable_mir::Symbol; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - self.to_string() - } -} - -impl<'tcx> Stable<'tcx> for rustc_span::Span { - type T = stable_mir::ty::Span; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - _: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - tables.create_span(*self) - } -} diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/ty.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/ty.rs deleted file mode 100644 index 596c8b96bfc..00000000000 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/ty.rs +++ /dev/null @@ -1,1151 +0,0 @@ -//! Conversion of internal Rust compiler `ty` items to stable ones. - -use rustc_middle::ty::Ty; -use rustc_middle::{bug, mir, ty}; -use rustc_smir::Tables; -use rustc_smir::context::SmirCtxt; -use stable_mir::alloc; -use stable_mir::compiler_interface::BridgeTys; -use stable_mir::ty::{ - AdtKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy, TyKind, UintTy, -}; -use stable_mir::unstable::Stable; - -use crate::{rustc_smir, stable_mir}; - -impl<'tcx> Stable<'tcx> for ty::AliasTyKind { - type T = stable_mir::ty::AliasKind; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - ty::Projection => stable_mir::ty::AliasKind::Projection, - ty::Inherent => stable_mir::ty::AliasKind::Inherent, - ty::Opaque => stable_mir::ty::AliasKind::Opaque, - ty::Free => stable_mir::ty::AliasKind::Free, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> { - type T = stable_mir::ty::AliasTy; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let ty::AliasTy { args, def_id, .. } = self; - stable_mir::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables, cx) } - } -} - -impl<'tcx> Stable<'tcx> for ty::AliasTerm<'tcx> { - type T = stable_mir::ty::AliasTerm; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let ty::AliasTerm { args, def_id, .. } = self; - stable_mir::ty::AliasTerm { - def_id: tables.alias_def(*def_id), - args: args.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::DynKind { - type T = stable_mir::ty::DynKind; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - ty::Dyn => stable_mir::ty::DynKind::Dyn, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> { - type T = stable_mir::ty::ExistentialPredicate; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::ExistentialPredicate::*; - match self { - ty::ExistentialPredicate::Trait(existential_trait_ref) => { - Trait(existential_trait_ref.stable(tables, cx)) - } - ty::ExistentialPredicate::Projection(existential_projection) => { - Projection(existential_projection.stable(tables, cx)) - } - ty::ExistentialPredicate::AutoTrait(def_id) => AutoTrait(tables.trait_def(*def_id)), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> { - type T = stable_mir::ty::ExistentialTraitRef; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let ty::ExistentialTraitRef { def_id, args, .. } = self; - stable_mir::ty::ExistentialTraitRef { - def_id: tables.trait_def(*def_id), - generic_args: args.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> { - type T = stable_mir::ty::TermKind; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::TermKind; - match self { - ty::TermKind::Ty(ty) => TermKind::Type(ty.stable(tables, cx)), - ty::TermKind::Const(cnst) => { - let cnst = cnst.stable(tables, cx); - TermKind::Const(cnst) - } - } - } -} - -impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> { - type T = stable_mir::ty::ExistentialProjection; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let ty::ExistentialProjection { def_id, args, term, .. } = self; - stable_mir::ty::ExistentialProjection { - def_id: tables.trait_def(*def_id), - generic_args: args.stable(tables, cx), - term: term.kind().stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion { - type T = stable_mir::mir::PointerCoercion; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::ty::adjustment::PointerCoercion; - match self { - PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer, - PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer, - PointerCoercion::ClosureFnPointer(safety) => { - stable_mir::mir::PointerCoercion::ClosureFnPointer(safety.stable(tables, cx)) - } - PointerCoercion::MutToConstPointer => { - stable_mir::mir::PointerCoercion::MutToConstPointer - } - PointerCoercion::ArrayToPointer => stable_mir::mir::PointerCoercion::ArrayToPointer, - PointerCoercion::Unsize => stable_mir::mir::PointerCoercion::Unsize, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex { - type T = usize; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - self.as_usize() - } -} - -impl<'tcx> Stable<'tcx> for ty::AdtKind { - type T = AdtKind; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - ty::AdtKind::Struct => AdtKind::Struct, - ty::AdtKind::Union => AdtKind::Union, - ty::AdtKind::Enum => AdtKind::Enum, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::FieldDef { - type T = stable_mir::ty::FieldDef; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - stable_mir::ty::FieldDef { - def: tables.create_def_id(self.did), - name: self.name.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> { - type T = stable_mir::ty::GenericArgs; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - GenericArgs(self.iter().map(|arg| arg.kind().stable(tables, cx)).collect()) - } -} - -impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> { - type T = stable_mir::ty::GenericArgKind; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::GenericArgKind; - match self { - ty::GenericArgKind::Lifetime(region) => { - GenericArgKind::Lifetime(region.stable(tables, cx)) - } - ty::GenericArgKind::Type(ty) => GenericArgKind::Type(ty.stable(tables, cx)), - ty::GenericArgKind::Const(cnst) => GenericArgKind::Const(cnst.stable(tables, cx)), - } - } -} - -impl<'tcx, S, V> Stable<'tcx> for ty::Binder<'tcx, S> -where - S: Stable<'tcx, T = V>, -{ - type T = stable_mir::ty::Binder<V>; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::Binder; - - Binder { - value: self.as_ref().skip_binder().stable(tables, cx), - bound_vars: self - .bound_vars() - .iter() - .map(|bound_var| bound_var.stable(tables, cx)) - .collect(), - } - } -} - -impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder<'tcx, S> -where - S: Stable<'tcx, T = V>, -{ - type T = stable_mir::ty::EarlyBinder<V>; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::EarlyBinder; - - EarlyBinder { value: self.as_ref().skip_binder().stable(tables, cx) } - } -} - -impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { - type T = stable_mir::ty::FnSig; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::FnSig; - - FnSig { - inputs_and_output: self - .inputs_and_output - .iter() - .map(|ty| ty.stable(tables, cx)) - .collect(), - c_variadic: self.c_variadic, - safety: self.safety.stable(tables, cx), - abi: self.abi.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::BoundTyKind { - type T = stable_mir::ty::BoundTyKind; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::BoundTyKind; - - match self { - ty::BoundTyKind::Anon => BoundTyKind::Anon, - ty::BoundTyKind::Param(def_id) => { - BoundTyKind::Param(tables.param_def(*def_id), cx.tcx.item_name(*def_id).to_string()) - } - } - } -} - -impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { - type T = stable_mir::ty::BoundRegionKind; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::BoundRegionKind; - - match self { - ty::BoundRegionKind::Anon => BoundRegionKind::BrAnon, - ty::BoundRegionKind::Named(def_id) => BoundRegionKind::BrNamed( - tables.br_named_def(*def_id), - cx.tcx.item_name(*def_id).to_string(), - ), - ty::BoundRegionKind::ClosureEnv => BoundRegionKind::BrEnv, - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::BoundVariableKind { - type T = stable_mir::ty::BoundVariableKind; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::BoundVariableKind; - - match self { - ty::BoundVariableKind::Ty(bound_ty_kind) => { - BoundVariableKind::Ty(bound_ty_kind.stable(tables, cx)) - } - ty::BoundVariableKind::Region(bound_region_kind) => { - BoundVariableKind::Region(bound_region_kind.stable(tables, cx)) - } - ty::BoundVariableKind::Const => BoundVariableKind::Const, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::IntTy { - type T = IntTy; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - ty::IntTy::Isize => IntTy::Isize, - ty::IntTy::I8 => IntTy::I8, - ty::IntTy::I16 => IntTy::I16, - ty::IntTy::I32 => IntTy::I32, - ty::IntTy::I64 => IntTy::I64, - ty::IntTy::I128 => IntTy::I128, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::UintTy { - type T = UintTy; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - ty::UintTy::Usize => UintTy::Usize, - ty::UintTy::U8 => UintTy::U8, - ty::UintTy::U16 => UintTy::U16, - ty::UintTy::U32 => UintTy::U32, - ty::UintTy::U64 => UintTy::U64, - ty::UintTy::U128 => UintTy::U128, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::FloatTy { - type T = FloatTy; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - ty::FloatTy::F16 => FloatTy::F16, - ty::FloatTy::F32 => FloatTy::F32, - ty::FloatTy::F64 => FloatTy::F64, - ty::FloatTy::F128 => FloatTy::F128, - } - } -} - -impl<'tcx> Stable<'tcx> for Ty<'tcx> { - type T = stable_mir::ty::Ty; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - tables.intern_ty(cx.lift(*self).unwrap()) - } -} - -impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { - type T = stable_mir::ty::TyKind; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match self { - ty::Bool => TyKind::RigidTy(RigidTy::Bool), - ty::Char => TyKind::RigidTy(RigidTy::Char), - ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables, cx))), - ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables, cx))), - ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables, cx))), - ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt( - tables.adt_def(adt_def.did()), - generic_args.stable(tables, cx), - )), - ty::Foreign(def_id) => TyKind::RigidTy(RigidTy::Foreign(tables.foreign_def(*def_id))), - ty::Str => TyKind::RigidTy(RigidTy::Str), - ty::Array(ty, constant) => { - TyKind::RigidTy(RigidTy::Array(ty.stable(tables, cx), constant.stable(tables, cx))) - } - ty::Pat(ty, pat) => { - TyKind::RigidTy(RigidTy::Pat(ty.stable(tables, cx), pat.stable(tables, cx))) - } - ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(ty.stable(tables, cx))), - ty::RawPtr(ty, mutbl) => { - TyKind::RigidTy(RigidTy::RawPtr(ty.stable(tables, cx), mutbl.stable(tables, cx))) - } - ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref( - region.stable(tables, cx), - ty.stable(tables, cx), - mutbl.stable(tables, cx), - )), - ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef( - tables.fn_def(*def_id), - generic_args.stable(tables, cx), - )), - ty::FnPtr(sig_tys, hdr) => { - TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables, cx))) - } - // FIXME(unsafe_binders): - ty::UnsafeBinder(_) => todo!(), - ty::Dynamic(existential_predicates, region, dyn_kind) => { - TyKind::RigidTy(RigidTy::Dynamic( - existential_predicates - .iter() - .map(|existential_predicate| existential_predicate.stable(tables, cx)) - .collect(), - region.stable(tables, cx), - dyn_kind.stable(tables, cx), - )) - } - ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure( - tables.closure_def(*def_id), - generic_args.stable(tables, cx), - )), - ty::CoroutineClosure(..) => todo!("FIXME(async_closures): Lower these to SMIR"), - ty::Coroutine(def_id, generic_args) => TyKind::RigidTy(RigidTy::Coroutine( - tables.coroutine_def(*def_id), - generic_args.stable(tables, cx), - cx.coroutine_movability(*def_id).stable(tables, cx), - )), - ty::Never => TyKind::RigidTy(RigidTy::Never), - ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple( - fields.iter().map(|ty| ty.stable(tables, cx)).collect(), - )), - ty::Alias(alias_kind, alias_ty) => { - TyKind::Alias(alias_kind.stable(tables, cx), alias_ty.stable(tables, cx)) - } - ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables, cx)), - ty::Bound(debruijn_idx, bound_ty) => { - TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables, cx)) - } - ty::CoroutineWitness(def_id, args) => TyKind::RigidTy(RigidTy::CoroutineWitness( - tables.coroutine_witness_def(*def_id), - args.stable(tables, cx), - )), - ty::Placeholder(..) | ty::Infer(_) | ty::Error(_) => { - unreachable!(); - } - } - } -} - -impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { - type T = stable_mir::ty::Pattern; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - match **self { - ty::PatternKind::Range { start, end } => stable_mir::ty::Pattern::Range { - // FIXME(SMIR): update data structures to not have an Option here anymore - start: Some(start.stable(tables, cx)), - end: Some(end.stable(tables, cx)), - include_end: true, - }, - ty::PatternKind::Or(_) => todo!(), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { - type T = stable_mir::ty::TyConst; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let ct = cx.lift(*self).unwrap(); - let kind = match ct.kind() { - ty::ConstKind::Value(cv) => { - let const_val = cx.valtree_to_const_val(cv); - if matches!(const_val, mir::ConstValue::ZeroSized) { - stable_mir::ty::TyConstKind::ZSTValue(cv.ty.stable(tables, cx)) - } else { - stable_mir::ty::TyConstKind::Value( - cv.ty.stable(tables, cx), - alloc::new_allocation(cv.ty, const_val, tables, cx), - ) - } - } - ty::ConstKind::Param(param) => { - stable_mir::ty::TyConstKind::Param(param.stable(tables, cx)) - } - ty::ConstKind::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated( - tables.const_def(uv.def), - uv.args.stable(tables, cx), - ), - ty::ConstKind::Error(_) => unreachable!(), - ty::ConstKind::Infer(_) => unreachable!(), - ty::ConstKind::Bound(_, _) => unimplemented!(), - ty::ConstKind::Placeholder(_) => unimplemented!(), - ty::ConstKind::Expr(_) => unimplemented!(), - }; - let id = tables.intern_ty_const(ct); - stable_mir::ty::TyConst::new(kind, id) - } -} - -impl<'tcx> Stable<'tcx> for ty::ParamConst { - type T = stable_mir::ty::ParamConst; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use stable_mir::ty::ParamConst; - ParamConst { index: self.index, name: self.name.to_string() } - } -} - -impl<'tcx> Stable<'tcx> for ty::ParamTy { - type T = stable_mir::ty::ParamTy; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use stable_mir::ty::ParamTy; - ParamTy { index: self.index, name: self.name.to_string() } - } -} - -impl<'tcx> Stable<'tcx> for ty::BoundTy { - type T = stable_mir::ty::BoundTy; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::BoundTy; - BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables, cx) } - } -} - -impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind { - type T = stable_mir::ty::TraitSpecializationKind; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use stable_mir::ty::TraitSpecializationKind; - - match self { - ty::trait_def::TraitSpecializationKind::None => TraitSpecializationKind::None, - ty::trait_def::TraitSpecializationKind::Marker => TraitSpecializationKind::Marker, - ty::trait_def::TraitSpecializationKind::AlwaysApplicable => { - TraitSpecializationKind::AlwaysApplicable - } - } - } -} - -impl<'tcx> Stable<'tcx> for ty::TraitDef { - type T = stable_mir::ty::TraitDecl; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::opaque; - use stable_mir::ty::TraitDecl; - - TraitDecl { - def_id: tables.trait_def(self.def_id), - safety: self.safety.stable(tables, cx), - paren_sugar: self.paren_sugar, - has_auto_impl: self.has_auto_impl, - is_marker: self.is_marker, - is_coinductive: self.is_coinductive, - skip_array_during_method_dispatch: self.skip_array_during_method_dispatch, - skip_boxed_slice_during_method_dispatch: self.skip_boxed_slice_during_method_dispatch, - specialization_kind: self.specialization_kind.stable(tables, cx), - must_implement_one_of: self - .must_implement_one_of - .as_ref() - .map(|idents| idents.iter().map(|ident| opaque(ident)).collect()), - implement_via_object: self.implement_via_object, - deny_explicit_impl: self.deny_explicit_impl, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> { - type T = stable_mir::ty::TraitRef; - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::TraitRef; - - TraitRef::try_new(tables.trait_def(self.def_id), self.args.stable(tables, cx)).unwrap() - } -} - -impl<'tcx> Stable<'tcx> for ty::Generics { - type T = stable_mir::ty::Generics; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::Generics; - - let params: Vec<_> = self.own_params.iter().map(|param| param.stable(tables, cx)).collect(); - let param_def_id_to_index = - params.iter().map(|param| (param.def_id, param.index)).collect(); - - Generics { - parent: self.parent.map(|did| tables.generic_def(did)), - parent_count: self.parent_count, - params, - param_def_id_to_index, - has_self: self.has_self, - has_late_bound_regions: self - .has_late_bound_regions - .as_ref() - .map(|late_bound_regions| late_bound_regions.stable(tables, cx)), - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { - type T = stable_mir::ty::GenericParamDefKind; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use stable_mir::ty::GenericParamDefKind; - match self { - ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime, - ty::GenericParamDefKind::Type { has_default, synthetic } => { - GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic } - } - ty::GenericParamDefKind::Const { has_default, synthetic: _ } => { - GenericParamDefKind::Const { has_default: *has_default } - } - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef { - type T = stable_mir::ty::GenericParamDef; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - GenericParamDef { - name: self.name.to_string(), - def_id: tables.generic_def(self.def_id), - index: self.index, - pure_wrt_drop: self.pure_wrt_drop, - kind: self.kind.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { - type T = stable_mir::ty::PredicateKind; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::ty::PredicateKind; - match self { - PredicateKind::Clause(clause_kind) => { - stable_mir::ty::PredicateKind::Clause(clause_kind.stable(tables, cx)) - } - PredicateKind::DynCompatible(did) => { - stable_mir::ty::PredicateKind::DynCompatible(tables.trait_def(*did)) - } - PredicateKind::Subtype(subtype_predicate) => { - stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables, cx)) - } - PredicateKind::Coerce(coerce_predicate) => { - stable_mir::ty::PredicateKind::Coerce(coerce_predicate.stable(tables, cx)) - } - PredicateKind::ConstEquate(a, b) => stable_mir::ty::PredicateKind::ConstEquate( - a.stable(tables, cx), - b.stable(tables, cx), - ), - PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous, - PredicateKind::NormalizesTo(_pred) => unimplemented!(), - PredicateKind::AliasRelate(a, b, alias_relation_direction) => { - stable_mir::ty::PredicateKind::AliasRelate( - a.kind().stable(tables, cx), - b.kind().stable(tables, cx), - alias_relation_direction.stable(tables, cx), - ) - } - } - } -} - -impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> { - type T = stable_mir::ty::ClauseKind; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use rustc_middle::ty::ClauseKind; - match *self { - ClauseKind::Trait(trait_object) => { - stable_mir::ty::ClauseKind::Trait(trait_object.stable(tables, cx)) - } - ClauseKind::RegionOutlives(region_outlives) => { - stable_mir::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables, cx)) - } - ClauseKind::TypeOutlives(type_outlives) => { - let ty::OutlivesPredicate::<_, _>(a, b) = type_outlives; - stable_mir::ty::ClauseKind::TypeOutlives(stable_mir::ty::OutlivesPredicate( - a.stable(tables, cx), - b.stable(tables, cx), - )) - } - ClauseKind::Projection(projection_predicate) => { - stable_mir::ty::ClauseKind::Projection(projection_predicate.stable(tables, cx)) - } - ClauseKind::ConstArgHasType(const_, ty) => stable_mir::ty::ClauseKind::ConstArgHasType( - const_.stable(tables, cx), - ty.stable(tables, cx), - ), - ClauseKind::WellFormed(term) => { - stable_mir::ty::ClauseKind::WellFormed(term.kind().stable(tables, cx)) - } - ClauseKind::ConstEvaluatable(const_) => { - stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables, cx)) - } - ClauseKind::HostEffect(..) => { - todo!() - } - } - } -} - -impl<'tcx> Stable<'tcx> for ty::ClosureKind { - type T = stable_mir::ty::ClosureKind; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::ty::ClosureKind::*; - match self { - Fn => stable_mir::ty::ClosureKind::Fn, - FnMut => stable_mir::ty::ClosureKind::FnMut, - FnOnce => stable_mir::ty::ClosureKind::FnOnce, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> { - type T = stable_mir::ty::SubtypePredicate; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let ty::SubtypePredicate { a, b, a_is_expected: _ } = self; - stable_mir::ty::SubtypePredicate { a: a.stable(tables, cx), b: b.stable(tables, cx) } - } -} - -impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> { - type T = stable_mir::ty::CoercePredicate; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let ty::CoercePredicate { a, b } = self; - stable_mir::ty::CoercePredicate { a: a.stable(tables, cx), b: b.stable(tables, cx) } - } -} - -impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection { - type T = stable_mir::ty::AliasRelationDirection; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::ty::AliasRelationDirection::*; - match self { - Equate => stable_mir::ty::AliasRelationDirection::Equate, - Subtype => stable_mir::ty::AliasRelationDirection::Subtype, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> { - type T = stable_mir::ty::TraitPredicate; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let ty::TraitPredicate { trait_ref, polarity } = self; - stable_mir::ty::TraitPredicate { - trait_ref: trait_ref.stable(tables, cx), - polarity: polarity.stable(tables, cx), - } - } -} - -impl<'tcx, T> Stable<'tcx> for ty::OutlivesPredicate<'tcx, T> -where - T: Stable<'tcx>, -{ - type T = stable_mir::ty::OutlivesPredicate<T::T, Region>; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let ty::OutlivesPredicate(a, b) = self; - stable_mir::ty::OutlivesPredicate(a.stable(tables, cx), b.stable(tables, cx)) - } -} - -impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> { - type T = stable_mir::ty::ProjectionPredicate; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let ty::ProjectionPredicate { projection_term, term } = self; - stable_mir::ty::ProjectionPredicate { - projection_term: projection_term.stable(tables, cx), - term: term.kind().stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::ImplPolarity { - type T = stable_mir::ty::ImplPolarity; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::ty::ImplPolarity::*; - match self { - Positive => stable_mir::ty::ImplPolarity::Positive, - Negative => stable_mir::ty::ImplPolarity::Negative, - Reservation => stable_mir::ty::ImplPolarity::Reservation, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::PredicatePolarity { - type T = stable_mir::ty::PredicatePolarity; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::ty::PredicatePolarity::*; - match self { - Positive => stable_mir::ty::PredicatePolarity::Positive, - Negative => stable_mir::ty::PredicatePolarity::Negative, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::Region<'tcx> { - type T = stable_mir::ty::Region; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - Region { kind: self.kind().stable(tables, cx) } - } -} - -impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { - type T = stable_mir::ty::RegionKind; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::{BoundRegion, EarlyParamRegion, RegionKind}; - match self { - ty::ReEarlyParam(early_reg) => RegionKind::ReEarlyParam(EarlyParamRegion { - index: early_reg.index, - name: early_reg.name.to_string(), - }), - ty::ReBound(db_index, bound_reg) => RegionKind::ReBound( - db_index.as_u32(), - BoundRegion { - var: bound_reg.var.as_u32(), - kind: bound_reg.kind.stable(tables, cx), - }, - ), - ty::ReStatic => RegionKind::ReStatic, - ty::RePlaceholder(place_holder) => { - RegionKind::RePlaceholder(stable_mir::ty::Placeholder { - universe: place_holder.universe.as_u32(), - bound: BoundRegion { - var: place_holder.bound.var.as_u32(), - kind: place_holder.bound.kind.stable(tables, cx), - }, - }) - } - ty::ReErased => RegionKind::ReErased, - _ => unreachable!("{self:?}"), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { - type T = stable_mir::mir::mono::Instance; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - let def = tables.instance_def(cx.lift(*self).unwrap()); - let kind = match self.def { - ty::InstanceKind::Item(..) => stable_mir::mir::mono::InstanceKind::Item, - ty::InstanceKind::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic, - ty::InstanceKind::Virtual(_def_id, idx) => { - stable_mir::mir::mono::InstanceKind::Virtual { idx } - } - ty::InstanceKind::VTableShim(..) - | ty::InstanceKind::ReifyShim(..) - | ty::InstanceKind::FnPtrAddrShim(..) - | ty::InstanceKind::ClosureOnceShim { .. } - | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::ThreadLocalShim(..) - | ty::InstanceKind::DropGlue(..) - | ty::InstanceKind::CloneShim(..) - | ty::InstanceKind::FnPtrShim(..) - | ty::InstanceKind::FutureDropPollShim(..) - | ty::InstanceKind::AsyncDropGlue(..) - | ty::InstanceKind::AsyncDropGlueCtorShim(..) => { - stable_mir::mir::mono::InstanceKind::Shim - } - }; - stable_mir::mir::mono::Instance { def, kind } - } -} - -impl<'tcx> Stable<'tcx> for ty::Variance { - type T = stable_mir::mir::Variance; - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - ty::Bivariant => stable_mir::mir::Variance::Bivariant, - ty::Contravariant => stable_mir::mir::Variance::Contravariant, - ty::Covariant => stable_mir::mir::Variance::Covariant, - ty::Invariant => stable_mir::mir::Variance::Invariant, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::Movability { - type T = stable_mir::ty::Movability; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - match self { - ty::Movability::Static => stable_mir::ty::Movability::Static, - ty::Movability::Movable => stable_mir::ty::Movability::Movable, - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi { - type T = stable_mir::ty::Abi; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use rustc_abi::ExternAbi; - use stable_mir::ty::Abi; - match *self { - ExternAbi::Rust => Abi::Rust, - ExternAbi::C { unwind } => Abi::C { unwind }, - ExternAbi::Cdecl { unwind } => Abi::Cdecl { unwind }, - ExternAbi::Stdcall { unwind } => Abi::Stdcall { unwind }, - ExternAbi::Fastcall { unwind } => Abi::Fastcall { unwind }, - ExternAbi::Vectorcall { unwind } => Abi::Vectorcall { unwind }, - ExternAbi::Thiscall { unwind } => Abi::Thiscall { unwind }, - ExternAbi::Aapcs { unwind } => Abi::Aapcs { unwind }, - ExternAbi::Win64 { unwind } => Abi::Win64 { unwind }, - ExternAbi::SysV64 { unwind } => Abi::SysV64 { unwind }, - ExternAbi::PtxKernel => Abi::PtxKernel, - ExternAbi::GpuKernel => Abi::GpuKernel, - ExternAbi::Msp430Interrupt => Abi::Msp430Interrupt, - ExternAbi::X86Interrupt => Abi::X86Interrupt, - ExternAbi::EfiApi => Abi::EfiApi, - ExternAbi::AvrInterrupt => Abi::AvrInterrupt, - ExternAbi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt, - ExternAbi::CmseNonSecureCall => Abi::CCmseNonSecureCall, - ExternAbi::CmseNonSecureEntry => Abi::CCmseNonSecureEntry, - ExternAbi::System { unwind } => Abi::System { unwind }, - ExternAbi::RustCall => Abi::RustCall, - ExternAbi::Unadjusted => Abi::Unadjusted, - ExternAbi::RustCold => Abi::RustCold, - ExternAbi::RustInvalid => Abi::RustInvalid, - ExternAbi::RiscvInterruptM => Abi::RiscvInterruptM, - ExternAbi::RiscvInterruptS => Abi::RiscvInterruptS, - ExternAbi::Custom => Abi::Custom, - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule { - type T = stable_mir::ty::ForeignModule; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - stable_mir::ty::ForeignModule { - def_id: tables.foreign_module_def(self.def_id), - abi: self.abi.stable(tables, cx), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::AssocKind { - type T = stable_mir::ty::AssocKind; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::{AssocKind, AssocTypeData}; - match *self { - ty::AssocKind::Const { name } => AssocKind::Const { name: name.to_string() }, - ty::AssocKind::Fn { name, has_self } => { - AssocKind::Fn { name: name.to_string(), has_self } - } - ty::AssocKind::Type { data } => AssocKind::Type { - data: match data { - ty::AssocTypeData::Normal(name) => AssocTypeData::Normal(name.to_string()), - ty::AssocTypeData::Rpitit(rpitit) => { - AssocTypeData::Rpitit(rpitit.stable(tables, cx)) - } - }, - }, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::AssocItemContainer { - type T = stable_mir::ty::AssocItemContainer; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use stable_mir::ty::AssocItemContainer; - match self { - ty::AssocItemContainer::Trait => AssocItemContainer::Trait, - ty::AssocItemContainer::Impl => AssocItemContainer::Impl, - } - } -} - -impl<'tcx> Stable<'tcx> for ty::AssocItem { - type T = stable_mir::ty::AssocItem; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - stable_mir::ty::AssocItem { - def_id: tables.assoc_def(self.def_id), - kind: self.kind.stable(tables, cx), - container: self.container.stable(tables, cx), - trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)), - } - } -} - -impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData { - type T = stable_mir::ty::ImplTraitInTraitData; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - _: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - use stable_mir::ty::ImplTraitInTraitData; - match self { - ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => { - ImplTraitInTraitData::Trait { - fn_def_id: tables.fn_def(*fn_def_id), - opaque_def_id: tables.opaque_def(*opaque_def_id), - } - } - ty::ImplTraitInTraitData::Impl { fn_def_id } => { - ImplTraitInTraitData::Impl { fn_def_id: tables.fn_def(*fn_def_id) } - } - } - } -} - -impl<'tcx> Stable<'tcx> for rustc_middle::ty::util::Discr<'tcx> { - type T = stable_mir::ty::Discr; - - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T { - stable_mir::ty::Discr { val: self.val, ty: self.ty.stable(tables, cx) } - } -} diff --git a/compiler/rustc_smir/src/stable_mir/unstable/mod.rs b/compiler/rustc_smir/src/stable_mir/unstable/mod.rs deleted file mode 100644 index 77a772019eb..00000000000 --- a/compiler/rustc_smir/src/stable_mir/unstable/mod.rs +++ /dev/null @@ -1,210 +0,0 @@ -//! Module that collects the things that have no stability guarantees. -//! -//! We want to keep StableMIR definitions and logic separate from -//! any sort of conversion and usage of internal rustc code. So we -//! restrict the usage of internal items to be inside this module. - -use std::marker::PointeeSized; - -use rustc_hir::def::DefKind; -use rustc_middle::ty::{List, Ty, TyCtxt}; -use rustc_middle::{mir, ty}; -use rustc_smir::Tables; -use rustc_smir::context::{ - SmirCtxt, SmirExistentialProjection, SmirExistentialTraitRef, SmirTraitRef, -}; -use stable_mir::{CtorKind, ItemKind}; - -use super::compiler_interface::BridgeTys; -use crate::{rustc_smir, stable_mir}; - -pub(crate) mod convert; - -impl<'tcx, T: InternalCx<'tcx>> SmirExistentialProjection<'tcx> for T { - fn new_from_args( - &self, - def_id: rustc_span::def_id::DefId, - args: ty::GenericArgsRef<'tcx>, - term: ty::Term<'tcx>, - ) -> ty::ExistentialProjection<'tcx> { - ty::ExistentialProjection::new_from_args(self.tcx(), def_id, args, term) - } -} - -impl<'tcx, T: InternalCx<'tcx>> SmirExistentialTraitRef<'tcx> for T { - fn new_from_args( - &self, - trait_def_id: rustc_span::def_id::DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> ty::ExistentialTraitRef<'tcx> { - ty::ExistentialTraitRef::new_from_args(self.tcx(), trait_def_id, args) - } -} - -impl<'tcx, T: InternalCx<'tcx>> SmirTraitRef<'tcx> for T { - fn new_from_args( - &self, - trait_def_id: rustc_span::def_id::DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> ty::TraitRef<'tcx> { - ty::TraitRef::new_from_args(self.tcx(), trait_def_id, args) - } -} - -impl<'tcx> InternalCx<'tcx> for TyCtxt<'tcx> { - fn tcx(self) -> TyCtxt<'tcx> { - self - } - - fn lift<T: ty::Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted> { - TyCtxt::lift(self, value) - } - - fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output - where - I: Iterator<Item = T>, - T: ty::CollectAndApply<ty::GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>, - { - TyCtxt::mk_args_from_iter(self, iter) - } - - fn mk_pat(self, v: ty::PatternKind<'tcx>) -> ty::Pattern<'tcx> { - TyCtxt::mk_pat(self, v) - } - - fn mk_poly_existential_predicates( - self, - eps: &[ty::PolyExistentialPredicate<'tcx>], - ) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> { - TyCtxt::mk_poly_existential_predicates(self, eps) - } - - fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> { - TyCtxt::mk_type_list(self, v) - } - - fn lifetimes_re_erased(self) -> ty::Region<'tcx> { - self.lifetimes.re_erased - } - - fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output - where - I: Iterator<Item = T>, - T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>, - { - TyCtxt::mk_bound_variable_kinds_from_iter(self, iter) - } - - fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List<mir::PlaceElem<'tcx>> { - TyCtxt::mk_place_elems(self, v) - } - - fn adt_def(self, def_id: rustc_hir::def_id::DefId) -> ty::AdtDef<'tcx> { - self.adt_def(def_id) - } -} - -/// Trait that defines the methods that are fine to call from [`RustcInternal`]. -/// -/// This trait is only for [`RustcInternal`]. Any other other access to rustc's internals -/// should go through [`crate::rustc_smir::context::SmirCtxt`]. -pub trait InternalCx<'tcx>: Copy + Clone { - fn tcx(self) -> TyCtxt<'tcx>; - - fn lift<T: ty::Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted>; - - fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output - where - I: Iterator<Item = T>, - T: ty::CollectAndApply<ty::GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>; - - fn mk_pat(self, v: ty::PatternKind<'tcx>) -> ty::Pattern<'tcx>; - - fn mk_poly_existential_predicates( - self, - eps: &[ty::PolyExistentialPredicate<'tcx>], - ) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>>; - - fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>>; - - fn lifetimes_re_erased(self) -> ty::Region<'tcx>; - - fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output - where - I: Iterator<Item = T>, - T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>; - - fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List<mir::PlaceElem<'tcx>>; - - fn adt_def(self, def_id: rustc_hir::def_id::DefId) -> ty::AdtDef<'tcx>; -} - -/// Trait used to convert between an internal MIR type to a Stable MIR type. -/// -/// This trait is currently exposed to users so they can have interoperability between internal MIR -/// and StableMIR constructs. However, they should be used seldom and they have no influence -/// in this crate semver. -#[doc(hidden)] -pub trait Stable<'tcx>: PointeeSized { - /// The stable representation of the type implementing Stable. - type T; - /// Converts an object to the equivalent Stable MIR representation. - fn stable<'cx>( - &self, - tables: &mut Tables<'cx, BridgeTys>, - cx: &SmirCtxt<'cx, BridgeTys>, - ) -> Self::T; -} - -/// Trait used to translate a stable construct to its rustc counterpart. -/// -/// This is basically a mirror of [Stable]. -/// -/// This trait is currently exposed to users so they can have interoperability between internal MIR -/// and StableMIR constructs. They should be used seldom as they have no stability guarantees. -#[doc(hidden)] -pub trait RustcInternal { - type T<'tcx>; - fn internal<'tcx>( - &self, - tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx>; -} - -pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind { - match kind { - DefKind::Mod - | DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::Variant - | DefKind::Trait - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::TraitAlias - | DefKind::AssocTy - | DefKind::TyParam - | DefKind::ConstParam - | DefKind::Macro(_) - | DefKind::ExternCrate - | DefKind::Use - | DefKind::ForeignMod - | DefKind::OpaqueTy - | DefKind::Field - | DefKind::LifetimeParam - | DefKind::Impl { .. } - | DefKind::GlobalAsm => { - unreachable!("Not a valid item kind: {kind:?}"); - } - DefKind::Closure | DefKind::AssocFn | DefKind::Fn | DefKind::SyntheticCoroutineBody => { - ItemKind::Fn - } - DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => { - ItemKind::Const - } - DefKind::Static { .. } => ItemKind::Static, - DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const), - DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn), - } -} diff --git a/compiler/rustc_smir/src/stable_mir/visitor.rs b/compiler/rustc_smir/src/stable_mir/visitor.rs deleted file mode 100644 index 31a53d1b19d..00000000000 --- a/compiler/rustc_smir/src/stable_mir/visitor.rs +++ /dev/null @@ -1,226 +0,0 @@ -use std::ops::ControlFlow; - -use stable_mir::Opaque; -use stable_mir::ty::TyConst; - -use super::ty::{ - Allocation, Binder, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, - MirConst, Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst, -}; -use crate::stable_mir; - -pub trait Visitor: Sized { - type Break; - fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break> { - ty.super_visit(self) - } - fn visit_const(&mut self, c: &TyConst) -> ControlFlow<Self::Break> { - c.super_visit(self) - } - fn visit_reg(&mut self, reg: &Region) -> ControlFlow<Self::Break> { - reg.super_visit(self) - } -} - -pub trait Visitable { - fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - self.super_visit(visitor) - } - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break>; -} - -impl Visitable for Ty { - fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - visitor.visit_ty(self) - } - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - match self.kind() { - super::ty::TyKind::RigidTy(ty) => ty.visit(visitor)?, - super::ty::TyKind::Alias(_, alias) => alias.args.visit(visitor)?, - super::ty::TyKind::Param(_) | super::ty::TyKind::Bound(_, _) => {} - } - ControlFlow::Continue(()) - } -} - -impl Visitable for TyConst { - fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - visitor.visit_const(self) - } - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - match &self.kind { - super::ty::TyConstKind::Param(_) | super::ty::TyConstKind::Bound(_, _) => {} - super::ty::TyConstKind::Unevaluated(_, args) => args.visit(visitor)?, - super::ty::TyConstKind::Value(ty, alloc) => { - alloc.visit(visitor)?; - ty.visit(visitor)?; - } - super::ty::TyConstKind::ZSTValue(ty) => ty.visit(visitor)?, - } - ControlFlow::Continue(()) - } -} - -impl Visitable for MirConst { - fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - self.super_visit(visitor) - } - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - match &self.kind() { - super::ty::ConstantKind::Ty(ct) => ct.visit(visitor)?, - super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor)?, - super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor)?, - super::ty::ConstantKind::Param(_) | super::ty::ConstantKind::ZeroSized => {} - } - self.ty().visit(visitor) - } -} - -impl Visitable for Opaque { - fn super_visit<V: Visitor>(&self, _visitor: &mut V) -> ControlFlow<V::Break> { - ControlFlow::Continue(()) - } -} - -impl Visitable for Allocation { - fn super_visit<V: Visitor>(&self, _visitor: &mut V) -> ControlFlow<V::Break> { - ControlFlow::Continue(()) - } -} - -impl Visitable for UnevaluatedConst { - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - let UnevaluatedConst { def, args, promoted } = self; - def.visit(visitor)?; - args.visit(visitor)?; - promoted.visit(visitor) - } -} - -impl Visitable for ConstDef { - fn super_visit<V: Visitor>(&self, _visitor: &mut V) -> ControlFlow<V::Break> { - ControlFlow::Continue(()) - } -} - -impl<T: Visitable> Visitable for Option<T> { - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - match self { - Some(val) => val.visit(visitor), - None => ControlFlow::Continue(()), - } - } -} - -impl Visitable for Promoted { - fn super_visit<V: Visitor>(&self, _visitor: &mut V) -> ControlFlow<V::Break> { - ControlFlow::Continue(()) - } -} - -impl Visitable for GenericArgs { - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - self.0.visit(visitor) - } -} - -impl Visitable for Region { - fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - visitor.visit_reg(self) - } - - fn super_visit<V: Visitor>(&self, _: &mut V) -> ControlFlow<V::Break> { - ControlFlow::Continue(()) - } -} - -impl Visitable for GenericArgKind { - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - match self { - GenericArgKind::Lifetime(lt) => lt.visit(visitor), - GenericArgKind::Type(t) => t.visit(visitor), - GenericArgKind::Const(c) => c.visit(visitor), - } - } -} - -impl Visitable for RigidTy { - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - match self { - RigidTy::Bool - | RigidTy::Char - | RigidTy::Int(_) - | RigidTy::Uint(_) - | RigidTy::Float(_) - | RigidTy::Never - | RigidTy::Foreign(_) - | RigidTy::Str => ControlFlow::Continue(()), - RigidTy::Array(t, c) => { - t.visit(visitor)?; - c.visit(visitor) - } - RigidTy::Pat(t, _p) => t.visit(visitor), - RigidTy::Slice(inner) => inner.visit(visitor), - RigidTy::RawPtr(ty, _) => ty.visit(visitor), - RigidTy::Ref(reg, ty, _) => { - reg.visit(visitor)?; - ty.visit(visitor) - } - RigidTy::Adt(_, args) - | RigidTy::Closure(_, args) - | RigidTy::Coroutine(_, args, _) - | RigidTy::CoroutineWitness(_, args) - | RigidTy::CoroutineClosure(_, args) - | RigidTy::FnDef(_, args) => args.visit(visitor), - RigidTy::FnPtr(sig) => sig.visit(visitor), - RigidTy::Dynamic(pred, r, _) => { - pred.visit(visitor)?; - r.visit(visitor) - } - RigidTy::Tuple(fields) => fields.visit(visitor), - } - } -} - -impl<T: Visitable> Visitable for Vec<T> { - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - for arg in self { - arg.visit(visitor)?; - } - ControlFlow::Continue(()) - } -} - -impl<T: Visitable> Visitable for Binder<T> { - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - self.value.visit(visitor) - } -} - -impl Visitable for ExistentialPredicate { - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - match self { - ExistentialPredicate::Trait(tr) => tr.generic_args.visit(visitor), - ExistentialPredicate::Projection(p) => { - p.term.visit(visitor)?; - p.generic_args.visit(visitor) - } - ExistentialPredicate::AutoTrait(_) => ControlFlow::Continue(()), - } - } -} - -impl Visitable for TermKind { - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - match self { - TermKind::Type(t) => t.visit(visitor), - TermKind::Const(c) => c.visit(visitor), - } - } -} - -impl Visitable for FnSig { - fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> { - self.inputs_and_output.visit(visitor) - } -} | 
