rustc_smir/rustc_smir/
mod.rs1use std::ops::RangeInclusive;
11
12use rustc_hir::def::DefKind;
13use rustc_middle::mir;
14use rustc_middle::mir::interpret::AllocId;
15use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
16use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
17use stable_mir::abi::Layout;
18use stable_mir::mir::mono::{InstanceDef, StaticDef};
19use stable_mir::ty::{FnDef, MirConstId, Span, TyConstId};
20use stable_mir::{CtorKind, ItemKind};
21use tracing::debug;
22
23use crate::rustc_internal::IndexMap;
24
25mod alloc;
26mod builder;
27pub(crate) mod context;
28mod convert;
29
30pub struct Tables<'tcx> {
31 pub(crate) tcx: TyCtxt<'tcx>,
32 pub(crate) def_ids: IndexMap<DefId, stable_mir::DefId>,
33 pub(crate) alloc_ids: IndexMap<AllocId, stable_mir::mir::alloc::AllocId>,
34 pub(crate) spans: IndexMap<rustc_span::Span, Span>,
35 pub(crate) types: IndexMap<Ty<'tcx>, stable_mir::ty::Ty>,
36 pub(crate) instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
37 pub(crate) ty_consts: IndexMap<ty::Const<'tcx>, TyConstId>,
38 pub(crate) mir_consts: IndexMap<mir::Const<'tcx>, MirConstId>,
39 pub(crate) layouts: IndexMap<rustc_abi::Layout<'tcx>, Layout>,
40}
41
42impl<'tcx> Tables<'tcx> {
43 pub(crate) fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty {
44 self.types.create_or_fetch(ty)
45 }
46
47 pub(crate) fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> TyConstId {
48 self.ty_consts.create_or_fetch(ct)
49 }
50
51 pub(crate) fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> MirConstId {
52 self.mir_consts.create_or_fetch(constant)
53 }
54
55 pub(crate) fn instance_has_body(&self, instance: Instance<'tcx>) -> bool {
60 let def_id = instance.def_id();
61 self.item_has_body(def_id)
62 || !matches!(
63 instance.def,
64 ty::InstanceKind::Virtual(..)
65 | ty::InstanceKind::Intrinsic(..)
66 | ty::InstanceKind::Item(..)
67 )
68 }
69
70 pub(crate) fn item_has_body(&self, def_id: DefId) -> bool {
75 let must_override = if let Some(intrinsic) = self.tcx.intrinsic(def_id) {
76 intrinsic.must_be_overridden
77 } else {
78 false
79 };
80 !must_override && self.tcx.is_mir_available(def_id)
81 }
82
83 fn to_fn_def(&mut self, def_id: DefId) -> Option<FnDef> {
84 if matches!(self.tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
85 Some(self.fn_def(def_id))
86 } else {
87 None
88 }
89 }
90
91 fn to_static(&mut self, def_id: DefId) -> Option<StaticDef> {
92 matches!(self.tcx.def_kind(def_id), DefKind::Static { .. }).then(|| self.static_def(def_id))
93 }
94}
95
96pub(crate) fn filter_def_ids<F, T>(tcx: TyCtxt<'_>, krate: CrateNum, mut func: F) -> Vec<T>
98where
99 F: FnMut(DefId) -> Option<T>,
100{
101 if krate == LOCAL_CRATE {
102 tcx.iter_local_def_id().filter_map(|did| func(did.to_def_id())).collect()
103 } else {
104 let num_definitions = tcx.num_extern_def_ids(krate);
105 (0..num_definitions)
106 .filter_map(move |i| {
107 let def_id = DefId { krate, index: rustc_span::def_id::DefIndex::from_usize(i) };
108 func(def_id)
109 })
110 .collect()
111 }
112}
113
114pub(crate) fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
116 let crate_name = tcx.crate_name(crate_num).to_string();
117 let is_local = crate_num == LOCAL_CRATE;
118 debug!(?crate_name, ?crate_num, "smir_crate");
119 stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local }
120}
121
122pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind {
123 match kind {
124 DefKind::Mod
125 | DefKind::Struct
126 | DefKind::Union
127 | DefKind::Enum
128 | DefKind::Variant
129 | DefKind::Trait
130 | DefKind::TyAlias
131 | DefKind::ForeignTy
132 | DefKind::TraitAlias
133 | DefKind::AssocTy
134 | DefKind::TyParam
135 | DefKind::ConstParam
136 | DefKind::Macro(_)
137 | DefKind::ExternCrate
138 | DefKind::Use
139 | DefKind::ForeignMod
140 | DefKind::OpaqueTy
141 | DefKind::Field
142 | DefKind::LifetimeParam
143 | DefKind::Impl { .. }
144 | DefKind::GlobalAsm => {
145 unreachable!("Not a valid item kind: {kind:?}");
146 }
147 DefKind::Closure | DefKind::AssocFn | DefKind::Fn | DefKind::SyntheticCoroutineBody => {
148 ItemKind::Fn
149 }
150 DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => {
151 ItemKind::Const
152 }
153 DefKind::Static { .. } => ItemKind::Static,
154 DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const),
155 DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn),
156 }
157}
158
159pub trait Stable<'cx> {
161 type T;
163 fn stable(&self, tables: &mut Tables<'_>) -> Self::T;
165}
166
167impl<'tcx, T> Stable<'tcx> for &T
168where
169 T: Stable<'tcx>,
170{
171 type T = T::T;
172
173 fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
174 (*self).stable(tables)
175 }
176}
177
178impl<'tcx, T> Stable<'tcx> for Option<T>
179where
180 T: Stable<'tcx>,
181{
182 type T = Option<T::T>;
183
184 fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
185 self.as_ref().map(|value| value.stable(tables))
186 }
187}
188
189impl<'tcx, T, E> Stable<'tcx> for Result<T, E>
190where
191 T: Stable<'tcx>,
192 E: Stable<'tcx>,
193{
194 type T = Result<T::T, E::T>;
195
196 fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
197 match self {
198 Ok(val) => Ok(val.stable(tables)),
199 Err(error) => Err(error.stable(tables)),
200 }
201 }
202}
203
204impl<'tcx, T> Stable<'tcx> for &[T]
205where
206 T: Stable<'tcx>,
207{
208 type T = Vec<T::T>;
209 fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
210 self.iter().map(|e| e.stable(tables)).collect()
211 }
212}
213
214impl<'tcx, T, U> Stable<'tcx> for (T, U)
215where
216 T: Stable<'tcx>,
217 U: Stable<'tcx>,
218{
219 type T = (T::T, U::T);
220 fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
221 (self.0.stable(tables), self.1.stable(tables))
222 }
223}
224
225impl<'tcx, T> Stable<'tcx> for RangeInclusive<T>
226where
227 T: Stable<'tcx>,
228{
229 type T = RangeInclusive<T::T>;
230 fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
231 RangeInclusive::new(self.start().stable(tables), self.end().stable(tables))
232 }
233}