/src/wasmtime/cranelift/codegen/src/ir/sourceloc.rs
Line | Count | Source |
1 | | //! Source locations. |
2 | | //! |
3 | | //! Cranelift tracks the original source location of each instruction, and preserves the source |
4 | | //! location when instructions are transformed. |
5 | | |
6 | | use core::fmt; |
7 | | #[cfg(feature = "enable-serde")] |
8 | | use serde_derive::{Deserialize, Serialize}; |
9 | | |
10 | | /// A source location. |
11 | | /// |
12 | | /// This is an opaque 32-bit number attached to each Cranelift IR instruction. Cranelift does not |
13 | | /// interpret source locations in any way, they are simply preserved from the input to the output. |
14 | | /// |
15 | | /// The default source location uses the all-ones bit pattern `!0`. It is used for instructions |
16 | | /// that can't be given a real source location. |
17 | | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
18 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
19 | | pub struct SourceLoc(u32); |
20 | | |
21 | | impl SourceLoc { |
22 | | /// Create a new source location with the given bits. |
23 | 92.4M | pub fn new(bits: u32) -> Self { |
24 | 92.4M | Self(bits) |
25 | 92.4M | } |
26 | | |
27 | | /// Is this the default source location? |
28 | 265M | pub fn is_default(self) -> bool { |
29 | 265M | self == Default::default() |
30 | 265M | } |
31 | | |
32 | | /// Read the bits of this source location. |
33 | 159M | pub fn bits(self) -> u32 { |
34 | 159M | self.0 |
35 | 159M | } |
36 | | } |
37 | | |
38 | | impl Default for SourceLoc { |
39 | 381M | fn default() -> Self { |
40 | 381M | Self(!0) |
41 | 381M | } |
42 | | } |
43 | | |
44 | | impl fmt::Display for SourceLoc { |
45 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
46 | 0 | if self.is_default() { |
47 | 0 | write!(f, "@-") |
48 | | } else { |
49 | 0 | write!(f, "@{:04x}", self.0) |
50 | | } |
51 | 0 | } |
52 | | } |
53 | | |
54 | | /// Source location relative to another base source location. |
55 | | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
56 | | #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] |
57 | | pub struct RelSourceLoc(u32); |
58 | | |
59 | | impl RelSourceLoc { |
60 | | /// Create a new relative source location with the given bits. |
61 | 0 | pub fn new(bits: u32) -> Self { |
62 | 0 | Self(bits) |
63 | 0 | } |
64 | | |
65 | | /// Creates a new `RelSourceLoc` based on the given base and offset. |
66 | 65.9M | pub fn from_base_offset(base: SourceLoc, offset: SourceLoc) -> Self { |
67 | 65.9M | if base.is_default() || offset.is_default() { |
68 | 206k | Self::default() |
69 | | } else { |
70 | 65.7M | Self(offset.bits().wrapping_sub(base.bits())) |
71 | | } |
72 | 65.9M | } |
73 | | |
74 | | /// Expands the relative source location into an absolute one, using the given base. |
75 | 33.9M | pub fn expand(&self, base: SourceLoc) -> SourceLoc { |
76 | 33.9M | if self.is_default() || base.is_default() { |
77 | 17.3M | Default::default() |
78 | | } else { |
79 | 16.5M | SourceLoc::new(self.0.wrapping_add(base.bits())) |
80 | | } |
81 | 33.9M | } |
82 | | |
83 | | /// Is this the default relative source location? |
84 | 37.6M | pub fn is_default(self) -> bool { |
85 | 37.6M | self == Default::default() |
86 | 37.6M | } |
87 | | } |
88 | | |
89 | | impl Default for RelSourceLoc { |
90 | 51.9M | fn default() -> Self { |
91 | 51.9M | Self(!0) |
92 | 51.9M | } |
93 | | } |
94 | | |
95 | | impl fmt::Display for RelSourceLoc { |
96 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
97 | 0 | if self.is_default() { |
98 | 0 | write!(f, "@-") |
99 | | } else { |
100 | 0 | write!(f, "@+{:04x}", self.0) |
101 | | } |
102 | 0 | } |
103 | | } |
104 | | |
105 | | #[cfg(test)] |
106 | | mod tests { |
107 | | use crate::ir::SourceLoc; |
108 | | use alloc::string::ToString; |
109 | | |
110 | | #[test] |
111 | | fn display() { |
112 | | assert_eq!(SourceLoc::default().to_string(), "@-"); |
113 | | assert_eq!(SourceLoc::new(0).to_string(), "@0000"); |
114 | | assert_eq!(SourceLoc::new(16).to_string(), "@0010"); |
115 | | assert_eq!(SourceLoc::new(0xabcdef).to_string(), "@abcdef"); |
116 | | } |
117 | | } |