summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_smir
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /compiler/rustc_smir
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz
rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_smir')
-rw-r--r--compiler/rustc_smir/Cargo.toml6
-rw-r--r--compiler/rustc_smir/rust-toolchain.toml2
-rw-r--r--compiler/rustc_smir/src/lib.rs15
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs110
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs1120
-rw-r--r--compiler/rustc_smir/src/stable_mir/mir/body.rs322
-rw-r--r--compiler/rustc_smir/src/stable_mir/mod.rs28
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs414
8 files changed, 1848 insertions, 169 deletions
diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml
index a6e6de5f7..80d4e7ed0 100644
--- a/compiler/rustc_smir/Cargo.toml
+++ b/compiler/rustc_smir/Cargo.toml
@@ -4,14 +4,18 @@ version = "0.0.0"
edition = "2021"
[dependencies]
-rustc_hir = { path = "../rustc_hir" }
+# Use optional dependencies for rustc_* in order to support building this crate separately.
+rustc_hir = { path = "../rustc_hir", optional = true }
rustc_middle = { path = "../rustc_middle", optional = true }
rustc_span = { path = "../rustc_span", optional = true }
+rustc_target = { path = "../rustc_target", optional = true }
tracing = "0.1"
scoped-tls = "1.0"
[features]
default = [
+ "rustc_hir",
"rustc_middle",
"rustc_span",
+ "rustc_target",
]
diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/rustc_smir/rust-toolchain.toml
index 157dfd620..d75e8e33b 100644
--- a/compiler/rustc_smir/rust-toolchain.toml
+++ b/compiler/rustc_smir/rust-toolchain.toml
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2023-02-28"
+channel = "nightly-2023-06-14"
components = [ "rustfmt", "rustc-dev" ]
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
index fb03633b9..8cb533c8d 100644
--- a/compiler/rustc_smir/src/lib.rs
+++ b/compiler/rustc_smir/src/lib.rs
@@ -1,6 +1,6 @@
//! The WIP stable interface to rustc internals.
//!
-//! For more information see https://github.com/rust-lang/project-stable-mir
+//! For more information see <https://github.com/rust-lang/project-stable-mir>
//!
//! # Note
//!
@@ -11,8 +11,19 @@
test(attr(allow(unused_variables), deny(warnings)))
)]
#![cfg_attr(not(feature = "default"), feature(rustc_private))]
-#![feature(local_key_cell_methods)]
#![feature(ptr_metadata)]
+#![feature(type_alias_impl_trait)] // Used to define opaque types.
+#![feature(intra_doc_pointers)]
+
+// Declare extern rustc_* crates to enable building this crate separately from the compiler.
+#[cfg(not(feature = "default"))]
+extern crate rustc_hir;
+#[cfg(not(feature = "default"))]
+extern crate rustc_middle;
+#[cfg(not(feature = "default"))]
+extern crate rustc_span;
+#[cfg(not(feature = "default"))]
+extern crate rustc_target;
pub mod rustc_internal;
pub mod stable_mir;
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 609a04d26..078ff6744 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -3,6 +3,9 @@
//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
//! until stable MIR is complete.
+use std::fmt::Debug;
+use std::string::ToString;
+
use crate::{
rustc_smir::Tables,
stable_mir::{self, with},
@@ -24,21 +27,117 @@ pub fn crate_item(did: DefId) -> stable_mir::CrateItem {
with_tables(|t| t.crate_item(did))
}
+pub fn adt_def(did: DefId) -> stable_mir::ty::AdtDef {
+ with_tables(|t| t.adt_def(did))
+}
+
+pub fn foreign_def(did: DefId) -> stable_mir::ty::ForeignDef {
+ with_tables(|t| t.foreign_def(did))
+}
+
+pub fn fn_def(did: DefId) -> stable_mir::ty::FnDef {
+ with_tables(|t| t.fn_def(did))
+}
+
+pub fn closure_def(did: DefId) -> stable_mir::ty::ClosureDef {
+ with_tables(|t| t.closure_def(did))
+}
+
+pub fn generator_def(did: DefId) -> stable_mir::ty::GeneratorDef {
+ with_tables(|t| t.generator_def(did))
+}
+
+pub fn alias_def(did: DefId) -> stable_mir::ty::AliasDef {
+ with_tables(|t| t.alias_def(did))
+}
+
+pub fn param_def(did: DefId) -> stable_mir::ty::ParamDef {
+ with_tables(|t| t.param_def(did))
+}
+
+pub fn br_named_def(did: DefId) -> stable_mir::ty::BrNamedDef {
+ with_tables(|t| t.br_named_def(did))
+}
+
+pub fn trait_def(did: DefId) -> stable_mir::ty::TraitDef {
+ with_tables(|t| t.trait_def(did))
+}
+
+pub fn impl_def(did: DefId) -> stable_mir::ty::ImplDef {
+ with_tables(|t| t.impl_def(did))
+}
+
impl<'tcx> Tables<'tcx> {
pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
self.def_ids[item.0]
}
+ pub fn trait_def_id(&self, trait_def: &stable_mir::ty::TraitDef) -> DefId {
+ self.def_ids[trait_def.0]
+ }
+
+ pub fn impl_trait_def_id(&self, impl_def: &stable_mir::ty::ImplDef) -> DefId {
+ self.def_ids[impl_def.0]
+ }
+
pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem {
+ stable_mir::CrateItem(self.create_def_id(did))
+ }
+
+ pub fn adt_def(&mut self, did: DefId) -> stable_mir::ty::AdtDef {
+ stable_mir::ty::AdtDef(self.create_def_id(did))
+ }
+
+ pub fn foreign_def(&mut self, did: DefId) -> stable_mir::ty::ForeignDef {
+ stable_mir::ty::ForeignDef(self.create_def_id(did))
+ }
+
+ pub fn fn_def(&mut self, did: DefId) -> stable_mir::ty::FnDef {
+ stable_mir::ty::FnDef(self.create_def_id(did))
+ }
+
+ pub fn closure_def(&mut self, did: DefId) -> stable_mir::ty::ClosureDef {
+ stable_mir::ty::ClosureDef(self.create_def_id(did))
+ }
+
+ pub fn generator_def(&mut self, did: DefId) -> stable_mir::ty::GeneratorDef {
+ stable_mir::ty::GeneratorDef(self.create_def_id(did))
+ }
+
+ pub fn alias_def(&mut self, did: DefId) -> stable_mir::ty::AliasDef {
+ stable_mir::ty::AliasDef(self.create_def_id(did))
+ }
+
+ pub fn param_def(&mut self, did: DefId) -> stable_mir::ty::ParamDef {
+ stable_mir::ty::ParamDef(self.create_def_id(did))
+ }
+
+ pub fn br_named_def(&mut self, did: DefId) -> stable_mir::ty::BrNamedDef {
+ stable_mir::ty::BrNamedDef(self.create_def_id(did))
+ }
+
+ pub fn trait_def(&mut self, did: DefId) -> stable_mir::ty::TraitDef {
+ stable_mir::ty::TraitDef(self.create_def_id(did))
+ }
+
+ pub fn const_def(&mut self, did: DefId) -> stable_mir::ty::ConstDef {
+ stable_mir::ty::ConstDef(self.create_def_id(did))
+ }
+
+ pub fn impl_def(&mut self, did: DefId) -> stable_mir::ty::ImplDef {
+ stable_mir::ty::ImplDef(self.create_def_id(did))
+ }
+
+ fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
// FIXME: this becomes inefficient when we have too many ids
for (i, &d) in self.def_ids.iter().enumerate() {
if d == did {
- return stable_mir::CrateItem(i);
+ return i;
}
}
let id = self.def_ids.len();
self.def_ids.push(did);
- stable_mir::CrateItem(id)
+ id
}
}
@@ -49,3 +148,10 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
crate::stable_mir::run(Tables { tcx, def_ids: vec![], types: vec![] }, f);
}
+
+/// A type that provides internal information but that can still be used for debug purpose.
+pub type Opaque = impl Debug + ToString + Clone;
+
+pub(crate) fn opaque<T: Debug>(value: &T) -> Opaque {
+ format!("{value:?}")
+}
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 85d5bb00c..06b37008e 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -7,11 +7,19 @@
//!
//! For now, we are developing everything inside `rustc`, thus, we keep this module private.
-use crate::stable_mir::ty::{FloatTy, IntTy, RigidTy, TyKind, UintTy};
+use crate::rustc_internal::{self, opaque};
+use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx};
+use crate::stable_mir::ty::{
+ allocation_filter, new_allocation, Const, FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy,
+};
use crate::stable_mir::{self, Context};
-use rustc_middle::mir;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_hir as hir;
+use rustc_middle::mir::coverage::CodeRegion;
+use rustc_middle::mir::interpret::alloc_range;
+use rustc_middle::mir::{self, ConstantKind};
+use rustc_middle::ty::{self, Ty, TyCtxt, Variance};
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_target::abi::FieldIdx;
use tracing::debug;
impl<'tcx> Context for Tables<'tcx> {
@@ -36,6 +44,35 @@ impl<'tcx> Context for Tables<'tcx> {
fn entry_fn(&mut self) -> Option<stable_mir::CrateItem> {
Some(self.crate_item(self.tcx.entry_fn(())?.0))
}
+
+ fn all_trait_decls(&mut self) -> stable_mir::TraitDecls {
+ self.tcx
+ .traits(LOCAL_CRATE)
+ .iter()
+ .map(|trait_def_id| self.trait_def(*trait_def_id))
+ .collect()
+ }
+
+ fn trait_decl(&mut self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
+ let def_id = self.trait_def_id(trait_def);
+ let trait_def = self.tcx.trait_def(def_id);
+ trait_def.stable(self)
+ }
+
+ fn all_trait_impls(&mut self) -> stable_mir::ImplTraitDecls {
+ self.tcx
+ .trait_impls_in_crate(LOCAL_CRATE)
+ .iter()
+ .map(|impl_def_id| self.impl_def(*impl_def_id))
+ .collect()
+ }
+
+ fn trait_impl(&mut self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
+ let def_id = self.impl_trait_def_id(impl_def);
+ let impl_trait = self.tcx.impl_trait_ref(def_id).unwrap();
+ impl_trait.stable(self)
+ }
+
fn mir_body(&mut self, item: &stable_mir::CrateItem) -> stable_mir::mir::Body {
let def_id = self.item_def_id(item);
let mir = self.tcx.optimized_mir(def_id);
@@ -44,8 +81,12 @@ impl<'tcx> Context for Tables<'tcx> {
.basic_blocks
.iter()
.map(|block| stable_mir::mir::BasicBlock {
- terminator: block.terminator().stable(),
- statements: block.statements.iter().map(mir::Statement::stable).collect(),
+ terminator: block.terminator().stable(self),
+ statements: block
+ .statements
+ .iter()
+ .map(|statement| statement.stable(self))
+ .collect(),
})
.collect(),
locals: mir.local_decls.iter().map(|decl| self.intern_ty(decl.ty)).collect(),
@@ -57,7 +98,8 @@ impl<'tcx> Context for Tables<'tcx> {
}
fn ty_kind(&mut self, ty: crate::stable_mir::ty::Ty) -> TyKind {
- self.rustc_ty_to_ty(self.types[ty.0])
+ let ty = self.types[ty.0];
+ ty.stable(self)
}
}
@@ -68,57 +110,6 @@ pub struct Tables<'tcx> {
}
impl<'tcx> Tables<'tcx> {
- fn rustc_ty_to_ty(&mut self, ty: Ty<'tcx>) -> TyKind {
- match ty.kind() {
- ty::Bool => TyKind::RigidTy(RigidTy::Bool),
- ty::Char => TyKind::RigidTy(RigidTy::Char),
- ty::Int(int_ty) => match int_ty {
- ty::IntTy::Isize => TyKind::RigidTy(RigidTy::Int(IntTy::Isize)),
- ty::IntTy::I8 => TyKind::RigidTy(RigidTy::Int(IntTy::I8)),
- ty::IntTy::I16 => TyKind::RigidTy(RigidTy::Int(IntTy::I16)),
- ty::IntTy::I32 => TyKind::RigidTy(RigidTy::Int(IntTy::I32)),
- ty::IntTy::I64 => TyKind::RigidTy(RigidTy::Int(IntTy::I64)),
- ty::IntTy::I128 => TyKind::RigidTy(RigidTy::Int(IntTy::I128)),
- },
- ty::Uint(uint_ty) => match uint_ty {
- ty::UintTy::Usize => TyKind::RigidTy(RigidTy::Uint(UintTy::Usize)),
- ty::UintTy::U8 => TyKind::RigidTy(RigidTy::Uint(UintTy::U8)),
- ty::UintTy::U16 => TyKind::RigidTy(RigidTy::Uint(UintTy::U16)),
- ty::UintTy::U32 => TyKind::RigidTy(RigidTy::Uint(UintTy::U32)),
- ty::UintTy::U64 => TyKind::RigidTy(RigidTy::Uint(UintTy::U64)),
- ty::UintTy::U128 => TyKind::RigidTy(RigidTy::Uint(UintTy::U128)),
- },
- ty::Float(float_ty) => match float_ty {
- ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)),
- ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)),
- },
- ty::Adt(_, _) => todo!(),
- ty::Foreign(_) => todo!(),
- ty::Str => todo!(),
- ty::Array(_, _) => todo!(),
- ty::Slice(_) => todo!(),
- ty::RawPtr(_) => todo!(),
- ty::Ref(_, _, _) => todo!(),
- ty::FnDef(_, _) => todo!(),
- ty::FnPtr(_) => todo!(),
- ty::Placeholder(..) => todo!(),
- ty::Dynamic(_, _, _) => todo!(),
- ty::Closure(_, _) => todo!(),
- ty::Generator(_, _, _) => todo!(),
- ty::GeneratorWitness(_) => todo!(),
- ty::GeneratorWitnessMIR(_, _) => todo!(),
- ty::Never => todo!(),
- ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
- fields.iter().map(|ty| self.intern_ty(ty)).collect(),
- )),
- ty::Alias(_, _) => todo!(),
- ty::Param(_) => todo!(),
- ty::Bound(_, _) => todo!(),
- ty::Infer(_) => todo!(),
- ty::Error(_) => todo!(),
- }
- }
-
fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty {
if let Some(id) = self.types.iter().position(|&t| t == ty) {
return stable_mir::ty::Ty(id);
@@ -137,78 +128,343 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local }
}
-pub trait Stable {
+/// Trait used to convert between an internal MIR type to a Stable MIR type.
+pub(crate) trait Stable<'tcx> {
+ /// The stable representation of the type implementing Stable.
type T;
- fn stable(&self) -> Self::T;
+ /// Converts an object to the equivalent Stable MIR representation.
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T;
}
-impl<'tcx> Stable for mir::Statement<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
type T = stable_mir::mir::Statement;
- fn stable(&self) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use rustc_middle::mir::StatementKind::*;
match &self.kind {
Assign(assign) => {
- stable_mir::mir::Statement::Assign(assign.0.stable(), assign.1.stable())
- }
- FakeRead(_) => todo!(),
- SetDiscriminant { .. } => todo!(),
- Deinit(_) => todo!(),
- StorageLive(_) => todo!(),
- StorageDead(_) => todo!(),
- Retag(_, _) => todo!(),
- PlaceMention(_) => todo!(),
- AscribeUserType(_, _) => todo!(),
- Coverage(_) => todo!(),
- Intrinsic(_) => todo!(),
- ConstEvalCounter => todo!(),
+ stable_mir::mir::Statement::Assign(assign.0.stable(tables), assign.1.stable(tables))
+ }
+ FakeRead(fake_read_place) => stable_mir::mir::Statement::FakeRead(
+ fake_read_place.0.stable(tables),
+ fake_read_place.1.stable(tables),
+ ),
+ SetDiscriminant { place: plc, variant_index: idx } => {
+ stable_mir::mir::Statement::SetDiscriminant {
+ place: plc.as_ref().stable(tables),
+ variant_index: idx.stable(tables),
+ }
+ }
+ Deinit(place) => stable_mir::mir::Statement::Deinit(place.stable(tables)),
+ StorageLive(place) => stable_mir::mir::Statement::StorageLive(place.stable(tables)),
+ StorageDead(place) => stable_mir::mir::Statement::StorageDead(place.stable(tables)),
+ Retag(retag, place) => {
+ stable_mir::mir::Statement::Retag(retag.stable(tables), place.stable(tables))
+ }
+ PlaceMention(place) => stable_mir::mir::Statement::PlaceMention(place.stable(tables)),
+ AscribeUserType(place_projection, variance) => {
+ stable_mir::mir::Statement::AscribeUserType {
+ place: place_projection.as_ref().0.stable(tables),
+ projections: place_projection.as_ref().1.stable(tables),
+ variance: variance.stable(tables),
+ }
+ }
+ Coverage(coverage) => stable_mir::mir::Statement::Coverage(stable_mir::mir::Coverage {
+ kind: coverage.kind.stable(tables),
+ code_region: coverage.code_region.as_ref().map(|reg| reg.stable(tables)),
+ }),
+ Intrinsic(intrinstic) => {
+ stable_mir::mir::Statement::Intrinsic(intrinstic.stable(tables))
+ }
+ ConstEvalCounter => stable_mir::mir::Statement::ConstEvalCounter,
Nop => stable_mir::mir::Statement::Nop,
}
}
}
-impl<'tcx> Stable for mir::Rvalue<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
type T = stable_mir::mir::Rvalue;
- fn stable(&self) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use mir::Rvalue::*;
match self {
- Use(op) => stable_mir::mir::Rvalue::Use(op.stable()),
- Repeat(_, _) => todo!(),
- Ref(_, _, _) => todo!(),
- ThreadLocalRef(_) => todo!(),
- AddressOf(_, _) => todo!(),
- Len(_) => todo!(),
- Cast(_, _, _) => todo!(),
- BinaryOp(_, _) => todo!(),
+ Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)),
+ Repeat(op, len) => {
+ let cnst = ConstantKind::from_const(*len, tables.tcx);
+ let len = Const { literal: cnst.stable(tables) };
+ stable_mir::mir::Rvalue::Repeat(op.stable(tables), len)
+ }
+ Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref(
+ opaque(region),
+ kind.stable(tables),
+ place.stable(tables),
+ ),
+ ThreadLocalRef(def_id) => {
+ stable_mir::mir::Rvalue::ThreadLocalRef(rustc_internal::crate_item(*def_id))
+ }
+ AddressOf(mutability, place) => {
+ stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables))
+ }
+ Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables)),
+ Cast(cast_kind, op, ty) => stable_mir::mir::Rvalue::Cast(
+ cast_kind.stable(tables),
+ op.stable(tables),
+ tables.intern_ty(*ty),
+ ),
+ BinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::BinaryOp(
+ bin_op.stable(tables),
+ ops.0.stable(tables),
+ ops.1.stable(tables),
+ ),
CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp(
- bin_op.stable(),
- ops.0.stable(),
- ops.1.stable(),
+ bin_op.stable(tables),
+ ops.0.stable(tables),
+ ops.1.stable(tables),
+ ),
+ NullaryOp(null_op, ty) => {
+ stable_mir::mir::Rvalue::NullaryOp(null_op.stable(tables), tables.intern_ty(*ty))
+ }
+ UnaryOp(un_op, op) => {
+ stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables), op.stable(tables))
+ }
+ Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables)),
+ Aggregate(agg_kind, operands) => {
+ let operands = operands.iter().map(|op| op.stable(tables)).collect();
+ stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables), operands)
+ }
+ ShallowInitBox(op, ty) => {
+ stable_mir::mir::Rvalue::ShallowInitBox(op.stable(tables), tables.intern_ty(*ty))
+ }
+ CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables)),
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::Mutability {
+ type T = stable_mir::mir::Mutability;
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ use mir::Mutability::*;
+ match *self {
+ Not => stable_mir::mir::Mutability::Not,
+ Mut => stable_mir::mir::Mutability::Mut,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::BorrowKind {
+ type T = stable_mir::mir::BorrowKind;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use mir::BorrowKind::*;
+ match *self {
+ Shared => stable_mir::mir::BorrowKind::Shared,
+ Shallow => stable_mir::mir::BorrowKind::Shallow,
+ Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) },
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
+ type T = stable_mir::mir::MutBorrowKind;
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ use 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::NullOp<'tcx> {
+ type T = stable_mir::mir::NullOp;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use 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)).collect(),
),
- NullaryOp(_, _) => todo!(),
- UnaryOp(un_op, op) => stable_mir::mir::Rvalue::UnaryOp(un_op.stable(), op.stable()),
- Discriminant(_) => todo!(),
- Aggregate(_, _) => todo!(),
- ShallowInitBox(_, _) => todo!(),
- CopyForDeref(_) => todo!(),
}
}
}
-impl<'tcx> Stable for mir::Operand<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::CastKind {
+ type T = stable_mir::mir::CastKind;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use mir::CastKind::*;
+ match self {
+ PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress,
+ PointerFromExposedAddress => stable_mir::mir::CastKind::PointerFromExposedAddress,
+ PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
+ DynStar => stable_mir::mir::CastKind::DynStar,
+ 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 ty::AliasKind {
+ type T = stable_mir::ty::AliasKind;
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ use ty::AliasKind::*;
+ match self {
+ Projection => stable_mir::ty::AliasKind::Projection,
+ Inherent => stable_mir::ty::AliasKind::Inherent,
+ Opaque => stable_mir::ty::AliasKind::Opaque,
+ Weak => stable_mir::ty::AliasKind::Weak,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> {
+ type T = stable_mir::ty::AliasTy;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ let ty::AliasTy { args, def_id, .. } = self;
+ stable_mir::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables) }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::DynKind {
+ type T = stable_mir::ty::DynKind;
+
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ use ty::DynKind;
+ match self {
+ DynKind::Dyn => stable_mir::ty::DynKind::Dyn,
+ DynKind::DynStar => stable_mir::ty::DynKind::DynStar,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> {
+ type T = stable_mir::ty::ExistentialPredicate;
+
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::ExistentialPredicate::*;
+ match self {
+ ty::ExistentialPredicate::Trait(existential_trait_ref) => {
+ Trait(existential_trait_ref.stable(tables))
+ }
+ ty::ExistentialPredicate::Projection(existential_projection) => {
+ Projection(existential_projection.stable(tables))
+ }
+ 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(&self, tables: &mut Tables<'tcx>) -> 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),
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
+ type T = stable_mir::ty::TermKind;
+
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::TermKind;
+ match self {
+ ty::TermKind::Ty(ty) => TermKind::Type(tables.intern_ty(*ty)),
+ ty::TermKind::Const(cnst) => {
+ let cnst = ConstantKind::from_const(*cnst, tables.tcx);
+ let cnst = Const { literal: cnst.stable(tables) };
+ TermKind::Const(cnst)
+ }
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> {
+ type T = stable_mir::ty::ExistentialProjection;
+
+ fn stable(&self, tables: &mut Tables<'tcx>) -> 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),
+ term: term.unpack().stable(tables),
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
+ type T = stable_mir::mir::PointerCoercion;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use ty::adjustment::PointerCoercion;
+ match self {
+ PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer,
+ PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer,
+ PointerCoercion::ClosureFnPointer(unsafety) => {
+ stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable(tables))
+ }
+ 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 rustc_hir::Unsafety {
+ type T = stable_mir::mir::Safety;
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ match self {
+ rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe,
+ rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::FakeReadCause {
+ type T = stable_mir::mir::FakeReadCause;
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ use 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 FieldIdx {
+ type T = usize;
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ self.as_usize()
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
type T = stable_mir::mir::Operand;
- fn stable(&self) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use mir::Operand::*;
match self {
- Copy(place) => stable_mir::mir::Operand::Copy(place.stable()),
- Move(place) => stable_mir::mir::Operand::Move(place.stable()),
+ Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables)),
+ Move(place) => stable_mir::mir::Operand::Move(place.stable(tables)),
Constant(c) => stable_mir::mir::Operand::Constant(c.to_string()),
}
}
}
-impl<'tcx> Stable for mir::Place<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
type T = stable_mir::mir::Place;
- fn stable(&self) -> Self::T {
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
stable_mir::mir::Place {
local: self.local.as_usize(),
projection: format!("{:?}", self.projection),
@@ -216,9 +472,113 @@ impl<'tcx> Stable for mir::Place<'tcx> {
}
}
-impl Stable for mir::UnwindAction {
+impl<'tcx> Stable<'tcx> for mir::coverage::CoverageKind {
+ type T = stable_mir::mir::CoverageKind;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use rustc_middle::mir::coverage::CoverageKind;
+ match self {
+ CoverageKind::Counter { function_source_hash, id } => {
+ stable_mir::mir::CoverageKind::Counter {
+ function_source_hash: *function_source_hash as usize,
+ id: opaque(id),
+ }
+ }
+ CoverageKind::Expression { id, lhs, op, rhs } => {
+ stable_mir::mir::CoverageKind::Expression {
+ id: opaque(id),
+ lhs: opaque(lhs),
+ op: op.stable(tables),
+ rhs: opaque(rhs),
+ }
+ }
+ CoverageKind::Unreachable => stable_mir::mir::CoverageKind::Unreachable,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::UserTypeProjection {
+ type T = stable_mir::mir::UserTypeProjection;
+
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ UserTypeProjection { base: self.base.as_usize(), projection: format!("{:?}", self.projs) }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::coverage::Op {
+ type T = stable_mir::mir::Op;
+
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ use rustc_middle::mir::coverage::Op::*;
+ match self {
+ Subtract => stable_mir::mir::Op::Subtract,
+ Add => stable_mir::mir::Op::Add,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::Local {
+ type T = stable_mir::mir::Local;
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ self.as_usize()
+ }
+}
+
+impl<'tcx> Stable<'tcx> for rustc_target::abi::VariantIdx {
+ type T = VariantIdx;
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ self.as_usize()
+ }
+}
+
+impl<'tcx> Stable<'tcx> for Variance {
+ type T = stable_mir::mir::Variance;
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ match self {
+ Variance::Bivariant => stable_mir::mir::Variance::Bivariant,
+ Variance::Contravariant => stable_mir::mir::Variance::Contravariant,
+ Variance::Covariant => stable_mir::mir::Variance::Covariant,
+ Variance::Invariant => stable_mir::mir::Variance::Invariant,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::RetagKind {
+ type T = stable_mir::mir::RetagKind;
+ fn stable(&self, _: &mut Tables<'tcx>) -> 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 ty::UserTypeAnnotationIndex {
+ type T = usize;
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ self.as_usize()
+ }
+}
+
+impl<'tcx> Stable<'tcx> for CodeRegion {
+ type T = stable_mir::mir::CodeRegion;
+
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ stable_mir::mir::CodeRegion {
+ file_name: self.file_name.as_str().to_string(),
+ start_line: self.start_line as usize,
+ start_col: self.start_col as usize,
+ end_line: self.end_line as usize,
+ end_col: self.end_col as usize,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::UnwindAction {
type T = stable_mir::mir::UnwindAction;
- fn stable(&self) -> Self::T {
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use rustc_middle::mir::UnwindAction;
match self {
UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
@@ -229,42 +589,68 @@ impl Stable for mir::UnwindAction {
}
}
-fn rustc_assert_msg_to_msg<'tcx>(
- assert_message: &rustc_middle::mir::AssertMessage<'tcx>,
-) -> stable_mir::mir::AssertMessage {
- use rustc_middle::mir::AssertKind;
- match assert_message {
- AssertKind::BoundsCheck { len, index } => {
- stable_mir::mir::AssertMessage::BoundsCheck { len: len.stable(), index: index.stable() }
- }
- AssertKind::Overflow(bin_op, op1, op2) => {
- stable_mir::mir::AssertMessage::Overflow(bin_op.stable(), op1.stable(), op2.stable())
- }
- AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()),
- AssertKind::DivisionByZero(op) => {
- stable_mir::mir::AssertMessage::DivisionByZero(op.stable())
- }
- AssertKind::RemainderByZero(op) => {
- stable_mir::mir::AssertMessage::RemainderByZero(op.stable())
- }
- AssertKind::ResumedAfterReturn(generator) => {
- stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable())
- }
- AssertKind::ResumedAfterPanic(generator) => {
- stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable())
+impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
+ type T = stable_mir::mir::NonDivergingIntrinsic;
+
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use rustc_middle::mir::NonDivergingIntrinsic;
+ match self {
+ NonDivergingIntrinsic::Assume(op) => {
+ stable_mir::mir::NonDivergingIntrinsic::Assume(op.stable(tables))
+ }
+ NonDivergingIntrinsic::CopyNonOverlapping(copy_non_overlapping) => {
+ stable_mir::mir::NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
+ src: copy_non_overlapping.src.stable(tables),
+ dst: copy_non_overlapping.dst.stable(tables),
+ count: copy_non_overlapping.count.stable(tables),
+ })
+ }
}
- AssertKind::MisalignedPointerDereference { required, found } => {
- stable_mir::mir::AssertMessage::MisalignedPointerDereference {
- required: required.stable(),
- found: found.stable(),
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
+ type T = stable_mir::mir::AssertMessage;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use rustc_middle::mir::AssertKind;
+ match self {
+ AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck {
+ len: len.stable(tables),
+ index: index.stable(tables),
+ },
+ AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow(
+ bin_op.stable(tables),
+ op1.stable(tables),
+ op2.stable(tables),
+ ),
+ AssertKind::OverflowNeg(op) => {
+ stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables))
+ }
+ AssertKind::DivisionByZero(op) => {
+ stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables))
+ }
+ AssertKind::RemainderByZero(op) => {
+ stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables))
+ }
+ AssertKind::ResumedAfterReturn(generator) => {
+ stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable(tables))
+ }
+ AssertKind::ResumedAfterPanic(generator) => {
+ stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable(tables))
+ }
+ AssertKind::MisalignedPointerDereference { required, found } => {
+ stable_mir::mir::AssertMessage::MisalignedPointerDereference {
+ required: required.stable(tables),
+ found: found.stable(tables),
+ }
}
}
}
}
-impl Stable for mir::BinOp {
+impl<'tcx> Stable<'tcx> for mir::BinOp {
type T = stable_mir::mir::BinOp;
- fn stable(&self) -> Self::T {
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use mir::BinOp;
match self {
BinOp::Add => stable_mir::mir::BinOp::Add,
@@ -293,9 +679,9 @@ impl Stable for mir::BinOp {
}
}
-impl Stable for mir::UnOp {
+impl<'tcx> Stable<'tcx> for mir::UnOp {
type T = stable_mir::mir::UnOp;
- fn stable(&self) -> Self::T {
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use mir::UnOp;
match self {
UnOp::Not => stable_mir::mir::UnOp::Not,
@@ -304,9 +690,43 @@ impl Stable for mir::UnOp {
}
}
-impl Stable for rustc_hir::GeneratorKind {
+impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
+ type T = stable_mir::mir::AggregateKind;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ match self {
+ mir::AggregateKind::Array(ty) => {
+ stable_mir::mir::AggregateKind::Array(tables.intern_ty(*ty))
+ }
+ 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(
+ rustc_internal::adt_def(*def_id),
+ var_idx.index(),
+ generic_arg.stable(tables),
+ 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(
+ rustc_internal::closure_def(*def_id),
+ generic_arg.stable(tables),
+ )
+ }
+ mir::AggregateKind::Generator(def_id, generic_arg, movability) => {
+ stable_mir::mir::AggregateKind::Generator(
+ rustc_internal::generator_def(*def_id),
+ generic_arg.stable(tables),
+ movability.stable(tables),
+ )
+ }
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for rustc_hir::GeneratorKind {
type T = stable_mir::mir::GeneratorKind;
- fn stable(&self) -> Self::T {
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
match self {
GeneratorKind::Async(async_gen) => {
@@ -322,35 +742,35 @@ impl Stable for rustc_hir::GeneratorKind {
}
}
-impl<'tcx> Stable for mir::InlineAsmOperand<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
type T = stable_mir::mir::InlineAsmOperand;
- fn stable(&self) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use rustc_middle::mir::InlineAsmOperand;
let (in_value, out_place) = match self {
- InlineAsmOperand::In { value, .. } => (Some(value.stable()), None),
- InlineAsmOperand::Out { place, .. } => (None, place.map(|place| place.stable())),
+ InlineAsmOperand::In { value, .. } => (Some(value.stable(tables)), None),
+ InlineAsmOperand::Out { place, .. } => (None, place.map(|place| place.stable(tables))),
InlineAsmOperand::InOut { in_value, out_place, .. } => {
- (Some(in_value.stable()), out_place.map(|place| place.stable()))
+ (Some(in_value.stable(tables)), out_place.map(|place| place.stable(tables)))
}
InlineAsmOperand::Const { .. }
| InlineAsmOperand::SymFn { .. }
| InlineAsmOperand::SymStatic { .. } => (None, None),
};
- stable_mir::mir::InlineAsmOperand { in_value, out_place, raw_rpr: format!("{:?}", self) }
+ stable_mir::mir::InlineAsmOperand { in_value, out_place, raw_rpr: format!("{self:?}") }
}
}
-impl<'tcx> Stable for mir::Terminator<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
type T = stable_mir::mir::Terminator;
- fn stable(&self) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use rustc_middle::mir::TerminatorKind::*;
use stable_mir::mir::Terminator;
match &self.kind {
Goto { target } => Terminator::Goto { target: target.as_usize() },
SwitchInt { discr, targets } => Terminator::SwitchInt {
- discr: discr.stable(),
+ discr: discr.stable(tables),
targets: targets
.iter()
.map(|(value, target)| stable_mir::mir::SwitchTarget {
@@ -365,37 +785,423 @@ impl<'tcx> Stable for mir::Terminator<'tcx> {
Return => Terminator::Return,
Unreachable => Terminator::Unreachable,
Drop { place, target, unwind, replace: _ } => Terminator::Drop {
- place: place.stable(),
+ place: place.stable(tables),
target: target.as_usize(),
- unwind: unwind.stable(),
+ unwind: unwind.stable(tables),
},
Call { func, args, destination, target, unwind, call_source: _, fn_span: _ } => {
Terminator::Call {
- func: func.stable(),
- args: args.iter().map(|arg| arg.stable()).collect(),
- destination: destination.stable(),
+ func: func.stable(tables),
+ args: args.iter().map(|arg| arg.stable(tables)).collect(),
+ destination: destination.stable(tables),
target: target.map(|t| t.as_usize()),
- unwind: unwind.stable(),
+ unwind: unwind.stable(tables),
}
}
Assert { cond, expected, msg, target, unwind } => Terminator::Assert {
- cond: cond.stable(),
+ cond: cond.stable(tables),
expected: *expected,
- msg: rustc_assert_msg_to_msg(msg),
+ msg: msg.stable(tables),
target: target.as_usize(),
- unwind: unwind.stable(),
+ unwind: unwind.stable(tables),
},
InlineAsm { template, operands, options, line_spans, destination, unwind } => {
Terminator::InlineAsm {
- template: format!("{:?}", template),
- operands: operands.iter().map(|operand| operand.stable()).collect(),
- options: format!("{:?}", options),
- line_spans: format!("{:?}", line_spans),
+ template: format!("{template:?}"),
+ operands: operands.iter().map(|operand| operand.stable(tables)).collect(),
+ options: format!("{options:?}"),
+ line_spans: format!("{line_spans:?}"),
destination: destination.map(|d| d.as_usize()),
- unwind: unwind.stable(),
+ unwind: unwind.stable(tables),
}
}
Yield { .. } | GeneratorDrop | FalseEdge { .. } | FalseUnwind { .. } => unreachable!(),
}
}
}
+
+impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
+ type T = stable_mir::ty::GenericArgs;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::GenericArgs;
+
+ GenericArgs(self.iter().map(|arg| arg.unpack().stable(tables)).collect())
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> {
+ type T = stable_mir::ty::GenericArgKind;
+
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::GenericArgKind;
+ match self {
+ ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(opaque(region)),
+ ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(*ty)),
+ ty::GenericArgKind::Const(cnst) => {
+ let cnst = ConstantKind::from_const(*cnst, tables.tcx);
+ GenericArgKind::Const(stable_mir::ty::Const { literal: cnst.stable(tables) })
+ }
+ }
+ }
+}
+
+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(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::Binder;
+
+ Binder {
+ value: self.as_ref().skip_binder().stable(tables),
+ bound_vars: self
+ .bound_vars()
+ .iter()
+ .map(|bound_var| bound_var.stable(tables))
+ .collect(),
+ }
+ }
+}
+
+impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder<S>
+where
+ S: Stable<'tcx, T = V>,
+{
+ type T = stable_mir::ty::EarlyBinder<V>;
+
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::EarlyBinder;
+
+ EarlyBinder { value: self.as_ref().skip_binder().stable(tables) }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
+ type T = stable_mir::ty::FnSig;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use rustc_target::spec::abi;
+ use stable_mir::ty::{Abi, FnSig};
+
+ FnSig {
+ inputs_and_output: self
+ .inputs_and_output
+ .iter()
+ .map(|ty| tables.intern_ty(ty))
+ .collect(),
+ c_variadic: self.c_variadic,
+ unsafety: self.unsafety.stable(tables),
+ abi: match self.abi {
+ abi::Abi::Rust => Abi::Rust,
+ abi::Abi::C { unwind } => Abi::C { unwind },
+ abi::Abi::Cdecl { unwind } => Abi::Cdecl { unwind },
+ abi::Abi::Stdcall { unwind } => Abi::Stdcall { unwind },
+ abi::Abi::Fastcall { unwind } => Abi::Fastcall { unwind },
+ abi::Abi::Vectorcall { unwind } => Abi::Vectorcall { unwind },
+ abi::Abi::Thiscall { unwind } => Abi::Thiscall { unwind },
+ abi::Abi::Aapcs { unwind } => Abi::Aapcs { unwind },
+ abi::Abi::Win64 { unwind } => Abi::Win64 { unwind },
+ abi::Abi::SysV64 { unwind } => Abi::SysV64 { unwind },
+ abi::Abi::PtxKernel => Abi::PtxKernel,
+ abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt,
+ abi::Abi::X86Interrupt => Abi::X86Interrupt,
+ abi::Abi::AmdGpuKernel => Abi::AmdGpuKernel,
+ abi::Abi::EfiApi => Abi::EfiApi,
+ abi::Abi::AvrInterrupt => Abi::AvrInterrupt,
+ abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt,
+ abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
+ abi::Abi::Wasm => Abi::Wasm,
+ abi::Abi::System { unwind } => Abi::System { unwind },
+ abi::Abi::RustIntrinsic => Abi::RustIntrinsic,
+ abi::Abi::RustCall => Abi::RustCall,
+ abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic,
+ abi::Abi::Unadjusted => Abi::Unadjusted,
+ abi::Abi::RustCold => Abi::RustCold,
+ abi::Abi::RiscvInterruptM => Abi::RiscvInterruptM,
+ abi::Abi::RiscvInterruptS => Abi::RiscvInterruptS,
+ },
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::BoundTyKind {
+ type T = stable_mir::ty::BoundTyKind;
+
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::BoundTyKind;
+
+ match self {
+ ty::BoundTyKind::Anon => BoundTyKind::Anon,
+ ty::BoundTyKind::Param(def_id, symbol) => {
+ BoundTyKind::Param(rustc_internal::param_def(*def_id), symbol.to_string())
+ }
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
+ type T = stable_mir::ty::BoundRegionKind;
+
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::BoundRegionKind;
+
+ match self {
+ ty::BoundRegionKind::BrAnon(option_span) => {
+ BoundRegionKind::BrAnon(option_span.map(|span| opaque(&span)))
+ }
+ ty::BoundRegionKind::BrNamed(def_id, symbol) => {
+ BoundRegionKind::BrNamed(rustc_internal::br_named_def(*def_id), symbol.to_string())
+ }
+ ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
+ type T = stable_mir::ty::BoundVariableKind;
+
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::BoundVariableKind;
+
+ match self {
+ ty::BoundVariableKind::Ty(bound_ty_kind) => {
+ BoundVariableKind::Ty(bound_ty_kind.stable(tables))
+ }
+ ty::BoundVariableKind::Region(bound_region_kind) => {
+ BoundVariableKind::Region(bound_region_kind.stable(tables))
+ }
+ ty::BoundVariableKind::Const => BoundVariableKind::Const,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::IntTy {
+ type T = IntTy;
+
+ fn stable(&self, _: &mut Tables<'tcx>) -> 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<'tcx>) -> 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<'tcx>) -> Self::T {
+ match self {
+ ty::FloatTy::F32 => FloatTy::F32,
+ ty::FloatTy::F64 => FloatTy::F64,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for hir::Movability {
+ type T = Movability;
+
+ fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ match self {
+ hir::Movability::Static => Movability::Static,
+ hir::Movability::Movable => Movability::Movable,
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for Ty<'tcx> {
+ type T = stable_mir::ty::TyKind;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ match self.kind() {
+ ty::Bool => TyKind::RigidTy(RigidTy::Bool),
+ ty::Char => TyKind::RigidTy(RigidTy::Char),
+ ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables))),
+ ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables))),
+ ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables))),
+ ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
+ rustc_internal::adt_def(adt_def.did()),
+ generic_args.stable(tables),
+ )),
+ ty::Foreign(def_id) => {
+ TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id)))
+ }
+ ty::Str => TyKind::RigidTy(RigidTy::Str),
+ ty::Array(ty, constant) => {
+ let cnst = ConstantKind::from_const(*constant, tables.tcx);
+ let cnst = stable_mir::ty::Const { literal: cnst.stable(tables) };
+ TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), cnst))
+ }
+ ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(tables.intern_ty(*ty))),
+ ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
+ TyKind::RigidTy(RigidTy::RawPtr(tables.intern_ty(*ty), mutbl.stable(tables)))
+ }
+ ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref(
+ opaque(region),
+ tables.intern_ty(*ty),
+ mutbl.stable(tables),
+ )),
+ ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef(
+ rustc_internal::fn_def(*def_id),
+ generic_args.stable(tables),
+ )),
+ ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))),
+ ty::Dynamic(existential_predicates, region, dyn_kind) => {
+ TyKind::RigidTy(RigidTy::Dynamic(
+ existential_predicates
+ .iter()
+ .map(|existential_predicate| existential_predicate.stable(tables))
+ .collect(),
+ opaque(region),
+ dyn_kind.stable(tables),
+ ))
+ }
+ ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
+ rustc_internal::closure_def(*def_id),
+ generic_args.stable(tables),
+ )),
+ ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
+ rustc_internal::generator_def(*def_id),
+ generic_args.stable(tables),
+ movability.stable(tables),
+ )),
+ ty::Never => TyKind::RigidTy(RigidTy::Never),
+ ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
+ fields.iter().map(|ty| tables.intern_ty(ty)).collect(),
+ )),
+ ty::Alias(alias_kind, alias_ty) => {
+ TyKind::Alias(alias_kind.stable(tables), alias_ty.stable(tables))
+ }
+ ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables)),
+ ty::Bound(debruijn_idx, bound_ty) => {
+ TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables))
+ }
+ ty::Placeholder(..)
+ | ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(_, _)
+ | ty::Infer(_)
+ | ty::Error(_) => {
+ unreachable!();
+ }
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::ParamTy {
+ type T = stable_mir::ty::ParamTy;
+ fn stable(&self, _: &mut Tables<'tcx>) -> 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(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::BoundTy;
+ BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables) }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
+ type T = stable_mir::ty::Allocation;
+
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ allocation_filter(self, alloc_range(rustc_target::abi::Size::ZERO, self.size()), tables)
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind {
+ type T = stable_mir::ty::TraitSpecializationKind;
+ fn stable(&self, _: &mut Tables<'tcx>) -> 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(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::TraitDecl;
+
+ TraitDecl {
+ def_id: rustc_internal::trait_def(self.def_id),
+ unsafety: self.unsafety.stable(tables),
+ 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,
+ specialization_kind: self.specialization_kind.stable(tables),
+ 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 rustc_middle::mir::ConstantKind<'tcx> {
+ type T = stable_mir::ty::ConstantKind;
+
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ match self {
+ ConstantKind::Ty(c) => match c.kind() {
+ ty::Value(val) => {
+ let const_val = tables.tcx.valtree_to_const_val((c.ty(), val));
+ stable_mir::ty::ConstantKind::Allocated(new_allocation(self, const_val, tables))
+ }
+ ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(&param)),
+ ty::ErrorCt(_) => unreachable!(),
+ _ => unimplemented!(),
+ },
+ ConstantKind::Unevaluated(unev_const, ty) => {
+ stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
+ ty: tables.intern_ty(*ty),
+ def: tables.const_def(unev_const.def),
+ args: unev_const.args.stable(tables),
+ promoted: unev_const.promoted.map(|u| u.as_u32()),
+ })
+ }
+ ConstantKind::Val(val, _) => {
+ stable_mir::ty::ConstantKind::Allocated(new_allocation(self, *val, tables))
+ }
+ }
+ }
+}
+
+impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> {
+ type T = stable_mir::ty::TraitRef;
+ fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ use stable_mir::ty::TraitRef;
+
+ TraitRef { def_id: rustc_internal::trait_def(self.def_id), args: self.args.stable(tables) }
+ }
+}
diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs
index 468e915d1..c16bd6cbd 100644
--- a/compiler/rustc_smir/src/stable_mir/mir/body.rs
+++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs
@@ -1,4 +1,8 @@
-use crate::stable_mir::ty::Ty;
+use crate::rustc_internal::Opaque;
+use crate::stable_mir::ty::{
+ AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region,
+};
+use crate::stable_mir::{self, ty::Ty};
#[derive(Clone, Debug)]
pub struct Body {
@@ -130,18 +134,225 @@ pub enum AsyncGeneratorKind {
Fn,
}
+pub(crate) type LocalDefId = Opaque;
+pub(crate) type CounterValueReference = Opaque;
+pub(crate) type InjectedExpressionId = Opaque;
+pub(crate) type ExpressionOperandId = Opaque;
+
+/// The FakeReadCause describes the type of pattern why a FakeRead statement exists.
+#[derive(Clone, Debug)]
+pub enum FakeReadCause {
+ ForMatchGuard,
+ ForMatchedPlace(LocalDefId),
+ ForGuardBinding,
+ ForLet(LocalDefId),
+ ForIndex,
+}
+
+/// Describes what kind of retag is to be performed
+#[derive(Clone, Debug)]
+pub enum RetagKind {
+ FnEntry,
+ TwoPhase,
+ Raw,
+ Default,
+}
+
+#[derive(Clone, Debug)]
+pub enum Variance {
+ Covariant,
+ Invariant,
+ Contravariant,
+ Bivariant,
+}
+
+#[derive(Clone, Debug)]
+pub enum Op {
+ Subtract,
+ Add,
+}
+
+#[derive(Clone, Debug)]
+pub enum CoverageKind {
+ Counter {
+ function_source_hash: usize,
+ id: CounterValueReference,
+ },
+ Expression {
+ id: InjectedExpressionId,
+ lhs: ExpressionOperandId,
+ op: Op,
+ rhs: ExpressionOperandId,
+ },
+ Unreachable,
+}
+
+#[derive(Clone, Debug)]
+pub struct CodeRegion {
+ pub file_name: String,
+ pub start_line: usize,
+ pub start_col: usize,
+ pub end_line: usize,
+ pub end_col: usize,
+}
+
+#[derive(Clone, Debug)]
+pub struct Coverage {
+ pub kind: CoverageKind,
+ pub code_region: Option<CodeRegion>,
+}
+
+#[derive(Clone, Debug)]
+pub struct CopyNonOverlapping {
+ pub src: Operand,
+ pub dst: Operand,
+ pub count: Operand,
+}
+
+#[derive(Clone, Debug)]
+pub enum NonDivergingIntrinsic {
+ Assume(Operand),
+ CopyNonOverlapping(CopyNonOverlapping),
+}
+
#[derive(Clone, Debug)]
pub enum Statement {
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,
}
-// FIXME this is incomplete
#[derive(Clone, Debug)]
pub enum Rvalue {
- Use(Operand),
+ /// 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(Mutability, 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 `Generator`. After
+ /// generator lowering, `Generator` aggregate kinds are disallowed too.
+ Aggregate(AggregateKind, Vec<Operand>),
+
+ /// * `Offset` has the same semantics as [`offset`](pointer::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 of type
+ /// [`discriminant_ty`]. 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; use [`discriminant_for_variant`] to convert.
+ ///
+ /// [`discriminant_ty`]: rustc_middle::ty::Ty::discriminant_ty
+ /// [#91095]: https://github.com/rust-lang/rust/issues/91095
+ /// [`discriminant_for_variant`]: rustc_middle::ty::Ty::discriminant_for_variant
+ 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, Const),
+
+ /// 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),
+}
+
+#[derive(Clone, Debug)]
+pub enum AggregateKind {
+ Array(Ty),
+ Tuple,
+ Adt(AdtDef, VariantIdx, GenericArgs, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
+ Closure(ClosureDef, GenericArgs),
+ Generator(GeneratorDef, GenericArgs, Movability),
}
#[derive(Clone, Debug)]
@@ -153,12 +364,115 @@ pub enum Operand {
#[derive(Clone, Debug)]
pub struct Place {
- pub local: usize,
+ pub local: Local,
pub projection: String,
}
#[derive(Clone, Debug)]
+pub struct UserTypeProjection {
+ pub base: UserTypeAnnotationIndex,
+ pub projection: String,
+}
+
+pub type Local = usize;
+
+type FieldIdx = usize;
+
+/// The source-order index of a variant in a type.
+pub type VariantIdx = usize;
+
+type UserTypeAnnotationIndex = usize;
+
+#[derive(Clone, Debug)]
pub struct SwitchTarget {
pub value: u128,
pub target: usize,
}
+
+#[derive(Clone, Debug)]
+pub enum BorrowKind {
+ /// Data must be immutable and is aliasable.
+ Shared,
+
+ /// The immediately borrowed place must be immutable, but projections from
+ /// it don't need to be. For example, a shallow borrow of `a.b` doesn't
+ /// conflict with a mutable borrow of `a.b.c`.
+ Shallow,
+
+ /// Data is mutable and not aliasable.
+ Mut {
+ /// `true` if this borrow arose from method-call auto-ref
+ kind: MutBorrowKind,
+ },
+}
+
+#[derive(Clone, Debug)]
+pub enum MutBorrowKind {
+ Default,
+ TwoPhaseBorrow,
+ ClosureCapture,
+}
+
+#[derive(Clone, Debug)]
+pub enum Mutability {
+ Not,
+ Mut,
+}
+
+#[derive(Clone, Debug)]
+pub enum Safety {
+ Unsafe,
+ Normal,
+}
+
+#[derive(Clone, Debug)]
+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 an 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 fat pointer.
+ /// This will do things like convert thin pointers to fat
+ /// pointers, or convert structs containing thin pointers to
+ /// structs containing fat pointers, or convert between fat
+ /// pointers.
+ Unsize,
+}
+
+#[derive(Clone, Debug)]
+pub enum CastKind {
+ PointerExposeAddress,
+ PointerFromExposedAddress,
+ PointerCoercion(PointerCoercion),
+ DynStar,
+ IntToInt,
+ FloatToInt,
+ FloatToFloat,
+ IntToFloat,
+ PtrToPtr,
+ FnPtrToPtr,
+ Transmute,
+}
+
+#[derive(Clone, Debug)]
+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<FieldIdx>),
+}
diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs
index 5e599a77b..19061742b 100644
--- a/compiler/rustc_smir/src/stable_mir/mod.rs
+++ b/compiler/rustc_smir/src/stable_mir/mod.rs
@@ -15,7 +15,7 @@ use std::cell::Cell;
use crate::rustc_smir::Tables;
-use self::ty::{Ty, TyKind};
+use self::ty::{ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind};
pub mod mir;
pub mod ty;
@@ -32,6 +32,12 @@ pub type DefId = usize;
/// 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>;
+
/// Holds information about a crate.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Crate {
@@ -79,11 +85,31 @@ 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 trait_decl(trait_def: &TraitDef) -> TraitDecl {
+ with(|cx| cx.trait_decl(trait_def))
+}
+
+pub fn all_trait_impls() -> ImplTraitDecls {
+ with(|cx| cx.all_trait_impls())
+}
+
+pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
+ with(|cx| cx.trait_impl(trait_impl))
+}
+
pub trait Context {
fn entry_fn(&mut self) -> Option<CrateItem>;
/// Retrieve all items of the local crate that have a MIR associated with them.
fn all_local_items(&mut self) -> CrateItems;
fn mir_body(&mut self, item: &CrateItem) -> mir::Body;
+ fn all_trait_decls(&mut self) -> TraitDecls;
+ fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl;
+ fn all_trait_impls(&mut self) -> ImplTraitDecls;
+ fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait;
/// Get information about the local crate.
fn local_crate(&self) -> Crate;
/// Retrieve a list of all external crates.
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index 3181af46e..7a6601f09 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1,4 +1,10 @@
-use super::with;
+use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer};
+
+use super::{mir::Mutability, mir::Safety, with, DefId};
+use crate::{
+ rustc_internal::{opaque, Opaque},
+ rustc_smir::{Stable, Tables},
+};
#[derive(Copy, Clone, Debug)]
pub struct Ty(pub usize);
@@ -9,9 +15,21 @@ impl Ty {
}
}
+#[derive(Debug, Clone)]
+pub struct Const {
+ pub literal: ConstantKind,
+}
+
+type Ident = Opaque;
+pub(crate) type Region = Opaque;
+type Span = Opaque;
+
#[derive(Clone, Debug)]
pub enum TyKind {
RigidTy(RigidTy),
+ Alias(AliasKind, AliasTy),
+ Param(ParamTy),
+ Bound(usize, BoundTy),
}
#[derive(Clone, Debug)]
@@ -21,6 +39,19 @@ pub enum RigidTy {
Int(IntTy),
Uint(UintTy),
Float(FloatTy),
+ Adt(AdtDef, GenericArgs),
+ Foreign(ForeignDef),
+ Str,
+ Array(Ty, Const),
+ Slice(Ty),
+ RawPtr(Ty, Mutability),
+ Ref(Region, Ty, Mutability),
+ FnDef(FnDef, GenericArgs),
+ FnPtr(PolyFnSig),
+ Closure(ClosureDef, GenericArgs),
+ Generator(GeneratorDef, GenericArgs, Movability),
+ Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind),
+ Never,
Tuple(Vec<Ty>),
}
@@ -49,3 +80,384 @@ pub enum FloatTy {
F32,
F64,
}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Movability {
+ Static,
+ Movable,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ForeignDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FnDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ClosureDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct GeneratorDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ParamDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct BrNamedDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct AdtDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct AliasDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct TraitDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ConstDef(pub(crate) DefId);
+
+impl TraitDef {
+ pub fn trait_decl(&self) -> TraitDecl {
+ with(|cx| cx.trait_decl(self))
+ }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ImplDef(pub(crate) DefId);
+
+impl ImplDef {
+ pub fn trait_impl(&self) -> ImplTrait {
+ with(|cx| cx.trait_impl(self))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct GenericArgs(pub Vec<GenericArgKind>);
+
+#[derive(Clone, Debug)]
+pub enum GenericArgKind {
+ Lifetime(Region),
+ Type(Ty),
+ Const(Const),
+}
+
+#[derive(Clone, Debug)]
+pub enum TermKind {
+ Type(Ty),
+ Const(Const),
+}
+
+#[derive(Clone, Debug)]
+pub enum AliasKind {
+ Projection,
+ Inherent,
+ Opaque,
+ Weak,
+}
+
+#[derive(Clone, Debug)]
+pub struct AliasTy {
+ pub def_id: AliasDef,
+ pub args: GenericArgs,
+}
+
+pub type PolyFnSig = Binder<FnSig>;
+
+#[derive(Clone, Debug)]
+pub struct FnSig {
+ pub inputs_and_output: Vec<Ty>,
+ pub c_variadic: bool,
+ pub unsafety: Safety,
+ pub abi: Abi,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+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,
+ AmdGpuKernel,
+ EfiApi,
+ AvrInterrupt,
+ AvrNonBlockingInterrupt,
+ CCmseNonSecureCall,
+ Wasm,
+ System { unwind: bool },
+ RustIntrinsic,
+ RustCall,
+ PlatformIntrinsic,
+ Unadjusted,
+ RustCold,
+ RiscvInterruptM,
+ RiscvInterruptS,
+}
+
+#[derive(Clone, Debug)]
+pub struct Binder<T> {
+ pub value: T,
+ pub bound_vars: Vec<BoundVariableKind>,
+}
+
+#[derive(Clone, Debug)]
+pub struct EarlyBinder<T> {
+ pub value: T,
+}
+
+#[derive(Clone, Debug)]
+pub enum BoundVariableKind {
+ Ty(BoundTyKind),
+ Region(BoundRegionKind),
+ Const,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum BoundTyKind {
+ Anon,
+ Param(ParamDef, String),
+}
+
+#[derive(Clone, Debug)]
+pub enum BoundRegionKind {
+ BrAnon(Option<Span>),
+ BrNamed(BrNamedDef, String),
+ BrEnv,
+}
+
+#[derive(Clone, Debug)]
+pub enum DynKind {
+ Dyn,
+ DynStar,
+}
+
+#[derive(Clone, Debug)]
+pub enum ExistentialPredicate {
+ Trait(ExistentialTraitRef),
+ Projection(ExistentialProjection),
+ AutoTrait(TraitDef),
+}
+
+#[derive(Clone, Debug)]
+pub struct ExistentialTraitRef {
+ pub def_id: TraitDef,
+ pub generic_args: GenericArgs,
+}
+
+#[derive(Clone, Debug)]
+pub struct ExistentialProjection {
+ pub def_id: TraitDef,
+ pub generic_args: GenericArgs,
+ pub term: TermKind,
+}
+
+#[derive(Clone, Debug)]
+pub struct ParamTy {
+ pub index: u32,
+ pub name: String,
+}
+
+#[derive(Clone, Debug)]
+pub struct BoundTy {
+ pub var: usize,
+ pub kind: BoundTyKind,
+}
+
+pub type Bytes = Vec<Option<u8>>;
+pub type Size = usize;
+pub type Prov = Opaque;
+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)]
+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)]
+pub struct Allocation {
+ pub bytes: Bytes,
+ pub provenance: ProvenanceMap,
+ pub align: Align,
+ pub mutability: Mutability,
+}
+
+impl Allocation {
+ /// Creates new empty `Allocation` from given `Align`.
+ fn new_empty_allocation(align: rustc_target::abi::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.
+pub fn new_allocation<'tcx>(
+ const_kind: &rustc_middle::mir::ConstantKind<'tcx>,
+ const_value: ConstValue<'tcx>,
+ tables: &mut Tables<'tcx>,
+) -> Allocation {
+ match const_value {
+ ConstValue::Scalar(scalar) => {
+ let size = scalar.size();
+ let align = tables
+ .tcx
+ .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+ .unwrap()
+ .align;
+ let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
+ allocation
+ .write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
+ .unwrap();
+ allocation.stable(tables)
+ }
+ ConstValue::ZeroSized => {
+ let align = tables
+ .tcx
+ .layout_of(rustc_middle::ty::ParamEnv::empty().and(const_kind.ty()))
+ .unwrap()
+ .align;
+ Allocation::new_empty_allocation(align.abi)
+ }
+ ConstValue::Slice { data, start, end } => {
+ let alloc_id = tables.tcx.create_memory_alloc(data);
+ let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start));
+ let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
+ let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize(
+ (end - start) as u64,
+ &tables.tcx,
+ );
+ let layout = tables
+ .tcx
+ .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+ .unwrap();
+ let mut allocation =
+ rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
+ allocation
+ .write_scalar(
+ &tables.tcx,
+ alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
+ scalar_ptr,
+ )
+ .unwrap();
+ allocation
+ .write_scalar(
+ &tables.tcx,
+ alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()),
+ scalar_len,
+ )
+ .unwrap();
+ allocation.stable(tables)
+ }
+ ConstValue::ByRef { alloc, offset } => {
+ let ty_size = tables
+ .tcx
+ .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+ .unwrap()
+ .size;
+ allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
+ }
+ }
+}
+
+/// Creates an `Allocation` only from information within the `AllocRange`.
+pub fn allocation_filter<'tcx>(
+ alloc: &rustc_middle::mir::interpret::Allocation,
+ alloc_range: AllocRange,
+ tables: &mut Tables<'tcx>,
+) -> Allocation {
+ let mut bytes: Vec<Option<u8>> = alloc
+ .inspect_with_uninit_and_ptr_outside_interpreter(
+ alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
+ )
+ .iter()
+ .copied()
+ .map(Some)
+ .collect();
+ for (i, b) in bytes.iter_mut().enumerate() {
+ if !alloc
+ .init_mask()
+ .get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize()))
+ {
+ *b = None;
+ }
+ }
+ let mut ptrs = Vec::new();
+ for (offset, prov) in alloc
+ .provenance()
+ .ptrs()
+ .iter()
+ .filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
+ {
+ ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), opaque(prov)));
+ }
+ Allocation {
+ bytes: bytes,
+ provenance: ProvenanceMap { ptrs },
+ align: alloc.align.bytes(),
+ mutability: alloc.mutability.stable(tables),
+ }
+}
+
+#[derive(Clone, Debug)]
+pub enum ConstantKind {
+ Allocated(Allocation),
+ Unevaluated(UnevaluatedConst),
+ ParamCt(Opaque),
+}
+
+#[derive(Clone, Debug)]
+pub struct UnevaluatedConst {
+ pub ty: Ty,
+ pub def: ConstDef,
+ pub args: GenericArgs,
+ pub promoted: Option<Promoted>,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum TraitSpecializationKind {
+ None,
+ Marker,
+ AlwaysApplicable,
+}
+
+#[derive(Clone, Debug)]
+pub struct TraitDecl {
+ pub def_id: TraitDef,
+ pub unsafety: 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 specialization_kind: TraitSpecializationKind,
+ pub must_implement_one_of: Option<Vec<Ident>>,
+ pub implement_via_object: bool,
+ pub deny_explicit_impl: bool,
+}
+
+pub type ImplTrait = EarlyBinder<TraitRef>;
+
+#[derive(Clone, Debug)]
+pub struct TraitRef {
+ pub def_id: TraitDef,
+ pub args: GenericArgs,
+}