diff options
Diffstat (limited to 'gcc/inchash.h')
-rw-r--r-- | gcc/inchash.h | 65 |
1 files changed, 59 insertions, 6 deletions
diff --git a/gcc/inchash.h b/gcc/inchash.h index 54fb0d8..4bb1272 100644 --- a/gcc/inchash.h +++ b/gcc/inchash.h @@ -36,8 +36,8 @@ along with GCC; see the file COPYING3. If not see Currently it just implements the plain old jhash based incremental hash from gcc's tree.c. */ -extern hashval_t iterative_hash_host_wide_int (HOST_WIDE_INT, hashval_t); -extern hashval_t iterative_hash_hashval_t (hashval_t, hashval_t); +hashval_t iterative_hash_host_wide_int (HOST_WIDE_INT, hashval_t); +hashval_t iterative_hash_hashval_t (hashval_t, hashval_t); namespace inchash { @@ -72,7 +72,7 @@ class hash } /* Hash in pointer PTR. */ - void add_ptr (void *ptr) + void add_ptr (const void *ptr) { add (&ptr, sizeof (ptr)); } @@ -121,13 +121,13 @@ class hash { if (a.end() > b.end()) { - merge (b); + merge (b); merge (a); } else { - merge (a); - merge (b); + merge (a); + merge (b); } } @@ -138,4 +138,57 @@ class hash } +/* Borrowed from hashtab.c iterative_hash implementation. */ +#define mix(a,b,c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<< 8); \ + c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \ + a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \ + b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \ + c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \ + a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \ + b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \ + c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \ +} + + +/* Produce good hash value combining VAL and VAL2. */ +inline +hashval_t +iterative_hash_hashval_t (hashval_t val, hashval_t val2) +{ + /* the golden ratio; an arbitrary value. */ + hashval_t a = 0x9e3779b9; + + mix (a, val, val2); + return val2; +} + +/* Produce good hash value combining VAL and VAL2. */ + +inline +hashval_t +iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2) +{ + if (sizeof (HOST_WIDE_INT) == sizeof (hashval_t)) + return iterative_hash_hashval_t (val, val2); + else + { + hashval_t a = (hashval_t) val; + /* Avoid warnings about shifting of more than the width of the type on + hosts that won't execute this path. */ + int zero = 0; + hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero)); + mix (a, b, val2); + if (sizeof (HOST_WIDE_INT) > 2 * sizeof (hashval_t)) + { + hashval_t a = (hashval_t) (val >> (sizeof (hashval_t) * 16 + zero)); + hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 24 + zero)); + mix (a, b, val2); + } + return val2; + } +} + #endif |