summaryrefslogtreecommitdiff
path: root/vendor/github.com/mmcloughlin/avo/reg/set.go
blob: 2cf88147c562e61c2c5b873952667a717506d7a1 (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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package reg

// MaskSet maps register IDs to masks.
type MaskSet map[ID]uint16

// NewEmptyMaskSet builds an empty register mask set.
func NewEmptyMaskSet() MaskSet {
	return MaskSet{}
}

// NewMaskSetFromRegisters forms a mask set from the given register list.
func NewMaskSetFromRegisters(rs []Register) MaskSet {
	s := NewEmptyMaskSet()
	for _, r := range rs {
		s.AddRegister(r)
	}
	return s
}

// Clone returns a copy of s.
func (s MaskSet) Clone() MaskSet {
	c := NewEmptyMaskSet()
	for id, mask := range s {
		c.Add(id, mask)
	}
	return c
}

// Add mask to the given register ID.
// Reports whether this made any change to the set.
func (s MaskSet) Add(id ID, mask uint16) bool {
	if (s[id] & mask) == mask {
		return false
	}
	s[id] |= mask
	return true
}

// AddRegister is a convenience for adding the register's (ID, mask) to the set.
// Reports whether this made any change to the set.
func (s MaskSet) AddRegister(r Register) bool {
	return s.Add(r.ID(), r.Mask())
}

// Discard clears masked bits from register ID.
// Reports whether this made any change to the set.
func (s MaskSet) Discard(id ID, mask uint16) bool {
	if curr, found := s[id]; !found || (curr&mask) == 0 {
		return false
	}
	s[id] &^= mask
	if s[id] == 0 {
		delete(s, id)
	}
	return true
}

// DiscardRegister is a convenience for discarding the register's (ID, mask) from the set.
// Reports whether this made any change to the set.
func (s MaskSet) DiscardRegister(r Register) bool {
	return s.Discard(r.ID(), r.Mask())
}

// Update adds masks in t to s.
// Reports whether this made any change to the set.
func (s MaskSet) Update(t MaskSet) bool {
	change := false
	for id, mask := range t {
		change = s.Add(id, mask) || change
	}
	return change
}

// Difference returns the set of registers in s but not t.
func (s MaskSet) Difference(t MaskSet) MaskSet {
	d := s.Clone()
	d.DifferenceUpdate(t)
	return d
}

// DifferenceUpdate removes every element of t from s.
func (s MaskSet) DifferenceUpdate(t MaskSet) bool {
	change := false
	for id, mask := range t {
		change = s.Discard(id, mask) || change
	}
	return change
}

// Equals returns true if s and t contain the same masks.
func (s MaskSet) Equals(t MaskSet) bool {
	if len(s) != len(t) {
		return false
	}
	for id, mask := range s {
		if _, found := t[id]; !found || mask != t[id] {
			return false
		}
	}
	return true
}

// OfKind returns the set of elements of s with kind k.
func (s MaskSet) OfKind(k Kind) MaskSet {
	t := NewEmptyMaskSet()
	for id, mask := range s {
		if id.Kind() == k {
			t.Add(id, mask)
		}
	}
	return t
}