cranelift_codegen/ir/
sourceloc.rs1use core::fmt;
7#[cfg(feature = "enable-serde")]
8use serde_derive::{Deserialize, Serialize};
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
19#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
20pub struct SourceLoc(u32);
21
22impl SourceLoc {
23 pub fn new(bits: u32) -> Self {
25 Self(bits)
26 }
27
28 pub fn is_default(self) -> bool {
30 self == Default::default()
31 }
32
33 pub fn bits(self) -> u32 {
35 self.0
36 }
37}
38
39impl Default for SourceLoc {
40 fn default() -> Self {
41 Self(0x7fff_ffff)
42 }
43}
44
45impl fmt::Display for SourceLoc {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 if self.is_default() {
48 write!(f, "@-")
49 } else {
50 write!(f, "@{:04x}", self.0)
51 }
52 }
53}
54
55#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
57#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
58pub struct RelSourceLoc(u32);
59
60impl RelSourceLoc {
61 pub fn new(bits: u32) -> Self {
63 Self(bits)
64 }
65
66 pub fn from_base_offset(base: SourceLoc, offset: SourceLoc) -> Self {
68 if base.is_default() || offset.is_default() {
69 Self::default()
70 } else {
71 Self(offset.bits().wrapping_sub(base.bits()) & MaybeRelSourceLoc::MASK)
74 }
75 }
76
77 pub fn expand(&self, base: SourceLoc) -> SourceLoc {
79 if self.is_default() || base.is_default() {
80 Default::default()
81 } else {
82 SourceLoc::new(self.0.wrapping_add(base.bits()) & MaybeRelSourceLoc::MASK)
83 }
84 }
85
86 pub fn is_default(self) -> bool {
88 self == Default::default()
89 }
90}
91
92impl Default for RelSourceLoc {
93 fn default() -> Self {
94 Self(0x7fff_ffff)
95 }
96}
97
98impl fmt::Display for RelSourceLoc {
99 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100 if self.is_default() {
101 write!(f, "@-")
102 } else {
103 write!(f, "@+{:04x}", self.0)
104 }
105 }
106}
107
108#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
123#[cfg_attr(
124 feature = "enable-serde",
125 derive(serde_derive::Serialize, serde_derive::Deserialize)
126)]
127pub struct MaybeRelSourceLoc(u32);
128
129impl MaybeRelSourceLoc {
130 const REL_BIT: u32 = 0x8000_0000;
131 const MASK: u32 = !Self::REL_BIT;
132
133 pub fn rel(loc: RelSourceLoc) -> Self {
135 debug_assert!(loc.0 & Self::MASK == loc.0);
136 MaybeRelSourceLoc(loc.0 | Self::REL_BIT)
137 }
138
139 pub fn abs(loc: SourceLoc) -> Self {
141 debug_assert!(loc.0 & Self::MASK == loc.0);
142 MaybeRelSourceLoc(loc.0)
143 }
144
145 pub fn is_rel(&self) -> bool {
147 self.0 & Self::REL_BIT != 0
148 }
149
150 pub fn is_abs(&self) -> bool {
152 self.0 & Self::REL_BIT == 0
153 }
154
155 pub fn as_rel(&self) -> RelSourceLoc {
161 assert!(self.is_rel());
162 RelSourceLoc(self.0 & Self::MASK)
163 }
164
165 pub fn as_abs(&self) -> SourceLoc {
171 assert!(self.is_abs());
172 SourceLoc(self.0)
173 }
174
175 pub fn relocate(&self, base: SourceLoc) -> SourceLoc {
182 self.as_rel().expand(base)
183 }
184}
185
186#[cfg(test)]
187mod tests {
188 use crate::ir::SourceLoc;
189 use alloc::string::ToString;
190
191 #[test]
192 fn display() {
193 assert_eq!(SourceLoc::default().to_string(), "@-");
194 assert_eq!(SourceLoc::new(0).to_string(), "@0000");
195 assert_eq!(SourceLoc::new(16).to_string(), "@0010");
196 assert_eq!(SourceLoc::new(0xabcdef).to_string(), "@abcdef");
197 }
198}