rustc_smir/stable_mir/mir/
mono.rs1use std::fmt::{Debug, Formatter};
2use std::io;
3
4use serde::Serialize;
5use stable_mir::abi::FnAbi;
6use stable_mir::crate_def::CrateDef;
7use stable_mir::mir::Body;
8use stable_mir::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty};
9use stable_mir::{CrateItem, DefId, Error, ItemKind, Opaque, Symbol, with};
10
11use crate::stable_mir;
12
13#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
14pub enum MonoItem {
15 Fn(Instance),
16 Static(StaticDef),
17 GlobalAsm(Opaque),
18}
19
20#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize)]
21pub struct Instance {
22 pub kind: InstanceKind,
24 pub def: InstanceDef,
27}
28
29#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)]
30pub enum InstanceKind {
31 Item,
33 Intrinsic,
35 Virtual { idx: usize },
38 Shim,
40}
41
42impl Instance {
43 pub fn args(&self) -> GenericArgs {
45 with(|cx| cx.instance_args(self.def))
46 }
47
48 pub fn body(&self) -> Option<Body> {
54 with(|context| context.instance_body(self.def))
55 }
56
57 pub fn has_body(&self) -> bool {
67 with(|cx| cx.has_body(self.def.def_id()))
68 }
69
70 pub fn is_foreign_item(&self) -> bool {
71 with(|cx| cx.is_foreign_item(self.def.def_id()))
72 }
73
74 pub fn ty(&self) -> Ty {
76 with(|context| context.instance_ty(self.def))
77 }
78
79 pub fn fn_abi(&self) -> Result<FnAbi, Error> {
81 with(|cx| cx.instance_abi(self.def))
82 }
83
84 pub fn mangled_name(&self) -> Symbol {
88 with(|context| context.instance_mangled_name(self.def))
89 }
90
91 pub fn name(&self) -> Symbol {
95 with(|context| context.instance_name(self.def, false))
96 }
97
98 pub fn trimmed_name(&self) -> Symbol {
104 with(|context| context.instance_name(self.def, true))
105 }
106
107 pub fn intrinsic_name(&self) -> Option<Symbol> {
112 match self.kind {
113 InstanceKind::Intrinsic => {
114 Some(with(|context| context.intrinsic(self.def.def_id()).unwrap().fn_name()))
115 }
116 InstanceKind::Item | InstanceKind::Virtual { .. } | InstanceKind::Shim => None,
117 }
118 }
119
120 pub fn resolve(def: FnDef, args: &GenericArgs) -> Result<Instance, Error> {
122 with(|context| {
123 context
124 .resolve_instance(def, args)
125 .ok_or_else(|| Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`")))
126 })
127 }
128
129 pub fn resolve_drop_in_place(ty: Ty) -> Instance {
131 with(|cx| cx.resolve_drop_in_place(ty))
132 }
133
134 pub fn resolve_for_fn_ptr(def: FnDef, args: &GenericArgs) -> Result<Instance, Error> {
136 with(|context| {
137 context
138 .resolve_for_fn_ptr(def, args)
139 .ok_or_else(|| Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`")))
140 })
141 }
142
143 pub fn resolve_closure(
145 def: ClosureDef,
146 args: &GenericArgs,
147 kind: ClosureKind,
148 ) -> Result<Instance, Error> {
149 with(|context| {
150 context
151 .resolve_closure(def, args, kind)
152 .ok_or_else(|| Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`")))
153 })
154 }
155
156 pub fn is_empty_shim(&self) -> bool {
166 self.kind == InstanceKind::Shim && with(|cx| cx.is_empty_drop_shim(self.def))
167 }
168
169 pub fn try_const_eval(&self, const_ty: Ty) -> Result<Allocation, Error> {
174 with(|cx| cx.eval_instance(self.def, const_ty))
175 }
176
177 pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
179 if let Some(body) = self.body() { body.dump(w, &self.name()) } else { Ok(()) }
180 }
181}
182
183impl Debug for Instance {
184 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
185 f.debug_struct("Instance")
186 .field("kind", &self.kind)
187 .field("def", &self.mangled_name())
188 .field("args", &self.args())
189 .finish()
190 }
191}
192
193impl TryFrom<CrateItem> for Instance {
196 type Error = stable_mir::Error;
197
198 fn try_from(item: CrateItem) -> Result<Self, Self::Error> {
199 with(|context| {
200 let def_id = item.def_id();
201 if !context.requires_monomorphization(def_id) {
202 Ok(context.mono_instance(def_id))
203 } else {
204 Err(Error::new("Item requires monomorphization".to_string()))
205 }
206 })
207 }
208}
209
210impl TryFrom<Instance> for CrateItem {
213 type Error = stable_mir::Error;
214
215 fn try_from(value: Instance) -> Result<Self, Self::Error> {
216 with(|context| {
217 if value.kind == InstanceKind::Item && context.has_body(value.def.def_id()) {
218 Ok(CrateItem(context.instance_def_id(value.def)))
219 } else {
220 Err(Error::new(format!("Item kind `{:?}` cannot be converted", value.kind)))
221 }
222 })
223 }
224}
225
226impl From<Instance> for MonoItem {
227 fn from(value: Instance) -> Self {
228 MonoItem::Fn(value)
229 }
230}
231
232impl From<StaticDef> for MonoItem {
233 fn from(value: StaticDef) -> Self {
234 MonoItem::Static(value)
235 }
236}
237
238impl From<StaticDef> for CrateItem {
239 fn from(value: StaticDef) -> Self {
240 CrateItem(value.0)
241 }
242}
243
244#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
245pub struct InstanceDef(usize);
246
247impl CrateDef for InstanceDef {
248 fn def_id(&self) -> DefId {
249 with(|context| context.instance_def_id(*self))
250 }
251}
252
253crate_def! {
254 #[derive(Serialize)]
256 pub StaticDef;
257}
258
259impl TryFrom<CrateItem> for StaticDef {
260 type Error = stable_mir::Error;
261
262 fn try_from(value: CrateItem) -> Result<Self, Self::Error> {
263 if matches!(value.kind(), ItemKind::Static) {
264 Ok(StaticDef(value.0))
265 } else {
266 Err(Error::new(format!("Expected a static item, but found: {value:?}")))
267 }
268 }
269}
270
271impl TryFrom<Instance> for StaticDef {
272 type Error = stable_mir::Error;
273
274 fn try_from(value: Instance) -> Result<Self, Self::Error> {
275 StaticDef::try_from(CrateItem::try_from(value)?)
276 }
277}
278
279impl From<StaticDef> for Instance {
280 fn from(value: StaticDef) -> Self {
281 with(|cx| cx.mono_instance(value.def_id()))
283 }
284}
285
286impl StaticDef {
287 pub fn ty(&self) -> Ty {
289 with(|cx| cx.def_ty(self.0))
290 }
291
292 pub fn eval_initializer(&self) -> Result<Allocation, Error> {
294 with(|cx| cx.eval_static_initializer(*self))
295 }
296}
297
298impl IndexedVal for InstanceDef {
299 fn to_val(index: usize) -> Self {
300 InstanceDef(index)
301 }
302 fn to_index(&self) -> usize {
303 self.0
304 }
305}