rustc_smir/stable_mir/mir/
mono.rs
1use 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
167 && with(|cx| {
168 cx.is_empty_drop_shim(self.def) || cx.is_empty_async_drop_ctor_shim(self.def)
169 })
170 }
171
172 pub fn try_const_eval(&self, const_ty: Ty) -> Result<Allocation, Error> {
177 with(|cx| cx.eval_instance(self.def, const_ty))
178 }
179
180 pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
182 if let Some(body) = self.body() { body.dump(w, &self.name()) } else { Ok(()) }
183 }
184}
185
186impl Debug for Instance {
187 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
188 f.debug_struct("Instance")
189 .field("kind", &self.kind)
190 .field("def", &self.mangled_name())
191 .field("args", &self.args())
192 .finish()
193 }
194}
195
196impl TryFrom<CrateItem> for Instance {
199 type Error = stable_mir::Error;
200
201 fn try_from(item: CrateItem) -> Result<Self, Self::Error> {
202 with(|context| {
203 let def_id = item.def_id();
204 if !context.requires_monomorphization(def_id) {
205 Ok(context.mono_instance(def_id))
206 } else {
207 Err(Error::new("Item requires monomorphization".to_string()))
208 }
209 })
210 }
211}
212
213impl TryFrom<Instance> for CrateItem {
216 type Error = stable_mir::Error;
217
218 fn try_from(value: Instance) -> Result<Self, Self::Error> {
219 with(|context| {
220 if value.kind == InstanceKind::Item && context.has_body(value.def.def_id()) {
221 Ok(CrateItem(context.instance_def_id(value.def)))
222 } else {
223 Err(Error::new(format!("Item kind `{:?}` cannot be converted", value.kind)))
224 }
225 })
226 }
227}
228
229impl From<Instance> for MonoItem {
230 fn from(value: Instance) -> Self {
231 MonoItem::Fn(value)
232 }
233}
234
235impl From<StaticDef> for MonoItem {
236 fn from(value: StaticDef) -> Self {
237 MonoItem::Static(value)
238 }
239}
240
241impl From<StaticDef> for CrateItem {
242 fn from(value: StaticDef) -> Self {
243 CrateItem(value.0)
244 }
245}
246
247#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
248pub struct InstanceDef(usize);
249
250impl CrateDef for InstanceDef {
251 fn def_id(&self) -> DefId {
252 with(|context| context.instance_def_id(*self))
253 }
254}
255
256crate_def! {
257 #[derive(Serialize)]
259 pub StaticDef;
260}
261
262impl TryFrom<CrateItem> for StaticDef {
263 type Error = stable_mir::Error;
264
265 fn try_from(value: CrateItem) -> Result<Self, Self::Error> {
266 if matches!(value.kind(), ItemKind::Static) {
267 Ok(StaticDef(value.0))
268 } else {
269 Err(Error::new(format!("Expected a static item, but found: {value:?}")))
270 }
271 }
272}
273
274impl TryFrom<Instance> for StaticDef {
275 type Error = stable_mir::Error;
276
277 fn try_from(value: Instance) -> Result<Self, Self::Error> {
278 StaticDef::try_from(CrateItem::try_from(value)?)
279 }
280}
281
282impl From<StaticDef> for Instance {
283 fn from(value: StaticDef) -> Self {
284 with(|cx| cx.mono_instance(value.def_id()))
286 }
287}
288
289impl StaticDef {
290 pub fn ty(&self) -> Ty {
292 with(|cx| cx.def_ty(self.0))
293 }
294
295 pub fn eval_initializer(&self) -> Result<Allocation, Error> {
297 with(|cx| cx.eval_static_initializer(*self))
298 }
299}
300
301impl IndexedVal for InstanceDef {
302 fn to_val(index: usize) -> Self {
303 InstanceDef(index)
304 }
305 fn to_index(&self) -> usize {
306 self.0
307 }
308}