//
// The LLVM Compiler Infrastructure
//
-// This file was developed by James M. Laskey and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/APFloat.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
+#include <cstring>
using namespace llvm;
//===----------------------------------------------------------------------===//
-// FoldingSetImpl::NodeID Implementation
+// FoldingSetNodeID Implementation
/// Add* - Add various data types to Bit data.
///
-void FoldingSetImpl::NodeID::AddPointer(const void *Ptr) {
+void FoldingSetNodeID::AddPointer(const void *Ptr) {
// Note: this adds pointers to the hash using sizes and endianness that
// depend on the host. It doesn't matter however, because hashing on
// pointer values in inherently unstable. Nothing should depend on the
if (sizeof(intptr_t) > sizeof(unsigned))
Bits.push_back(unsigned(uint64_t(PtrI) >> 32));
}
-void FoldingSetImpl::NodeID::AddInteger(signed I) {
+void FoldingSetNodeID::AddInteger(signed I) {
Bits.push_back(I);
}
-void FoldingSetImpl::NodeID::AddInteger(unsigned I) {
+void FoldingSetNodeID::AddInteger(unsigned I) {
Bits.push_back(I);
}
-void FoldingSetImpl::NodeID::AddInteger(int64_t I) {
+void FoldingSetNodeID::AddInteger(int64_t I) {
AddInteger((uint64_t)I);
}
-void FoldingSetImpl::NodeID::AddInteger(uint64_t I) {
+void FoldingSetNodeID::AddInteger(uint64_t I) {
Bits.push_back(unsigned(I));
// If the integer is small, encode it just as 32-bits.
if ((uint64_t)(int)I != I)
Bits.push_back(unsigned(I >> 32));
}
-void FoldingSetImpl::NodeID::AddFloat(float F) {
+void FoldingSetNodeID::AddFloat(float F) {
Bits.push_back(FloatToBits(F));
}
-void FoldingSetImpl::NodeID::AddDouble(double D) {
+void FoldingSetNodeID::AddDouble(double D) {
AddInteger(DoubleToBits(D));
}
-void FoldingSetImpl::NodeID::AddAPFloat(const APFloat& apf) {
- APInt api = apf.convertToAPInt();
- const uint64_t *p = api.getRawData();
- for (unsigned i=0; i<api.getNumWords(); i++)
- AddInteger(*p++);
+
+void FoldingSetNodeID::AddString(const char *String) {
+ unsigned Size = static_cast<unsigned>(strlen(String));
+ Bits.push_back(Size);
+ if (!Size) return;
+
+ unsigned Units = Size / 4;
+ unsigned Pos = 0;
+ const unsigned *Base = (const unsigned *)String;
+
+ // If the string is aligned do a bulk transfer.
+ if (!((intptr_t)Base & 3)) {
+ Bits.append(Base, Base + Units);
+ Pos = (Units + 1) * 4;
+ } else {
+ // Otherwise do it the hard way.
+ for ( Pos += 4; Pos <= Size; Pos += 4) {
+ unsigned V = ((unsigned char)String[Pos - 4] << 24) |
+ ((unsigned char)String[Pos - 3] << 16) |
+ ((unsigned char)String[Pos - 2] << 8) |
+ (unsigned char)String[Pos - 1];
+ Bits.push_back(V);
+ }
+ }
+
+ // With the leftover bits.
+ unsigned V = 0;
+ // Pos will have overshot size by 4 - #bytes left over.
+ switch (Pos - Size) {
+ case 1: V = (V << 8) | (unsigned char)String[Size - 3]; // Fall thru.
+ case 2: V = (V << 8) | (unsigned char)String[Size - 2]; // Fall thru.
+ case 3: V = (V << 8) | (unsigned char)String[Size - 1]; break;
+ default: return; // Nothing left.
+ }
+
+ Bits.push_back(V);
}
-void FoldingSetImpl::NodeID::AddString(const std::string &String) {
- unsigned Size = String.size();
+
+void FoldingSetNodeID::AddString(const std::string &String) {
+ unsigned Size = static_cast<unsigned>(String.size());
Bits.push_back(Size);
if (!Size) return;
Bits.push_back(V);
}
-/// ComputeHash - Compute a strong hash value for this NodeID, used to
+/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to
/// lookup the node in the FoldingSetImpl.
-unsigned FoldingSetImpl::NodeID::ComputeHash() const {
+unsigned FoldingSetNodeID::ComputeHash() const {
// This is adapted from SuperFastHash by Paul Hsieh.
- unsigned Hash = Bits.size();
+ unsigned Hash = static_cast<unsigned>(Bits.size());
for (const unsigned *BP = &Bits[0], *E = BP+Bits.size(); BP != E; ++BP) {
unsigned Data = *BP;
Hash += Data & 0xFFFF;
/// operator== - Used to compare two nodes to each other.
///
-bool FoldingSetImpl::NodeID::operator==(const FoldingSetImpl::NodeID &RHS)const{
+bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS)const{
if (Bits.size() != RHS.Bits.size()) return false;
return memcmp(&Bits[0], &RHS.Bits[0], Bits.size()*sizeof(Bits[0])) == 0;
}
return static_cast<FoldingSetImpl::Node*>(NextInBucketPtr);
}
-/// GetBucketPtr - Provides a casting of a bucket pointer for isNode
+
/// testing.
static void **GetBucketPtr(void *NextInBucketPtr) {
intptr_t Ptr = reinterpret_cast<intptr_t>(NextInBucketPtr);
/// GetBucketFor - Hash the specified node ID and return the hash bucket for
/// the specified ID.
-static void **GetBucketFor(const FoldingSetImpl::NodeID &ID,
+static void **GetBucketFor(const FoldingSetNodeID &ID,
void **Buckets, unsigned NumBuckets) {
// NumBuckets is always a power of 2.
unsigned BucketNum = ID.ComputeHash() & (NumBuckets-1);
memset(Buckets, 0, NumBuckets*sizeof(void*));
// Set the very last bucket to be a non-null "pointer".
- Buckets[NumBuckets] = reinterpret_cast<void*>(-2);
+ Buckets[NumBuckets] = reinterpret_cast<void*>(-1);
}
FoldingSetImpl::~FoldingSetImpl() {
delete [] Buckets;
NodeInBucket->SetNextInBucket(0);
// Insert the node into the new bucket, after recomputing the hash.
- NodeID ID;
+ FoldingSetNodeID ID;
GetNodeProfile(ID, NodeInBucket);
InsertNode(NodeInBucket, GetBucketFor(ID, Buckets, NumBuckets));
}
/// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
/// return it. If not, return the insertion token that will make insertion
/// faster.
-FoldingSetImpl::Node *FoldingSetImpl::FindNodeOrInsertPos(const NodeID &ID,
- void *&InsertPos) {
+FoldingSetImpl::Node
+*FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
+ void *&InsertPos) {
+
void **Bucket = GetBucketFor(ID, Buckets, NumBuckets);
void *Probe = *Bucket;
InsertPos = 0;
while (Node *NodeInBucket = GetNextPtr(Probe)) {
- NodeID OtherID;
+ FoldingSetNodeID OtherID;
GetNodeProfile(OtherID, NodeInBucket);
if (OtherID == ID)
return NodeInBucket;
// Do we need to grow the hashtable?
if (NumNodes+1 > NumBuckets*2) {
GrowHashTable();
- NodeID ID;
+ FoldingSetNodeID ID;
GetNodeProfile(ID, N);
InsertPos = GetBucketFor(ID, Buckets, NumBuckets);
}
/// equal to the specified node, return it. Otherwise, insert 'N' and it
/// instead.
FoldingSetImpl::Node *FoldingSetImpl::GetOrInsertNode(FoldingSetImpl::Node *N) {
- NodeID ID;
+ FoldingSetNodeID ID;
GetNodeProfile(ID, N);
void *IP;
if (Node *E = FindNodeOrInsertPos(ID, IP))
FoldingSetIteratorImpl::FoldingSetIteratorImpl(void **Bucket) {
// Skip to the first non-null non-self-cycle bucket.
- while (*Bucket == 0 || GetNextPtr(*Bucket) == 0)
+ while (*Bucket != reinterpret_cast<void*>(-1) &&
+ (*Bucket == 0 || GetNextPtr(*Bucket) == 0))
++Bucket;
NodePtr = static_cast<FoldingSetNode*>(*Bucket);
// Skip to the next non-null non-self-cycle bucket.
do {
++Bucket;
- } while (*Bucket == 0 || GetNextPtr(*Bucket) == 0);
+ } while (*Bucket != reinterpret_cast<void*>(-1) &&
+ (*Bucket == 0 || GetNextPtr(*Bucket) == 0));
NodePtr = static_cast<FoldingSetNode*>(*Bucket);
}
}
+//===----------------------------------------------------------------------===//
+// FoldingSetBucketIteratorImpl Implementation
+
+FoldingSetBucketIteratorImpl::FoldingSetBucketIteratorImpl(void **Bucket) {
+ Ptr = (*Bucket == 0 || GetNextPtr(*Bucket) == 0) ? (void*) Bucket : *Bucket;
+}