1747ad3c4Slazypassion //! Source locations.
2747ad3c4Slazypassion //!
3747ad3c4Slazypassion //! Cranelift tracks the original source location of each instruction, and preserves the source
4747ad3c4Slazypassion //! location when instructions are transformed.
5747ad3c4Slazypassion 
6747ad3c4Slazypassion use core::fmt;
79e884b44SArtur Jamro #[cfg(feature = "enable-serde")]
8*9ec02f9dSChristopher Serr use serde_derive::{Deserialize, Serialize};
9747ad3c4Slazypassion 
10747ad3c4Slazypassion /// A source location.
11747ad3c4Slazypassion ///
12747ad3c4Slazypassion /// This is an opaque 32-bit number attached to each Cranelift IR instruction. Cranelift does not
13747ad3c4Slazypassion /// interpret source locations in any way, they are simply preserved from the input to the output.
14747ad3c4Slazypassion ///
15747ad3c4Slazypassion /// The default source location uses the all-ones bit pattern `!0`. It is used for instructions
16747ad3c4Slazypassion /// that can't be given a real source location.
172be12a51SChris Fallin #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
189e884b44SArtur Jamro #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
19747ad3c4Slazypassion pub struct SourceLoc(u32);
20747ad3c4Slazypassion 
21747ad3c4Slazypassion impl SourceLoc {
22747ad3c4Slazypassion     /// Create a new source location with the given bits.
new(bits: u32) -> Self23747ad3c4Slazypassion     pub fn new(bits: u32) -> Self {
249f506692SPeter Huene         Self(bits)
25747ad3c4Slazypassion     }
26747ad3c4Slazypassion 
27747ad3c4Slazypassion     /// Is this the default source location?
is_default(self) -> bool28747ad3c4Slazypassion     pub fn is_default(self) -> bool {
29747ad3c4Slazypassion         self == Default::default()
30747ad3c4Slazypassion     }
31747ad3c4Slazypassion 
32747ad3c4Slazypassion     /// Read the bits of this source location.
bits(self) -> u3233747ad3c4Slazypassion     pub fn bits(self) -> u32 {
34747ad3c4Slazypassion         self.0
35747ad3c4Slazypassion     }
36747ad3c4Slazypassion }
37747ad3c4Slazypassion 
38747ad3c4Slazypassion impl Default for SourceLoc {
default() -> Self39747ad3c4Slazypassion     fn default() -> Self {
409f506692SPeter Huene         Self(!0)
41747ad3c4Slazypassion     }
42747ad3c4Slazypassion }
43747ad3c4Slazypassion 
44747ad3c4Slazypassion impl fmt::Display for SourceLoc {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result45747ad3c4Slazypassion     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46747ad3c4Slazypassion         if self.is_default() {
47747ad3c4Slazypassion             write!(f, "@-")
48747ad3c4Slazypassion         } else {
49747ad3c4Slazypassion             write!(f, "@{:04x}", self.0)
50747ad3c4Slazypassion         }
51747ad3c4Slazypassion     }
52747ad3c4Slazypassion }
53747ad3c4Slazypassion 
548a9b1a90SBenjamin Bouvier /// Source location relative to another base source location.
558a9b1a90SBenjamin Bouvier #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
568a9b1a90SBenjamin Bouvier #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
578a9b1a90SBenjamin Bouvier pub struct RelSourceLoc(u32);
588a9b1a90SBenjamin Bouvier 
598a9b1a90SBenjamin Bouvier impl RelSourceLoc {
608a9b1a90SBenjamin Bouvier     /// Create a new relative source location with the given bits.
new(bits: u32) -> Self618a9b1a90SBenjamin Bouvier     pub fn new(bits: u32) -> Self {
628a9b1a90SBenjamin Bouvier         Self(bits)
638a9b1a90SBenjamin Bouvier     }
648a9b1a90SBenjamin Bouvier 
658a9b1a90SBenjamin Bouvier     /// Creates a new `RelSourceLoc` based on the given base and offset.
from_base_offset(base: SourceLoc, offset: SourceLoc) -> Self668a9b1a90SBenjamin Bouvier     pub fn from_base_offset(base: SourceLoc, offset: SourceLoc) -> Self {
678a9b1a90SBenjamin Bouvier         if base.is_default() || offset.is_default() {
688a9b1a90SBenjamin Bouvier             Self::default()
698a9b1a90SBenjamin Bouvier         } else {
708a9b1a90SBenjamin Bouvier             Self(offset.bits().wrapping_sub(base.bits()))
718a9b1a90SBenjamin Bouvier         }
728a9b1a90SBenjamin Bouvier     }
738a9b1a90SBenjamin Bouvier 
748a9b1a90SBenjamin Bouvier     /// Expands the relative source location into an absolute one, using the given base.
expand(&self, base: SourceLoc) -> SourceLoc758a9b1a90SBenjamin Bouvier     pub fn expand(&self, base: SourceLoc) -> SourceLoc {
768a9b1a90SBenjamin Bouvier         if self.is_default() || base.is_default() {
778a9b1a90SBenjamin Bouvier             Default::default()
788a9b1a90SBenjamin Bouvier         } else {
798a9b1a90SBenjamin Bouvier             SourceLoc::new(self.0.wrapping_add(base.bits()))
808a9b1a90SBenjamin Bouvier         }
818a9b1a90SBenjamin Bouvier     }
828a9b1a90SBenjamin Bouvier 
838a9b1a90SBenjamin Bouvier     /// Is this the default relative source location?
is_default(self) -> bool848a9b1a90SBenjamin Bouvier     pub fn is_default(self) -> bool {
858a9b1a90SBenjamin Bouvier         self == Default::default()
868a9b1a90SBenjamin Bouvier     }
878a9b1a90SBenjamin Bouvier }
888a9b1a90SBenjamin Bouvier 
898a9b1a90SBenjamin Bouvier impl Default for RelSourceLoc {
default() -> Self908a9b1a90SBenjamin Bouvier     fn default() -> Self {
918a9b1a90SBenjamin Bouvier         Self(!0)
928a9b1a90SBenjamin Bouvier     }
938a9b1a90SBenjamin Bouvier }
948a9b1a90SBenjamin Bouvier 
958a9b1a90SBenjamin Bouvier impl fmt::Display for RelSourceLoc {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result968a9b1a90SBenjamin Bouvier     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
978a9b1a90SBenjamin Bouvier         if self.is_default() {
988a9b1a90SBenjamin Bouvier             write!(f, "@-")
998a9b1a90SBenjamin Bouvier         } else {
1008a9b1a90SBenjamin Bouvier             write!(f, "@+{:04x}", self.0)
1018a9b1a90SBenjamin Bouvier         }
1028a9b1a90SBenjamin Bouvier     }
1038a9b1a90SBenjamin Bouvier }
1048a9b1a90SBenjamin Bouvier 
105747ad3c4Slazypassion #[cfg(test)]
106747ad3c4Slazypassion mod tests {
107747ad3c4Slazypassion     use crate::ir::SourceLoc;
10810e226f9Sbjorn3     use alloc::string::ToString;
109747ad3c4Slazypassion 
110747ad3c4Slazypassion     #[test]
display()111747ad3c4Slazypassion     fn display() {
112747ad3c4Slazypassion         assert_eq!(SourceLoc::default().to_string(), "@-");
113747ad3c4Slazypassion         assert_eq!(SourceLoc::new(0).to_string(), "@0000");
114747ad3c4Slazypassion         assert_eq!(SourceLoc::new(16).to_string(), "@0010");
115747ad3c4Slazypassion         assert_eq!(SourceLoc::new(0xabcdef).to_string(), "@abcdef");
116747ad3c4Slazypassion     }
117747ad3c4Slazypassion }
118