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}