Skip to main content

celox_analysis/
memory.rs

1//! Memory locations and byte-range aliasing.
2//!
3//! These types are one alias-domain implementation.  MemorySSA itself does
4//! not depend on them: clients may use a different query and alias oracle.
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct MemoryLocation<O> {
8    pub object: O,
9    pub offset: i64,
10    pub byte_len: usize,
11}
12
13impl<O: Copy> MemoryLocation<O> {
14    #[must_use]
15    pub fn end(self) -> Option<i64> {
16        self.offset.checked_add(i64::try_from(self.byte_len).ok()?)
17    }
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum MemoryEffect<O> {
22    Exact(MemoryLocation<O>),
23    UnknownObject(O),
24    UnknownAll,
25}
26
27/// Conservatively decide whether two byte-range effects may touch the same
28/// memory.  Callers are responsible for rejecting empty or overflowing exact
29/// ranges when constructing their IR adapter.
30#[must_use]
31pub fn effects_may_alias<O: Copy + Eq>(left: MemoryEffect<O>, right: MemoryEffect<O>) -> bool {
32    match (left, right) {
33        (MemoryEffect::UnknownAll, _) | (_, MemoryEffect::UnknownAll) => true,
34        (MemoryEffect::UnknownObject(left), MemoryEffect::UnknownObject(right)) => left == right,
35        (MemoryEffect::UnknownObject(object), MemoryEffect::Exact(location))
36        | (MemoryEffect::Exact(location), MemoryEffect::UnknownObject(object)) => {
37            object == location.object
38        }
39        (MemoryEffect::Exact(left), MemoryEffect::Exact(right)) => {
40            if left.object != right.object {
41                return false;
42            }
43            let (Some(left_end), Some(right_end)) = (left.end(), right.end()) else {
44                return true;
45            };
46            left.offset < right_end && right.offset < left_end
47        }
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    fn exact(object: u8, offset: i64, byte_len: usize) -> MemoryEffect<u8> {
56        MemoryEffect::Exact(MemoryLocation {
57            object,
58            offset,
59            byte_len,
60        })
61    }
62
63    #[test]
64    fn exact_aliasing_is_object_and_half_open_range_based() {
65        assert!(effects_may_alias(exact(1, 4, 8), exact(1, 8, 8)));
66        assert!(!effects_may_alias(exact(1, 0, 8), exact(1, 8, 8)));
67        assert!(!effects_may_alias(exact(1, 4, 8), exact(2, 4, 8)));
68    }
69
70    #[test]
71    fn unknown_effects_are_conservative_within_their_domain() {
72        assert!(effects_may_alias(
73            MemoryEffect::UnknownObject(1),
74            exact(1, 64, 8)
75        ));
76        assert!(!effects_may_alias(
77            MemoryEffect::UnknownObject(1),
78            exact(2, 64, 8)
79        ));
80        assert!(effects_may_alias(MemoryEffect::UnknownAll, exact(2, 64, 8)));
81    }
82}