1#[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#[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}