Coverage Report

Created: 2026-08-28 08:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}