mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-17 03:07:06 +00:00
9c336fabd5
to use lowercase letters for the start of most method names and to replace some method names with more descriptive names (e.g., "getLeft()" instead of "Left()"). No real functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120070 91177308-0d34-0410-b5e6-96231b3b80d8
243 lines
7.4 KiB
C++
243 lines
7.4 KiB
C++
//===--- ImmutableIntervalMap.h - Immutable (functional) map ---*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the ImmutableIntervalMap class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "llvm/ADT/ImmutableMap.h"
|
|
|
|
namespace llvm {
|
|
|
|
class Interval {
|
|
private:
|
|
int64_t Start;
|
|
int64_t End;
|
|
|
|
public:
|
|
Interval(int64_t S, int64_t E) : Start(S), End(E) {}
|
|
|
|
int64_t getStart() const { return Start; }
|
|
int64_t getEnd() const { return End; }
|
|
};
|
|
|
|
template <typename T>
|
|
struct ImutIntervalInfo {
|
|
typedef const std::pair<Interval, T> value_type;
|
|
typedef const value_type &value_type_ref;
|
|
typedef const Interval key_type;
|
|
typedef const Interval &key_type_ref;
|
|
typedef const T data_type;
|
|
typedef const T &data_type_ref;
|
|
|
|
static key_type_ref KeyOfValue(value_type_ref V) {
|
|
return V.first;
|
|
}
|
|
|
|
static data_type_ref DataOfValue(value_type_ref V) {
|
|
return V.second;
|
|
}
|
|
|
|
static bool isEqual(key_type_ref L, key_type_ref R) {
|
|
return L.getStart() == R.getStart() && L.getEnd() == R.getEnd();
|
|
}
|
|
|
|
static bool isDataEqual(data_type_ref L, data_type_ref R) {
|
|
return ImutContainerInfo<T>::isEqual(L,R);
|
|
}
|
|
|
|
static bool isLess(key_type_ref L, key_type_ref R) {
|
|
// Assume L and R does not overlap.
|
|
if (L.getStart() < R.getStart()) {
|
|
assert(L.getEnd() < R.getStart());
|
|
return true;
|
|
} else if (L.getStart() == R.getStart()) {
|
|
assert(L.getEnd() == R.getEnd());
|
|
return false;
|
|
} else {
|
|
assert(L.getStart() > R.getEnd());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static bool isContainedIn(key_type_ref K, key_type_ref L) {
|
|
if (K.getStart() >= L.getStart() && K.getEnd() <= L.getEnd())
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
static void Profile(FoldingSetNodeID &ID, value_type_ref V) {
|
|
ID.AddInteger(V.first.getStart());
|
|
ID.AddInteger(V.first.getEnd());
|
|
ImutProfileInfo<T>::Profile(ID, V.second);
|
|
}
|
|
};
|
|
|
|
template <typename ImutInfo>
|
|
class ImutIntervalAVLFactory : public ImutAVLFactory<ImutInfo> {
|
|
typedef ImutAVLTree<ImutInfo> TreeTy;
|
|
typedef typename ImutInfo::value_type value_type;
|
|
typedef typename ImutInfo::value_type_ref value_type_ref;
|
|
typedef typename ImutInfo::key_type key_type;
|
|
typedef typename ImutInfo::key_type_ref key_type_ref;
|
|
typedef typename ImutInfo::data_type data_type;
|
|
typedef typename ImutInfo::data_type_ref data_type_ref;
|
|
|
|
public:
|
|
ImutIntervalAVLFactory(BumpPtrAllocator &Alloc)
|
|
: ImutAVLFactory<ImutInfo>(Alloc) {}
|
|
|
|
TreeTy *Add(TreeTy *T, value_type_ref V) {
|
|
T = add_internal(V,T);
|
|
this->MarkImmutable(T);
|
|
return T;
|
|
}
|
|
|
|
TreeTy *Find(TreeTy *T, key_type_ref K) {
|
|
if (!T)
|
|
return NULL;
|
|
|
|
key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->getValue(T));
|
|
|
|
if (ImutInfo::isContainedIn(K, CurrentKey))
|
|
return T;
|
|
else if (ImutInfo::isLess(K, CurrentKey))
|
|
return Find(this->getLeft(T), K);
|
|
else
|
|
return Find(this->getRight(T), K);
|
|
}
|
|
|
|
private:
|
|
TreeTy *add_internal(value_type_ref V, TreeTy *T) {
|
|
key_type_ref K = ImutInfo::KeyOfValue(V);
|
|
T = removeAllOverlaps(T, K);
|
|
if (this->isEmpty(T))
|
|
return this->CreateNode(NULL, V, NULL);
|
|
|
|
assert(!T->isMutable());
|
|
|
|
key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T));
|
|
|
|
if (ImutInfo::isLess(K, KCurrent))
|
|
return this->Balance(add_internal(V, this->Left(T)), this->Value(T),
|
|
this->Right(T));
|
|
else
|
|
return this->Balance(this->Left(T), this->Value(T),
|
|
add_internal(V, this->Right(T)));
|
|
}
|
|
|
|
// Remove all overlaps from T.
|
|
TreeTy *removeAllOverlaps(TreeTy *T, key_type_ref K) {
|
|
bool Changed;
|
|
do {
|
|
Changed = false;
|
|
T = removeOverlap(T, K, Changed);
|
|
this->markImmutable(T);
|
|
} while (Changed);
|
|
|
|
return T;
|
|
}
|
|
|
|
// Remove one overlap from T.
|
|
TreeTy *removeOverlap(TreeTy *T, key_type_ref K, bool &Changed) {
|
|
if (!T)
|
|
return NULL;
|
|
Interval CurrentK = ImutInfo::KeyOfValue(this->Value(T));
|
|
|
|
// If current key does not overlap the inserted key.
|
|
if (CurrentK.getStart() > K.getEnd())
|
|
return this->Balance(removeOverlap(this->Left(T), K, Changed),
|
|
this->Value(T), this->Right(T));
|
|
else if (CurrentK.getEnd() < K.getStart())
|
|
return this->Balance(this->Left(T), this->Value(T),
|
|
removeOverlap(this->Right(T), K, Changed));
|
|
|
|
// Current key overlaps with the inserted key.
|
|
// Remove the current key.
|
|
Changed = true;
|
|
data_type_ref OldData = ImutInfo::DataOfValue(this->Value(T));
|
|
T = this->Remove_internal(CurrentK, T);
|
|
// Add back the unoverlapped part of the current key.
|
|
if (CurrentK.getStart() < K.getStart()) {
|
|
if (CurrentK.getEnd() <= K.getEnd()) {
|
|
Interval NewK(CurrentK.getStart(), K.getStart()-1);
|
|
return add_internal(std::make_pair(NewK, OldData), T);
|
|
} else {
|
|
Interval NewK1(CurrentK.getStart(), K.getStart()-1);
|
|
T = add_internal(std::make_pair(NewK1, OldData), T);
|
|
|
|
Interval NewK2(K.getEnd()+1, CurrentK.getEnd());
|
|
return add_internal(std::make_pair(NewK2, OldData), T);
|
|
}
|
|
} else {
|
|
if (CurrentK.getEnd() > K.getEnd()) {
|
|
Interval NewK(K.getEnd()+1, CurrentK.getEnd());
|
|
return add_internal(std::make_pair(NewK, OldData), T);
|
|
} else
|
|
return T;
|
|
}
|
|
}
|
|
};
|
|
|
|
/// ImmutableIntervalMap maps an interval [start, end] to a value. The intervals
|
|
/// in the map are guaranteed to be disjoint.
|
|
template <typename ValT>
|
|
class ImmutableIntervalMap
|
|
: public ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> > {
|
|
|
|
typedef typename ImutIntervalInfo<ValT>::value_type value_type;
|
|
typedef typename ImutIntervalInfo<ValT>::value_type_ref value_type_ref;
|
|
typedef typename ImutIntervalInfo<ValT>::key_type key_type;
|
|
typedef typename ImutIntervalInfo<ValT>::key_type_ref key_type_ref;
|
|
typedef typename ImutIntervalInfo<ValT>::data_type data_type;
|
|
typedef typename ImutIntervalInfo<ValT>::data_type_ref data_type_ref;
|
|
typedef ImutAVLTree<ImutIntervalInfo<ValT> > TreeTy;
|
|
|
|
public:
|
|
explicit ImmutableIntervalMap(TreeTy *R)
|
|
: ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> >(R) {}
|
|
|
|
class Factory {
|
|
ImutIntervalAVLFactory<ImutIntervalInfo<ValT> > F;
|
|
|
|
public:
|
|
Factory(BumpPtrAllocator& Alloc) : F(Alloc) {}
|
|
|
|
ImmutableIntervalMap getEmptyMap() {
|
|
return ImmutableIntervalMap(F.getEmptyTree());
|
|
}
|
|
|
|
ImmutableIntervalMap add(ImmutableIntervalMap Old,
|
|
key_type_ref K, data_type_ref D) {
|
|
TreeTy *T = F.add(Old.Root, std::make_pair<key_type, data_type>(K, D));
|
|
return ImmutableIntervalMap(F.getCanonicalTree(T));
|
|
}
|
|
|
|
ImmutableIntervalMap remove(ImmutableIntervalMap Old, key_type_ref K) {
|
|
TreeTy *T = F.remove(Old.Root, K);
|
|
return ImmutableIntervalMap(F.getCanonicalTree(T));
|
|
}
|
|
|
|
data_type *lookup(ImmutableIntervalMap M, key_type_ref K) {
|
|
TreeTy *T = F.Find(M.getRoot(), K);
|
|
if (T)
|
|
return &T->getValue().second;
|
|
else
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
private:
|
|
// For ImmutableIntervalMap, the lookup operation has to be done by the
|
|
// factory.
|
|
data_type* lookup(key_type_ref K) const;
|
|
};
|
|
|
|
} // end namespace llvm
|