1
//===--- ImmutableIntervalMap.h - Immutable (functional) map ---*- C++ -*-===//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
10
// This file defines the ImmutableIntervalMap class.
12
//===----------------------------------------------------------------------===//
13
#include "llvm/ADT/ImmutableMap.h"
23
Interval(int64_t S, int64_t E) : Start(S), End(E) {}
25
int64_t getStart() const { return Start; }
26
int64_t getEnd() const { return End; }
30
struct ImutIntervalInfo {
31
typedef const std::pair<Interval, T> value_type;
32
typedef const value_type &value_type_ref;
33
typedef const Interval key_type;
34
typedef const Interval &key_type_ref;
35
typedef const T data_type;
36
typedef const T &data_type_ref;
38
static key_type_ref KeyOfValue(value_type_ref V) {
42
static data_type_ref DataOfValue(value_type_ref V) {
46
static bool isEqual(key_type_ref L, key_type_ref R) {
47
return L.getStart() == R.getStart() && L.getEnd() == R.getEnd();
50
static bool isDataEqual(data_type_ref L, data_type_ref R) {
51
return ImutContainerInfo<T>::isEqual(L,R);
54
static bool isLess(key_type_ref L, key_type_ref R) {
55
// Assume L and R does not overlap.
56
if (L.getStart() < R.getStart()) {
57
assert(L.getEnd() < R.getStart());
59
} else if (L.getStart() == R.getStart()) {
60
assert(L.getEnd() == R.getEnd());
63
assert(L.getStart() > R.getEnd());
68
static bool isContainedIn(key_type_ref K, key_type_ref L) {
69
if (K.getStart() >= L.getStart() && K.getEnd() <= L.getEnd())
75
static void Profile(FoldingSetNodeID &ID, value_type_ref V) {
76
ID.AddInteger(V.first.getStart());
77
ID.AddInteger(V.first.getEnd());
78
ImutProfileInfo<T>::Profile(ID, V.second);
82
template <typename ImutInfo>
83
class ImutIntervalAVLFactory : public ImutAVLFactory<ImutInfo> {
84
typedef ImutAVLTree<ImutInfo> TreeTy;
85
typedef typename ImutInfo::value_type value_type;
86
typedef typename ImutInfo::value_type_ref value_type_ref;
87
typedef typename ImutInfo::key_type key_type;
88
typedef typename ImutInfo::key_type_ref key_type_ref;
89
typedef typename ImutInfo::data_type data_type;
90
typedef typename ImutInfo::data_type_ref data_type_ref;
93
ImutIntervalAVLFactory(BumpPtrAllocator &Alloc)
94
: ImutAVLFactory<ImutInfo>(Alloc) {}
96
TreeTy *Add(TreeTy *T, value_type_ref V) {
97
T = Add_internal(V,T);
98
this->MarkImmutable(T);
102
TreeTy *Find(TreeTy *T, key_type_ref K) {
106
key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->Value(T));
108
if (ImutInfo::isContainedIn(K, CurrentKey))
110
else if (ImutInfo::isLess(K, CurrentKey))
111
return Find(this->Left(T), K);
113
return Find(this->Right(T), K);
117
TreeTy *Add_internal(value_type_ref V, TreeTy *T) {
118
key_type_ref K = ImutInfo::KeyOfValue(V);
119
T = RemoveAllOverlaps(T, K);
120
if (this->isEmpty(T))
121
return this->CreateNode(NULL, V, NULL);
123
assert(!T->isMutable());
125
key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T));
127
if (ImutInfo::isLess(K, KCurrent))
128
return this->Balance(Add_internal(V, this->Left(T)), this->Value(T),
131
return this->Balance(this->Left(T), this->Value(T),
132
Add_internal(V, this->Right(T)));
135
// Remove all overlaps from T.
136
TreeTy *RemoveAllOverlaps(TreeTy *T, key_type_ref K) {
140
T = RemoveOverlap(T, K, Changed);
141
this->MarkImmutable(T);
147
// Remove one overlap from T.
148
TreeTy *RemoveOverlap(TreeTy *T, key_type_ref K, bool &Changed) {
151
Interval CurrentK = ImutInfo::KeyOfValue(this->Value(T));
153
// If current key does not overlap the inserted key.
154
if (CurrentK.getStart() > K.getEnd())
155
return this->Balance(RemoveOverlap(this->Left(T), K, Changed),
156
this->Value(T), this->Right(T));
157
else if (CurrentK.getEnd() < K.getStart())
158
return this->Balance(this->Left(T), this->Value(T),
159
RemoveOverlap(this->Right(T), K, Changed));
161
// Current key overlaps with the inserted key.
162
// Remove the current key.
164
data_type_ref OldData = ImutInfo::DataOfValue(this->Value(T));
165
T = this->Remove_internal(CurrentK, T);
166
// Add back the unoverlapped part of the current key.
167
if (CurrentK.getStart() < K.getStart()) {
168
if (CurrentK.getEnd() <= K.getEnd()) {
169
Interval NewK(CurrentK.getStart(), K.getStart()-1);
170
return Add_internal(std::make_pair(NewK, OldData), T);
172
Interval NewK1(CurrentK.getStart(), K.getStart()-1);
173
T = Add_internal(std::make_pair(NewK1, OldData), T);
175
Interval NewK2(K.getEnd()+1, CurrentK.getEnd());
176
return Add_internal(std::make_pair(NewK2, OldData), T);
179
if (CurrentK.getEnd() > K.getEnd()) {
180
Interval NewK(K.getEnd()+1, CurrentK.getEnd());
181
return Add_internal(std::make_pair(NewK, OldData), T);
188
/// ImmutableIntervalMap maps an interval [start, end] to a value. The intervals
189
/// in the map are guaranteed to be disjoint.
190
template <typename ValT>
191
class ImmutableIntervalMap
192
: public ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> > {
194
typedef typename ImutIntervalInfo<ValT>::value_type value_type;
195
typedef typename ImutIntervalInfo<ValT>::value_type_ref value_type_ref;
196
typedef typename ImutIntervalInfo<ValT>::key_type key_type;
197
typedef typename ImutIntervalInfo<ValT>::key_type_ref key_type_ref;
198
typedef typename ImutIntervalInfo<ValT>::data_type data_type;
199
typedef typename ImutIntervalInfo<ValT>::data_type_ref data_type_ref;
200
typedef ImutAVLTree<ImutIntervalInfo<ValT> > TreeTy;
203
explicit ImmutableIntervalMap(TreeTy *R)
204
: ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> >(R) {}
207
ImutIntervalAVLFactory<ImutIntervalInfo<ValT> > F;
210
Factory(BumpPtrAllocator& Alloc) : F(Alloc) {}
212
ImmutableIntervalMap GetEmptyMap() {
213
return ImmutableIntervalMap(F.GetEmptyTree());
216
ImmutableIntervalMap Add(ImmutableIntervalMap Old,
217
key_type_ref K, data_type_ref D) {
218
TreeTy *T = F.Add(Old.Root, std::make_pair<key_type, data_type>(K, D));
219
return ImmutableIntervalMap(F.GetCanonicalTree(T));
222
ImmutableIntervalMap Remove(ImmutableIntervalMap Old, key_type_ref K) {
223
TreeTy *T = F.Remove(Old.Root, K);
224
return ImmutableIntervalMap(F.GetCanonicalTree(T));
227
data_type *Lookup(ImmutableIntervalMap M, key_type_ref K) {
228
TreeTy *T = F.Find(M.getRoot(), K);
230
return &T->getValue().second;
237
// For ImmutableIntervalMap, the lookup operation has to be done by the
239
data_type* lookup(key_type_ref K) const;
242
} // end namespace llvm