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