diff options
Diffstat (limited to 'libgo/runtime')
-rw-r--r-- | libgo/runtime/go-type-complex.c | 122 | ||||
-rw-r--r-- | libgo/runtime/go-type-eface.c | 8 | ||||
-rw-r--r-- | libgo/runtime/go-type-error.c | 6 | ||||
-rw-r--r-- | libgo/runtime/go-type-float.c | 96 | ||||
-rw-r--r-- | libgo/runtime/go-type-identity.c | 44 | ||||
-rw-r--r-- | libgo/runtime/go-type-interface.c | 8 | ||||
-rw-r--r-- | libgo/runtime/go-type-string.c | 12 | ||||
-rw-r--r-- | libgo/runtime/go-type.h | 24 |
8 files changed, 272 insertions, 48 deletions
diff --git a/libgo/runtime/go-type-complex.c b/libgo/runtime/go-type-complex.c new file mode 100644 index 00000000000..f923c867d99 --- /dev/null +++ b/libgo/runtime/go-type-complex.c @@ -0,0 +1,122 @@ +/* go-type-complex.c -- hash and equality complex functions. + + Copyright 2012 The Go Authors. All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. */ + +#include "runtime.h" +#include "go-type.h" + +/* The 64-bit type. */ + +typedef unsigned int DItype __attribute__ ((mode (DI))); + +/* Hash function for float types. */ + +uintptr_t +__go_type_hash_complex (const void *vkey, uintptr_t key_size) +{ + if (key_size == 8) + { + union + { + unsigned char a[8]; + __complex float cf; + DItype di; + } ucf; + __complex float cf; + float cfr; + float cfi; + + __builtin_memcpy (ucf.a, vkey, 8); + cf = ucf.cf; + cfr = __builtin_crealf (cf); + cfi = __builtin_cimagf (cf); + if (__builtin_isinff (cfr) || __builtin_isinff (cfi) + || __builtin_isnanf (cfr) || __builtin_isnanf (cfi)) + return 0; + + /* Avoid negative zero. */ + if (cfr == 0 && cfi == 0) + return 0; + else if (cfr == 0) + ucf.cf = cfi * 1.0iF; + else if (cfi == 0) + ucf.cf = cfr; + + return ucf.di; + } + else if (key_size == 16) + { + union + { + unsigned char a[16]; + __complex double cd; + DItype adi[2]; + } ucd; + __complex double cd; + double cdr; + double cdi; + + __builtin_memcpy (ucd.a, vkey, 16); + cd = ucd.cd; + cdr = __builtin_crealf (cd); + cdi = __builtin_cimagf (cd); + if (__builtin_isinf (cdr) || __builtin_isinf (cdi) + || __builtin_isnan (cdr) || __builtin_isnan (cdi)) + return 0; + + /* Avoid negative zero. */ + if (cdr == 0 && cdi == 0) + return 0; + else if (cdr == 0) + ucd.cd = cdi * 1.0i; + else if (cdi == 0) + ucd.cd = cdr; + + return ucd.adi[0] ^ ucd.adi[1]; + } + else + runtime_throw ("__go_type_hash_complex: invalid complex size"); +} + +/* Equality function for complex types. */ + +_Bool +__go_type_equal_complex (const void *vk1, const void *vk2, uintptr_t key_size) +{ + if (key_size == 8) + { + union + { + unsigned char a[8]; + __complex float cf; + } ucf; + __complex float cf1; + __complex float cf2; + + __builtin_memcpy (ucf.a, vk1, 8); + cf1 = ucf.cf; + __builtin_memcpy (ucf.a, vk2, 8); + cf2 = ucf.cf; + return cf1 == cf2; + } + else if (key_size == 16) + { + union + { + unsigned char a[16]; + __complex double cd; + } ucd; + __complex double cd1; + __complex double cd2; + + __builtin_memcpy (ucd.a, vk1, 16); + cd1 = ucd.cd; + __builtin_memcpy (ucd.a, vk2, 16); + cd2 = ucd.cd; + return cd1 == cd2; + } + else + runtime_throw ("__go_type_equal_complex: invalid complex size"); +} diff --git a/libgo/runtime/go-type-eface.c b/libgo/runtime/go-type-eface.c index 5bf932fc8ba..cb3424b98d3 100644 --- a/libgo/runtime/go-type-eface.c +++ b/libgo/runtime/go-type-eface.c @@ -10,13 +10,13 @@ /* A hash function for an empty interface. */ -size_t +uintptr_t __go_type_hash_empty_interface (const void *vval, - size_t key_size __attribute__ ((unused))) + uintptr_t key_size __attribute__ ((unused))) { const struct __go_empty_interface *val; const struct __go_type_descriptor *descriptor; - size_t size; + uintptr_t size; val = (const struct __go_empty_interface *) vval; descriptor = val->__type_descriptor; @@ -33,7 +33,7 @@ __go_type_hash_empty_interface (const void *vval, _Bool __go_type_equal_empty_interface (const void *vv1, const void *vv2, - size_t key_size __attribute__ ((unused))) + uintptr_t key_size __attribute__ ((unused))) { const struct __go_empty_interface *v1; const struct __go_empty_interface *v2; diff --git a/libgo/runtime/go-type-error.c b/libgo/runtime/go-type-error.c index ba3146e3dda..b4c609b93ec 100644 --- a/libgo/runtime/go-type-error.c +++ b/libgo/runtime/go-type-error.c @@ -10,9 +10,9 @@ /* A hash function used for a type which does not support hash functions. */ -size_t +uintptr_t __go_type_hash_error (const void *val __attribute__ ((unused)), - size_t key_size __attribute__ ((unused))) + uintptr_t key_size __attribute__ ((unused))) { runtime_panicstring ("hash of unhashable type"); } @@ -22,7 +22,7 @@ __go_type_hash_error (const void *val __attribute__ ((unused)), _Bool __go_type_equal_error (const void *v1 __attribute__ ((unused)), const void *v2 __attribute__ ((unused)), - size_t key_size __attribute__ ((unused))) + uintptr_t key_size __attribute__ ((unused))) { runtime_panicstring ("comparing uncomparable types"); } diff --git a/libgo/runtime/go-type-float.c b/libgo/runtime/go-type-float.c new file mode 100644 index 00000000000..cc6e247e531 --- /dev/null +++ b/libgo/runtime/go-type-float.c @@ -0,0 +1,96 @@ +/* go-type-float.c -- hash and equality float functions. + + Copyright 2012 The Go Authors. All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. */ + +#include "runtime.h" +#include "go-type.h" + +/* The 32-bit and 64-bit types. */ + +typedef unsigned int SItype __attribute__ ((mode (SI))); +typedef unsigned int DItype __attribute__ ((mode (DI))); + +/* Hash function for float types. */ + +uintptr_t +__go_type_hash_float (const void *vkey, uintptr_t key_size) +{ + if (key_size == 4) + { + union + { + unsigned char a[4]; + float f; + SItype si; + } uf; + float f; + + __builtin_memcpy (uf.a, vkey, 4); + f = uf.f; + if (__builtin_isinff (f) || __builtin_isnanf (f) || f == 0) + return 0; + return (uintptr_t) uf.si; + } + else if (key_size == 8) + { + union + { + unsigned char a[8]; + double d; + DItype di; + } ud; + double d; + + __builtin_memcpy (ud.a, vkey, 8); + d = ud.d; + if (__builtin_isinf (d) || __builtin_isnan (d) || d == 0) + return 0; + return (uintptr_t) ud.di; + } + else + runtime_throw ("__go_type_hash_float: invalid float size"); +} + +/* Equality function for float types. */ + +_Bool +__go_type_equal_float (const void *vk1, const void *vk2, uintptr_t key_size) +{ + if (key_size == 4) + { + union + { + unsigned char a[4]; + float f; + } uf; + float f1; + float f2; + + __builtin_memcpy (uf.a, vk1, 4); + f1 = uf.f; + __builtin_memcpy (uf.a, vk2, 4); + f2 = uf.f; + return f1 == f2; + } + else if (key_size == 8) + { + union + { + unsigned char a[8]; + double d; + DItype di; + } ud; + double d1; + double d2; + + __builtin_memcpy (ud.a, vk1, 8); + d1 = ud.d; + __builtin_memcpy (ud.a, vk2, 8); + d2 = ud.d; + return d1 == d2; + } + else + runtime_throw ("__go_type_equal_float: invalid float size"); +} diff --git a/libgo/runtime/go-type-identity.c b/libgo/runtime/go-type-identity.c index f1de3c28ad8..a0168e24836 100644 --- a/libgo/runtime/go-type-identity.c +++ b/libgo/runtime/go-type-identity.c @@ -8,35 +8,37 @@ #include "go-type.h" -/* Typedefs for accesses of different sizes. */ +/* The 64-bit type. */ -typedef int QItype __attribute__ ((mode (QI))); -typedef int HItype __attribute__ ((mode (HI))); -typedef int SItype __attribute__ ((mode (SI))); -typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int DItype __attribute__ ((mode (DI))); /* An identity hash function for a type. This is used for types where we can simply use the type value itself as a hash code. This is true of, e.g., integers and pointers. */ -size_t -__go_type_hash_identity (const void *key, size_t key_size) +uintptr_t +__go_type_hash_identity (const void *key, uintptr_t key_size) { - switch (key_size) + uintptr_t ret; + uintptr_t i; + const unsigned char *p; + + if (key_size <= 8) { - case 1: - return *(const QItype *) key; - case 2: - return *(const HItype *) key; - case 3: - case 4: - case 5: - case 6: - case 7: - return *(const SItype *) key; - default: - return *(const DItype *) key; + union + { + DItype v; + unsigned char a[8]; + } u; + u.v = 0; + __builtin_memcpy (&u.a, key, key_size); + return (uintptr_t) u.v; } + + ret = 5381; + for (i = 0, p = (const unsigned char *) key; i < key_size; i++, p++) + ret = ret * 33 + *p; + return ret; } /* An identity equality function for a type. This is used for types @@ -44,7 +46,7 @@ __go_type_hash_identity (const void *key, size_t key_size) the same bits. */ _Bool -__go_type_equal_identity (const void *k1, const void *k2, size_t key_size) +__go_type_equal_identity (const void *k1, const void *k2, uintptr_t key_size) { return __builtin_memcmp (k1, k2, key_size) == 0; } diff --git a/libgo/runtime/go-type-interface.c b/libgo/runtime/go-type-interface.c index 9750b843c49..bc3b37c4ba2 100644 --- a/libgo/runtime/go-type-interface.c +++ b/libgo/runtime/go-type-interface.c @@ -9,13 +9,13 @@ /* A hash function for an interface. */ -size_t +uintptr_t __go_type_hash_interface (const void *vval, - size_t key_size __attribute__ ((unused))) + uintptr_t key_size __attribute__ ((unused))) { const struct __go_interface *val; const struct __go_type_descriptor *descriptor; - size_t size; + uintptr_t size; val = (const struct __go_interface *) vval; if (val->__methods == NULL) @@ -32,7 +32,7 @@ __go_type_hash_interface (const void *vval, _Bool __go_type_equal_interface (const void *vv1, const void *vv2, - size_t key_size __attribute__ ((unused))) + uintptr_t key_size __attribute__ ((unused))) { const struct __go_interface *v1; const struct __go_interface *v2; diff --git a/libgo/runtime/go-type-string.c b/libgo/runtime/go-type-string.c index 998955d6255..719ecb0e7ea 100644 --- a/libgo/runtime/go-type-string.c +++ b/libgo/runtime/go-type-string.c @@ -11,14 +11,14 @@ /* A string hash function for a map. */ -size_t +uintptr_t __go_type_hash_string (const void *vkey, - size_t key_size __attribute__ ((unused))) + uintptr_t key_size __attribute__ ((unused))) { - size_t ret; + uintptr_t ret; const struct __go_string *key; - size_t len; - size_t i; + int len; + int i; const unsigned char *p; ret = 5381; @@ -33,7 +33,7 @@ __go_type_hash_string (const void *vkey, _Bool __go_type_equal_string (const void *vk1, const void *vk2, - size_t key_size __attribute__ ((unused))) + uintptr_t key_size __attribute__ ((unused))) { const struct __go_string *k1; const struct __go_string *k2; diff --git a/libgo/runtime/go-type.h b/libgo/runtime/go-type.h index 6e2193982d6..25f096c4851 100644 --- a/libgo/runtime/go-type.h +++ b/libgo/runtime/go-type.h @@ -86,11 +86,11 @@ struct __go_type_descriptor size of this type, and returns a hash code. We pass the size explicitly becaues it means that we can share a single instance of this function for various different types. */ - size_t (*__hashfn) (const void *, size_t); + uintptr_t (*__hashfn) (const void *, uintptr_t); /* This function takes two pointers to values of this type, and the size of this type, and returns whether the values are equal. */ - _Bool (*__equalfn) (const void *, const void *, size_t); + _Bool (*__equalfn) (const void *, const void *, uintptr_t); /* A string describing this type. This is only used for debugging. */ @@ -317,13 +317,17 @@ extern _Bool __go_type_descriptors_equal(const struct __go_type_descriptor*, const struct __go_type_descriptor*); -extern size_t __go_type_hash_identity (const void *, size_t); -extern _Bool __go_type_equal_identity (const void *, const void *, size_t); -extern size_t __go_type_hash_string (const void *, size_t); -extern _Bool __go_type_equal_string (const void *, const void *, size_t); -extern size_t __go_type_hash_interface (const void *, size_t); -extern _Bool __go_type_equal_interface (const void *, const void *, size_t); -extern size_t __go_type_hash_error (const void *, size_t); -extern _Bool __go_type_equal_error (const void *, const void *, size_t); +extern uintptr_t __go_type_hash_identity (const void *, uintptr_t); +extern _Bool __go_type_equal_identity (const void *, const void *, uintptr_t); +extern uintptr_t __go_type_hash_string (const void *, uintptr_t); +extern _Bool __go_type_equal_string (const void *, const void *, uintptr_t); +extern uintptr_t __go_type_hash_float (const void *, uintptr_t); +extern _Bool __go_type_equal_float (const void *, const void *, uintptr_t); +extern uintptr_t __go_type_hash_complex (const void *, uintptr_t); +extern _Bool __go_type_equal_complex (const void *, const void *, uintptr_t); +extern uintptr_t __go_type_hash_interface (const void *, uintptr_t); +extern _Bool __go_type_equal_interface (const void *, const void *, uintptr_t); +extern uintptr_t __go_type_hash_error (const void *, uintptr_t); +extern _Bool __go_type_equal_error (const void *, const void *, uintptr_t); #endif /* !defined(LIBGO_GO_TYPE_H) */ |