Skip to main content

backend_lang/mir/
entity.rs

1//! Dense ids for a function's blocks, instructions, stack slots, symbols, and
2//! condition codes.
3
4use core::fmt;
5
6macro_rules! entity {
7    ($(#[$doc:meta])* $name:ident, $prefix:literal, $example:literal) => {
8        $(#[$doc])*
9        #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
10        pub struct $name(u32);
11
12        impl $name {
13            /// The id with index `index`. Whether a function has it is
14            /// checked where it is used.
15            ///
16            /// # Examples
17            ///
18            /// ```
19            #[doc = concat!("use backend_lang::mir::", stringify!($name), ";")]
20            ///
21            #[doc = concat!("assert_eq!(", stringify!($name), "::new(3).index(), 3);")]
22            /// ```
23            #[inline]
24            #[must_use]
25            pub const fn new(index: u32) -> $name {
26                $name(index)
27            }
28
29            /// The id's index.
30            ///
31            /// # Examples
32            ///
33            /// ```
34            #[doc = $example]
35            /// ```
36            #[inline]
37            #[must_use]
38            pub const fn index(self) -> usize {
39                self.0 as usize
40            }
41
42            /// Builds an id from a table length the caller has bounded.
43            #[allow(dead_code, reason = "not every id type is built from a length")]
44            pub(crate) const fn from_index(index: usize) -> $name {
45                $name(index as u32)
46            }
47        }
48
49        impl fmt::Debug for $name {
50            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51                write!(f, concat!($prefix, "{}"), self.0)
52            }
53        }
54
55        impl fmt::Display for $name {
56            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57                write!(f, concat!($prefix, "{}"), self.0)
58            }
59        }
60    };
61}
62
63entity!(
64    /// A basic block of a function. The first block created is the entry.
65    ///
66    /// # Examples
67    ///
68    /// ```
69    /// use backend_lang::mir::Function;
70    /// use backend_lang::x86_64::SYSV;
71    ///
72    /// let mut f = Function::new("f", &SYSV);
73    /// let entry = f.block()?;
74    /// assert_eq!(entry.to_string(), "block0");
75    /// # Ok::<(), backend_lang::mir::MirError>(())
76    /// ```
77    Block,
78    "block",
79    "use backend_lang::mir::Function;\nuse backend_lang::x86_64::SYSV;\nlet mut f = Function::new(\"f\", &SYSV);\nlet _ = f.block()?;\nassert_eq!(f.block()?.index(), 1);\n# Ok::<(), backend_lang::mir::MirError>(())"
80);
81
82entity!(
83    /// An instruction of a function, numbered in creation order across all
84    /// blocks.
85    ///
86    /// # Examples
87    ///
88    /// ```
89    /// use backend_lang::mir::{Function, Operand};
90    /// use backend_lang::x86_64::{op, SYSV};
91    ///
92    /// let mut f = Function::new("f", &SYSV);
93    /// let b = f.block()?;
94    /// let i = f.push(b, op::RET, &[])?;
95    /// assert_eq!(i.to_string(), "inst0");
96    /// # Ok::<(), backend_lang::mir::MirError>(())
97    /// ```
98    Inst,
99    "inst",
100    "use backend_lang::mir::Function;\nuse backend_lang::x86_64::{op, SYSV};\nlet mut f = Function::new(\"f\", &SYSV);\nlet b = f.block()?;\nassert_eq!(f.push(b, op::RET, &[])?.index(), 0);\n# Ok::<(), backend_lang::mir::MirError>(())"
101);
102
103entity!(
104    /// A stack slot of a function: a local, a spill slot, or an incoming
105    /// stack argument. Printed `ssN`.
106    ///
107    /// # Examples
108    ///
109    /// ```
110    /// use backend_lang::mir::{Function, SlotKind};
111    /// use backend_lang::x86_64::SYSV;
112    ///
113    /// let mut f = Function::new("f", &SYSV);
114    /// let s = f.stack_slot(SlotKind::Local { size: 8, align: 8 })?;
115    /// assert_eq!(s.to_string(), "ss0");
116    /// # Ok::<(), backend_lang::mir::MirError>(())
117    /// ```
118    StackSlot,
119    "ss",
120    "use backend_lang::mir::{Function, SlotKind};\nuse backend_lang::x86_64::SYSV;\nlet mut f = Function::new(\"f\", &SYSV);\nlet s = f.stack_slot(SlotKind::Local { size: 8, align: 8 })?;\nassert_eq!(s.index(), 0);\n# Ok::<(), backend_lang::mir::MirError>(())"
121);
122
123entity!(
124    /// A reference to a function by name: a call target, or a function whose
125    /// address an instruction takes. Resolved by name at emission.
126    ///
127    /// # Examples
128    ///
129    /// ```
130    /// use backend_lang::mir::Function;
131    /// use backend_lang::x86_64::SYSV;
132    ///
133    /// let mut f = Function::new("f", &SYSV);
134    /// let s = f.symbol("helper")?;
135    /// assert_eq!(f.symbol_name(s), Some("helper"));
136    /// # Ok::<(), backend_lang::mir::MirError>(())
137    /// ```
138    Symbol,
139    "sym",
140    "use backend_lang::mir::Function;\nuse backend_lang::x86_64::SYSV;\nlet mut f = Function::new(\"f\", &SYSV);\nassert_eq!(f.symbol(\"g\")?.index(), 0);\n# Ok::<(), backend_lang::mir::MirError>(())"
141);
142
143/// A condition code, numbered by the target (for x86-64, the `cc` field of
144/// `Jcc`/`SETcc`/`CMOVcc`; see [`x86_64::cond`](crate::x86_64::cond)).
145///
146/// # Examples
147///
148/// ```
149/// use backend_lang::mir::CondCode;
150/// use backend_lang::x86_64;
151/// use isa_lang::x86_64::Cond;
152///
153/// let l = x86_64::cond(Cond::L);
154/// assert_eq!(l, CondCode::new(12));
155/// assert_eq!(x86_64::TARGET.cond_name(l), "l");
156/// ```
157#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
158pub struct CondCode(u8);
159
160impl CondCode {
161    /// The condition with number `code`.
162    ///
163    /// # Examples
164    ///
165    /// ```
166    /// use backend_lang::mir::CondCode;
167    ///
168    /// assert_eq!(CondCode::new(4).code(), 4);
169    /// ```
170    #[inline]
171    #[must_use]
172    pub const fn new(code: u8) -> CondCode {
173        CondCode(code)
174    }
175
176    /// The condition's number.
177    ///
178    /// # Examples
179    ///
180    /// ```
181    /// use backend_lang::mir::CondCode;
182    ///
183    /// assert_eq!(CondCode::new(15).code(), 15);
184    /// ```
185    #[inline]
186    #[must_use]
187    pub const fn code(self) -> u8 {
188        self.0
189    }
190}