-11e249a59e8c627fe9c2938c38e39cb1efefb1fb
+57da43e8159bfe1a31e49683c371cf36e2fb6051
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
Gogo* gogo = context->gogo();
std::string var_name;
- if (no->package() == NULL)
- var_name = gogo->pkgpath_symbol();
+ bool is_descriptor = false;
+ if (no->is_function_declaration()
+ && !no->func_declaration_value()->asm_name().empty()
+ && Linemap::is_predeclared_location(no->location()))
+ {
+ var_name = no->func_declaration_value()->asm_name() + "_descriptor";
+ is_descriptor = true;
+ }
else
- var_name = no->package()->pkgpath_symbol();
- var_name.push_back('.');
- var_name.append(Gogo::unpack_hidden_name(no->name()));
- var_name.append("$descriptor");
+ {
+ if (no->package() == NULL)
+ var_name = gogo->pkgpath_symbol();
+ else
+ var_name = no->package()->pkgpath_symbol();
+ var_name.push_back('.');
+ var_name.append(Gogo::unpack_hidden_name(no->name()));
+ var_name.append("$descriptor");
+ }
Btype* btype = this->type()->get_backend(gogo);
Bvariable* bvar;
- if (no->package() != NULL
- || Linemap::is_predeclared_location(no->location()))
+ if (no->package() != NULL || is_descriptor)
bvar = context->backend()->immutable_struct_reference(var_name, btype,
loc);
else
Type* void_type = Type::make_void_type();
Type* unsafe_pointer_type = Type::make_pointer_type(void_type);
+ Typed_identifier_list *params = new Typed_identifier_list();
+ params->push_back(Typed_identifier("key", unsafe_pointer_type, bloc));
+ params->push_back(Typed_identifier("key_size", uintptr_type, bloc));
+
+ Typed_identifier_list* results = new Typed_identifier_list();
+ results->push_back(Typed_identifier("", uintptr_type, bloc));
+
+ Type* hash_fntype = Type::make_function_type(NULL, params, results,
+ bloc);
+
+ params = new Typed_identifier_list();
+ params->push_back(Typed_identifier("key1", unsafe_pointer_type, bloc));
+ params->push_back(Typed_identifier("key2", unsafe_pointer_type, bloc));
+ params->push_back(Typed_identifier("key_size", uintptr_type, bloc));
+
+ results = new Typed_identifier_list();
+ results->push_back(Typed_identifier("", Type::lookup_bool_type(), bloc));
+
+ Type* equal_fntype = Type::make_function_type(NULL, params, results,
+ bloc);
+
// Forward declaration for the type descriptor type.
Named_object* named_type_descriptor_type =
Named_object::make_type_declaration("commonType", NULL, bloc);
"fieldAlign", uint8_type,
"size", uintptr_type,
"hash", uint32_type,
- "hashfn", uintptr_type,
- "equalfn", uintptr_type,
+ "hashfn", hash_fntype,
+ "equalfn", equal_fntype,
"gc", uintptr_type,
"string", pointer_string_type,
"", pointer_uncommon_type,
gogo->add_block(b, bloc);
gogo->lower_block(equal_fn, b);
gogo->finish_function(bloc);
+
+ // Build the function descriptors for the type descriptor to refer to.
+ hash_fn->func_value()->descriptor(gogo, hash_fn);
+ equal_fn->func_value()->descriptor(gogo, equal_fn);
}
// Write a hash function that simply calls the hash function for a
Named_object* equal_fn;
this->type_functions(gogo, name, hash_fntype, equal_fntype, &hash_fn,
&equal_fn);
- vals->push_back(Expression::make_func_code_reference(hash_fn, bloc));
- vals->push_back(Expression::make_func_code_reference(equal_fn, bloc));
+ vals->push_back(Expression::make_func_reference(hash_fn, NULL, bloc));
+ vals->push_back(Expression::make_func_reference(equal_fn, NULL, bloc));
++p;
go_assert(p->is_field_name("gc"));
size uintptr
hash uint32 // hash of type; avoids computation in hash tables
- hashfn uintptr // hash function code
- equalfn uintptr // equality function code
+ hashfn func(unsafe.Pointer, uintptr) // hash function
+ equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) // equality function
gc unsafe.Pointer // garbage collection data
string *string // string form; unnecessary but undeniably useful
return 1;
if (__go_is_pointer_type (left_descriptor))
return left.__object == right.__object ? 0 : 1;
- if (!left_descriptor->__equalfn (left.__object, right.__object,
- left_descriptor->__size))
+ if (!__go_call_equalfn (left_descriptor->__equalfn, left.__object,
+ right.__object, left_descriptor->__size))
return 1;
return 0;
}
return 1;
if (__go_is_pointer_type (left_descriptor))
return left.__object == val ? 0 : 1;
- if (!left_descriptor->__equalfn (left.__object, val,
- left_descriptor->__size))
+ if (!__go_call_equalfn (left_descriptor->__equalfn, left.__object, val,
+ left_descriptor->__size))
return 1;
return 0;
}
return 1;
if (__go_is_pointer_type (left_descriptor))
return left.__object == right.__object ? 0 : 1;
- if (!left_descriptor->__equalfn (left.__object, right.__object,
- left_descriptor->__size))
+ if (!__go_call_equalfn (left_descriptor->__equalfn, left.__object,
+ right.__object, left_descriptor->__size))
return 1;
return 0;
}
return 1;
if (__go_is_pointer_type (left_descriptor))
return left.__object == right.__object ? 0 : 1;
- if (!left_descriptor->__equalfn (left.__object, right.__object,
- left_descriptor->__size))
+ if (!__go_call_equalfn (left_descriptor->__equalfn, left.__object,
+ right.__object, left_descriptor->__size))
return 1;
return 0;
}
return 1;
if (__go_is_pointer_type (left_descriptor))
return left.__object == val ? 0 : 1;
- if (!left_descriptor->__equalfn (left.__object, val,
- left_descriptor->__size))
+ if (!__go_call_equalfn (left_descriptor->__equalfn, left.__object, val,
+ left_descriptor->__size))
return 1;
return 0;
}
const struct __go_map_descriptor *descriptor;
const struct __go_type_descriptor *key_descriptor;
uintptr_t key_offset;
- _Bool (*equalfn) (const void*, const void*, uintptr_t);
+ const FuncVal *equalfn;
size_t key_hash;
size_t key_size;
size_t bucket_index;
__go_assert (key_size != -1UL);
equalfn = key_descriptor->__equalfn;
- key_hash = key_descriptor->__hashfn (key, key_size);
+ key_hash = __go_call_hashfn (key_descriptor->__hashfn, key, key_size);
bucket_index = key_hash % map->__bucket_count;
pentry = map->__buckets + bucket_index;
while (*pentry != NULL)
{
char *entry = (char *) *pentry;
- if (equalfn (key, entry + key_offset, key_size))
+ if (__go_call_equalfn (equalfn, key, entry + key_offset, key_size))
{
*pentry = *(void **) entry;
if (descriptor->__entry_size >= TinySize)
const struct __go_type_descriptor *key_descriptor;
uintptr_t key_offset;
size_t key_size;
- uintptr_t (*hashfn) (const void *, uintptr_t);
+ const FuncVal *hashfn;
uintptr_t old_bucket_count;
void **old_buckets;
uintptr_t new_bucket_count;
/* We could speed up rehashing at the cost of memory space
by caching the hash code. */
- key_hash = hashfn (entry + key_offset, key_size);
+ key_hash = __go_call_hashfn (hashfn, entry + key_offset, key_size);
new_bucket_index = key_hash % new_bucket_count;
next = *(char **) entry;
const struct __go_map_descriptor *descriptor;
const struct __go_type_descriptor *key_descriptor;
uintptr_t key_offset;
- _Bool (*equalfn) (const void*, const void*, uintptr_t);
+ const FuncVal *equalfn;
size_t key_hash;
size_t key_size;
size_t bucket_index;
__go_assert (key_size != -1UL);
equalfn = key_descriptor->__equalfn;
- key_hash = key_descriptor->__hashfn (key, key_size);
+ key_hash = __go_call_hashfn (key_descriptor->__hashfn, key, key_size);
bucket_index = key_hash % map->__bucket_count;
entry = (char *) map->__buckets[bucket_index];
while (entry != NULL)
{
- if (equalfn (key, entry + key_offset, key_size))
+ if (__go_call_equalfn (equalfn, key, entry + key_offset, key_size))
return entry + descriptor->__val_offset;
entry = *(char **) entry;
}
_Bool
ismapkey (const struct __go_type_descriptor *typ)
{
- return typ != NULL && typ->__hashfn != __go_type_hash_error;
+ return (typ != NULL
+ && (void *) typ->__hashfn->fn != (void *) __go_type_hash_error);
}
runtime_throw ("__go_type_hash_complex: invalid complex size");
}
+const FuncVal __go_type_hash_complex_descriptor =
+ { (void *) __go_type_hash_complex };
+
/* Equality function for complex types. */
_Bool
else
runtime_throw ("__go_type_equal_complex: invalid complex size");
}
+
+const FuncVal __go_type_equal_complex_descriptor =
+ { (void *) __go_type_equal_complex };
return 0;
size = descriptor->__size;
if (__go_is_pointer_type (descriptor))
- return descriptor->__hashfn (&val->__object, size);
+ return __go_call_hashfn (descriptor->__hashfn, &val->__object, size);
else
- return descriptor->__hashfn (val->__object, size);
+ return __go_call_hashfn (descriptor->__hashfn, val->__object, size);
}
+const FuncVal __go_type_hash_empty_interface_descriptor =
+ { (void *) __go_type_hash_empty_interface };
+
/* An equality function for an empty interface. */
_Bool
if (__go_is_pointer_type (v1_descriptor))
return v1->__object == v2->__object;
else
- return v1_descriptor->__equalfn (v1->__object, v2->__object,
- v1_descriptor->__size);
+ return __go_call_equalfn (v1_descriptor->__equalfn, v1->__object,
+ v2->__object, v1_descriptor->__size);
}
+
+const FuncVal __go_type_equal_empty_interface_descriptor =
+ { (void *) __go_type_equal_empty_interface };
runtime_panicstring ("hash of unhashable type");
}
+const FuncVal __go_type_hash_error_descriptor =
+ { (void *) __go_type_hash_error };
+
/* An equality function for an interface. */
_Bool
{
runtime_panicstring ("comparing uncomparable types");
}
+
+const FuncVal __go_type_equal_error_descriptor =
+ { (void *) __go_type_equal_error };
runtime_throw ("__go_type_hash_float: invalid float size");
}
+const FuncVal __go_type_hash_float_descriptor =
+ { (void *) __go_type_hash_float };
+
/* Equality function for float types. */
_Bool
else
runtime_throw ("__go_type_equal_float: invalid float size");
}
+
+const FuncVal __go_type_equal_float_descriptor =
+ { (void *) __go_type_equal_float };
return ret;
}
+const FuncVal __go_type_hash_identity_descriptor =
+ { (void *) __go_type_hash_identity };
+
/* An identity equality function for a type. This is used for types
where we can check for equality by checking that the values have
the same bits. */
{
return __builtin_memcmp (k1, k2, key_size) == 0;
}
+
+const FuncVal __go_type_equal_identity_descriptor =
+ { (void *) __go_type_equal_identity };
descriptor = (const struct __go_type_descriptor *) val->__methods[0];
size = descriptor->__size;
if (__go_is_pointer_type (descriptor))
- return descriptor->__hashfn (&val->__object, size);
+ return __go_call_hashfn (descriptor->__hashfn, &val->__object, size);
else
- return descriptor->__hashfn (val->__object, size);
+ return __go_call_hashfn (descriptor->__hashfn, val->__object, size);
}
+const FuncVal __go_type_hash_interface_descriptor =
+ { (void *) __go_type_hash_interface };
+
/* An equality function for an interface. */
_Bool
if (__go_is_pointer_type (v1_descriptor))
return v1->__object == v2->__object;
else
- return v1_descriptor->__equalfn (v1->__object, v2->__object,
- v1_descriptor->__size);
+ return __go_call_equalfn (v1_descriptor->__equalfn, v1->__object,
+ v2->__object, v1_descriptor->__size);
}
+
+const FuncVal __go_type_equal_interface_descriptor =
+ { (void *) __go_type_equal_interface };
return ret;
}
+const FuncVal __go_type_hash_string_descriptor =
+ { (void *) __go_type_hash_string };
+
/* A string equality function for a map. */
_Bool
k2 = (const String *) vk2;
return __go_ptr_strings_equal (k1, k2);
}
+
+const FuncVal __go_type_equal_string_descriptor =
+ { (void *) __go_type_equal_string };
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. */
- uintptr_t (*__hashfn) (const void *, uintptr_t);
+ const FuncVal *__hashfn;
/* 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 *, uintptr_t);
+ const FuncVal *__equalfn;
/* The garbage collection data. */
const uintptr *__gc;
|| (td->__code & GO_CODE_MASK) == GO_UNSAFE_POINTER);
}
+/* Call a type hash function, given the __hashfn value. */
+
+static inline uintptr_t
+__go_call_hashfn (const FuncVal *hashfn, const void *p, uintptr_t size)
+{
+ uintptr_t (*h) (const void *, uintptr_t) = (void *) hashfn->fn;
+ return __builtin_call_with_static_chain (h (p, size), hashfn);
+}
+
+/* Call a type equality function, given the __equalfn value. */
+
+static inline _Bool
+__go_call_equalfn (const FuncVal *equalfn, const void *p1, const void *p2,
+ uintptr_t size)
+{
+ _Bool (*e) (const void *, const void *, uintptr_t) = (void *) equalfn->fn;
+ return __builtin_call_with_static_chain (e (p1, p2, size), equalfn);
+}
+
extern _Bool
__go_type_descriptors_equal(const struct __go_type_descriptor*,
const struct __go_type_descriptor*);
extern uintptr_t __go_type_hash_identity (const void *, uintptr_t);
+extern const FuncVal __go_type_hash_identity_descriptor;
extern _Bool __go_type_equal_identity (const void *, const void *, uintptr_t);
+extern const FuncVal __go_type_equal_identity_descriptor;
extern uintptr_t __go_type_hash_string (const void *, uintptr_t);
+extern const FuncVal __go_type_hash_string_descriptor;
extern _Bool __go_type_equal_string (const void *, const void *, uintptr_t);
+extern const FuncVal __go_type_equal_string_descriptor;
extern uintptr_t __go_type_hash_float (const void *, uintptr_t);
+extern const FuncVal __go_type_hash_float_descriptor;
extern _Bool __go_type_equal_float (const void *, const void *, uintptr_t);
+extern const FuncVal __go_type_equal_float_descriptor;
extern uintptr_t __go_type_hash_complex (const void *, uintptr_t);
+extern const FuncVal __go_type_hash_complex_descriptor;
extern _Bool __go_type_equal_complex (const void *, const void *, uintptr_t);
+extern const FuncVal __go_type_equal_complex_descriptor;
extern uintptr_t __go_type_hash_interface (const void *, uintptr_t);
+extern const FuncVal __go_type_hash_interface_descriptor;
extern _Bool __go_type_equal_interface (const void *, const void *, uintptr_t);
+extern const FuncVal __go_type_equal_interface_descriptor;
extern uintptr_t __go_type_hash_error (const void *, uintptr_t);
+extern const FuncVal __go_type_hash_error_descriptor;
extern _Bool __go_type_equal_error (const void *, const void *, uintptr_t);
+extern const FuncVal __go_type_equal_error_descriptor;
#endif /* !defined(LIBGO_GO_TYPE_H) */
/* __hash */
78501163U,
/* __hashfn */
- __go_type_hash_identity,
+ &__go_type_hash_identity_descriptor,
/* __equalfn */
- __go_type_equal_identity,
+ &__go_type_equal_identity_descriptor,
/* __gc */
unsafe_Pointer_gc,
/* __reflection */
/* __hash */
1256018616U,
/* __hashfn */
- __go_type_hash_identity,
+ &__go_type_hash_identity_descriptor,
/* __equalfn */
- __go_type_equal_identity,
+ &__go_type_equal_identity_descriptor,
/* __gc */
unsafe_Pointer_gc,
/* __reflection */
/* __hash */
0, /* This value doesn't matter. */
/* __hashfn */
- __go_type_hash_error,
+ &__go_type_hash_error_descriptor,
/* __equalfn */
- __go_type_equal_error,
+ &__go_type_equal_error_descriptor,
/* __gc */
NULL, /* This value doesn't matter */
/* __reflection */