From edce58fbd94fd8f274b34729c182fc156a2bda37 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 11 Jun 2010 11:06:44 +0000 Subject: Define ContextualFoldingSet, which stores a context parameter to pass down to the Profile method. Currently this only works with the default FoldingSetTraits implementation. The point of this is to allow nodes to not store context values which are only used during profiling. A better solution would thread this value through the folding algorithms, but then those would need to be (1) templated and (2) non-opaque. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105819 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/FoldingSet.h | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index e8979bb..c03ee5e 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -196,6 +196,10 @@ protected: template struct FoldingSetTrait { static inline void Profile(const T& X, FoldingSetNodeID& ID) { X.Profile(ID);} static inline void Profile(T& X, FoldingSetNodeID& ID) { X.Profile(ID); } + template + static inline void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) { + X.Profile(ID, Context); + } }; //===--------------------------------------------------------------------===// @@ -322,6 +326,77 @@ public: }; //===----------------------------------------------------------------------===// +/// ContextualFoldingSet - This template class is a further refinement +/// of FoldingSet which provides a context argument when calling +/// Profile on its nodes. Currently, that argument is fixed at +/// initialization time. +/// +/// T must be a subclass of FoldingSetNode and implement a Profile +/// function with signature +/// void Profile(llvm::FoldingSetNodeID &, Ctx); +template +class ContextualFoldingSet : public FoldingSetImpl { + // Unfortunately, this can't derive from FoldingSet because the + // construction vtable for FoldingSet requires + // FoldingSet::GetNodeProfile to be instantiated, which in turn + // requires a single-argument T::Profile(). + +private: + Ctx Context; + + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a + /// way to convert nodes into a unique specifier. + virtual void GetNodeProfile(FoldingSetNodeID &ID, + FoldingSetImpl::Node *N) const { + T *TN = static_cast(N); + + // We must use explicit template arguments in case Ctx is a + // reference type. + FoldingSetTrait::template Profile(*TN, ID, Context); + } + +public: + explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6) + : FoldingSetImpl(Log2InitSize), Context(Context) + {} + + Ctx getContext() const { return Context; } + + + typedef FoldingSetIterator iterator; + iterator begin() { return iterator(Buckets); } + iterator end() { return iterator(Buckets+NumBuckets); } + + typedef FoldingSetIterator const_iterator; + const_iterator begin() const { return const_iterator(Buckets); } + const_iterator end() const { return const_iterator(Buckets+NumBuckets); } + + typedef FoldingSetBucketIterator bucket_iterator; + + bucket_iterator bucket_begin(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1))); + } + + bucket_iterator bucket_end(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); + } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' + /// and return it instead. + T *GetOrInsertNode(Node *N) { + return static_cast(FoldingSetImpl::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it + /// exists, return it. If not, return the insertion token that will + /// make insertion faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos)); + } +}; + +//===----------------------------------------------------------------------===// /// FoldingSetIteratorImpl - This is the common iterator support shared by all /// folding sets, which knows how to walk the folding set hash table. class FoldingSetIteratorImpl { -- cgit v1.1