mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
Add an immutable interval map, prepared to be used by flat memory model
in the analyzer. WIP. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94976 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7bb2929512
commit
746f5b6eb1
199
include/llvm/ADT/ImmutableIntervalMap.h
Normal file
199
include/llvm/ADT/ImmutableIntervalMap.h
Normal file
@ -0,0 +1,199 @@
|
||||
//===--- 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:
|
||||
uint64_t Start;
|
||||
uint64_t End;
|
||||
|
||||
public:
|
||||
Interval(uint64_t S, uint64_t E) : Start(S), End(E) {}
|
||||
|
||||
uint64_t getStart() const { return Start; }
|
||||
uint64_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 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;
|
||||
|
||||
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:
|
||||
TreeTy *Add(TreeTy* T, value_type_ref V) {
|
||||
T = Add_internal(V,T);
|
||||
MarkImmutable(T);
|
||||
return T;
|
||||
}
|
||||
|
||||
private:
|
||||
TreeTy *Add_internal(value_type_ref V, TreeTy *T) {
|
||||
if (isEmpty(T))
|
||||
return CreateNode(NULL, V, NULL);
|
||||
|
||||
assert(!T->isMutable());
|
||||
|
||||
key_type_ref K = ImutInfo::KeyOfValue(V);
|
||||
key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T));
|
||||
|
||||
T = RemoveAllOverlaps(T, K);
|
||||
|
||||
if (ImutInfo::isLess(K, KCurrent))
|
||||
return Balance(Add_internal(V, Left(T)), Value(T), Right(T));
|
||||
else
|
||||
return Balance(Left(T), Value(T), Add_internal(V, Right(T)));
|
||||
}
|
||||
|
||||
// Remove all overlaps from T.
|
||||
TreeTy *RemoveAllOverlaps(TreeTy *T, key_type_ref K) {
|
||||
TreeTy *OldTree, *NewTree;
|
||||
NewTree = T;
|
||||
do {
|
||||
OldTree = NewTree;
|
||||
NewTree = RemoveOverlap(OldTree, K);
|
||||
} while (NewTree != OldTree);
|
||||
}
|
||||
|
||||
// Remove one overlap from T.
|
||||
TreeTy *RemoveOverlap(TreeTy *T, key_type_ref K) {
|
||||
Interval CurrentK = ImutInfo::KeyOfValue(Value(T));
|
||||
|
||||
// If current key does not overlap the inserted key.
|
||||
if (CurrentK.getStart() > K.getEnd())
|
||||
return RemoveOverlap(Left(T), K);
|
||||
else if (CurrentK.getEnd() < K.getStart())
|
||||
return RemoveOverlap(Right(T), K);
|
||||
|
||||
// Current key overlaps with the inserted key.
|
||||
// Remove the current key.
|
||||
T = 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<key_type, data_type>(NewK,
|
||||
ImutInfo::DataOfValue(Value(T))), T);
|
||||
} else {
|
||||
Interval NewK1(CurrentK.getStart(), K.getStart()-1);
|
||||
T = Add_internal(std::make_pair<key_type, data_type>(NewK1,
|
||||
ImutInfo::DataOfValue(Value(T))), T);
|
||||
|
||||
Interval NewK2(K.getEnd()+1, CurrentK.getEnd());
|
||||
return Add_internal(std::make_pair<key_type, data_type>(NewK2,
|
||||
ImutInfo::DataOfValue(Value(T))), T);
|
||||
}
|
||||
} else {
|
||||
if (CurrentK.getEnd() > K.getEnd()) {
|
||||
Interval NewK(K.getEnd()+1, CurrentK.getEnd());
|
||||
return Add_internal(std::make_pair<key_type, data_type>(NewK,
|
||||
ImutInfo::DataOfValue(Value(T))), 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:
|
||||
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));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
@ -68,7 +68,7 @@ public:
|
||||
typedef typename ValInfo::data_type_ref data_type_ref;
|
||||
typedef ImutAVLTree<ValInfo> TreeTy;
|
||||
|
||||
private:
|
||||
protected:
|
||||
TreeTy* Root;
|
||||
|
||||
public:
|
||||
|
@ -27,6 +27,7 @@ namespace llvm {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
template <typename ImutInfo> class ImutAVLFactory;
|
||||
template <typename ImutInfo> class ImutIntervalAVLFactory;
|
||||
template <typename ImutInfo> class ImutAVLTreeInOrderIterator;
|
||||
template <typename ImutInfo> class ImutAVLTreeGenericIterator;
|
||||
|
||||
@ -39,6 +40,7 @@ public:
|
||||
|
||||
typedef ImutAVLFactory<ImutInfo> Factory;
|
||||
friend class ImutAVLFactory<ImutInfo>;
|
||||
friend class ImutIntervalAVLFactory<ImutInfo>;
|
||||
|
||||
friend class ImutAVLTreeGenericIterator<ImutInfo>;
|
||||
friend class FoldingSet<ImutAVLTree>;
|
||||
@ -389,7 +391,7 @@ public:
|
||||
// These have succinct names so that the balancing code
|
||||
// is as terse (and readable) as possible.
|
||||
//===--------------------------------------------------===//
|
||||
private:
|
||||
protected:
|
||||
|
||||
bool isEmpty(TreeTy* T) const { return !T; }
|
||||
unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; }
|
||||
|
Loading…
Reference in New Issue
Block a user