summaryrefslogtreecommitdiffstats
path: root/third_party/rust/jsparagus-stencil/src/bytecode_offset.rs
blob: 3583ec67288eba2f56625ff225a853763ff6470a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/// For tracking bytecode offsets in jumps
#[derive(Clone, Copy, PartialEq, Debug)]
#[must_use]
pub struct BytecodeOffset {
    pub offset: usize,
}

impl BytecodeOffset {
    fn new(offset: usize) -> Self {
        Self { offset }
    }

    /// diff_from is useful for finding the offset between two bytecodes. This is usually
    /// used for jumps and jump_targets.
    ///
    /// For a forward jump, self will be a larger number, and start will be smaller
    /// the output will be a positive number.  for a backward jump, the reverse
    /// will be true, and the number will be negative. So it is important to use this api
    /// consistently in both cases.
    ///
    /// Examples:
    /// let offset_diff: BytecodeOffsetDiff = forward_jump_target_offset.diff_from(jump)
    /// let offset_diff: BytecodeOffsetDiff = backward_jump_target_offset.diff_from(jump)
    pub fn diff_from(self, start: BytecodeOffset) -> BytecodeOffsetDiff {
        BytecodeOffsetDiff::new(self, start)
    }
}

impl From<BytecodeOffset> for usize {
    fn from(offset: BytecodeOffset) -> usize {
        offset.offset
    }
}

impl From<usize> for BytecodeOffset {
    fn from(offset: usize) -> BytecodeOffset {
        BytecodeOffset::new(offset)
    }
}

pub struct BytecodeOffsetDiff {
    diff: i32,
}

impl BytecodeOffsetDiff {
    fn new(end: BytecodeOffset, start: BytecodeOffset) -> Self {
        let diff = (end.offset as i128 - start.offset as i128) as i32;
        Self { diff }
    }

    pub fn uninitialized() -> Self {
        Self { diff: 0i32 }
    }
}

impl From<BytecodeOffsetDiff> for i32 {
    fn from(offset: BytecodeOffsetDiff) -> i32 {
        offset.diff
    }
}