Support any comparable type for map keys

This commit is contained in:
gingerBill
2020-11-29 16:37:19 +00:00
parent b922398a96
commit 5ab7ec5b16
4 changed files with 214 additions and 28 deletions
+32 -10
View File
@@ -2849,26 +2849,48 @@ void init_map_internal_types(Type *type) {
}
void add_map_key_type_dependencies(CheckerContext *ctx, Type *key) {
key = core_type(key);
if (is_type_cstring(key)) {
add_package_dependency(ctx, "runtime", "default_hasher_cstring");
} else if (is_type_string(key)) {
add_package_dependency(ctx, "runtime", "default_hasher_string");
} else if (!is_type_polymorphic(key)) {
if (!is_type_simple_compare(key)) {
if (!is_type_comparable(key)) {
return;
}
if (is_type_struct(key)) {
if (key->kind == Type_Struct) {
add_package_dependency(ctx, "runtime", "default_hasher_n");
}
if (!is_type_simple_compare(key)) {
for_array(i, key->Struct.fields) {
Entity *field = key->Struct.fields[i];
add_map_key_type_dependencies(ctx, field->type);
}
}
} else if (key->kind == Type_EnumeratedArray) {
add_package_dependency(ctx, "runtime", "default_hasher_n");
if (!is_type_simple_compare(key->EnumeratedArray.elem)) {
add_map_key_type_dependencies(ctx, key->EnumeratedArray.elem);
}
} else if (key->kind == Type_Array) {
add_package_dependency(ctx, "runtime", "default_hasher_n");
if (!is_type_simple_compare(key->Array.elem)) {
add_map_key_type_dependencies(ctx, key->Array.elem);
}
} else {
if (!is_type_simple_compare(key)) {
GB_PANIC("HERE");
}
i64 sz = type_size_of(key);
switch (sz) {
case 1: add_package_dependency(ctx, "runtime", "default_hasher1"); break;
case 2: add_package_dependency(ctx, "runtime", "default_hasher2"); break;
case 4: add_package_dependency(ctx, "runtime", "default_hasher4"); break;
case 8: add_package_dependency(ctx, "runtime", "default_hasher8"); break;
case 16: add_package_dependency(ctx, "runtime", "default_hasher16"); break;
i64 sz = type_size_of(key);
switch (sz) {
case 1: add_package_dependency(ctx, "runtime", "default_hasher1"); break;
case 2: add_package_dependency(ctx, "runtime", "default_hasher2"); break;
case 4: add_package_dependency(ctx, "runtime", "default_hasher4"); break;
case 8: add_package_dependency(ctx, "runtime", "default_hasher8"); break;
case 16: add_package_dependency(ctx, "runtime", "default_hasher16"); break;
}
}
}
}
+87 -9
View File
@@ -4967,7 +4967,7 @@ irValue *ir_get_equal_proc_for_type(irModule *m, Type *type) {
irValue *ir_get_hasher_proc_for_type(irModule *m, Type *type) {
Type *original_type = type;
type = base_type(type);
type = core_type(type);
Type *pt = alloc_type_pointer(type);
GB_ASSERT(is_type_valid_for_keys(type));
@@ -5006,14 +5006,92 @@ irValue *ir_get_hasher_proc_for_type(irModule *m, Type *type) {
if (type->kind == Type_Struct) {
type_set_offsets(type);
GB_ASSERT(is_type_simple_compare(type));
i64 sz = type_size_of(type);
auto args = array_make<irValue *>(permanent_allocator(), 3);
args[0] = data;
args[1] = seed;
args[2] = ir_const_int(sz);
irValue *res = ir_emit_runtime_call(proc, "default_hasher_n", args);
ir_emit(proc, ir_instr_return(proc, res));
if (is_type_simple_compare(type)) {
i64 sz = type_size_of(type);
auto args = array_make<irValue *>(permanent_allocator(), 3);
args[0] = data;
args[1] = seed;
args[2] = ir_const_int(sz);
irValue *res = ir_emit_runtime_call(proc, "default_hasher_n", args);
ir_emit(proc, ir_instr_return(proc, res));
} else {
data = ir_emit_conv(proc, data, t_u8_ptr);
auto args = array_make<irValue *>(permanent_allocator(), 2);
for_array(i, type->Struct.fields) {
i64 offset = type->Struct.offsets[i];
Entity *field = type->Struct.fields[i];
irValue *field_hasher = ir_get_hasher_proc_for_type(m, field->type);
irValue *ptr = ir_emit_ptr_offset(proc, data, ir_const_uintptr(offset));
args[0] = ptr;
args[1] = seed;
seed = ir_emit_call(proc, field_hasher, args);
}
ir_emit(proc, ir_instr_return(proc, seed));
}
} else if (type->kind == Type_Array) {
if (is_type_simple_compare(type)) {
i64 sz = type_size_of(type);
auto args = array_make<irValue *>(permanent_allocator(), 3);
args[0] = data;
args[1] = seed;
args[2] = ir_const_int(sz);
irValue *res = ir_emit_runtime_call(proc, "default_hasher_n", args);
ir_emit(proc, ir_instr_return(proc, res));
} else {
irValue *pres = ir_add_local_generated(proc, t_uintptr, false);
ir_emit_store(proc, pres, seed);
auto args = array_make<irValue *>(permanent_allocator(), 2);
irValue *elem_hasher = ir_get_hasher_proc_for_type(m, type->Array.elem);
auto loop_data = ir_loop_start(proc, type->Array.count, t_i32);
data = ir_emit_conv(proc, data, pt);
irValue *ptr = ir_emit_array_ep(proc, data, loop_data.idx);
args[0] = ptr;
args[1] = ir_emit_load(proc, pres);
irValue *new_seed = ir_emit_call(proc, elem_hasher, args);
ir_emit_store(proc, pres, new_seed);
ir_loop_end(proc, loop_data);
irValue *res = ir_emit_load(proc, pres);
ir_emit(proc, ir_instr_return(proc, res));
}
} else if (type->kind == Type_EnumeratedArray) {
if (is_type_simple_compare(type)) {
i64 sz = type_size_of(type);
auto args = array_make<irValue *>(permanent_allocator(), 3);
args[0] = data;
args[1] = seed;
args[2] = ir_const_int(sz);
irValue *res = ir_emit_runtime_call(proc, "default_hasher_n", args);
ir_emit(proc, ir_instr_return(proc, res));
} else {
irValue *pres = ir_add_local_generated(proc, t_uintptr, false);
ir_emit_store(proc, pres, seed);
auto args = array_make<irValue *>(permanent_allocator(), 2);
irValue *elem_hasher = ir_get_hasher_proc_for_type(m, type->Array.elem);
auto loop_data = ir_loop_start(proc, type->Array.count, t_i32);
data = ir_emit_conv(proc, data, pt);
irValue *ptr = ir_emit_array_ep(proc, data, loop_data.idx);
args[0] = ptr;
args[1] = ir_emit_load(proc, pres);
irValue *new_seed = ir_emit_call(proc, elem_hasher, args);
ir_emit_store(proc, pres, new_seed);
ir_loop_end(proc, loop_data);
irValue *res = ir_emit_load(proc, pres);
ir_emit(proc, ir_instr_return(proc, res));
}
} else if (is_type_cstring(type)) {
auto args = array_make<irValue *>(permanent_allocator(), 2);
args[0] = data;
+89 -9
View File
@@ -9251,7 +9251,7 @@ lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) {
lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
Type *original_type = type;
type = base_type(type);
type = core_type(type);
GB_ASSERT(is_type_valid_for_keys(type));
Type *pt = alloc_type_pointer(type);
@@ -9284,14 +9284,94 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
if (type->kind == Type_Struct) {
type_set_offsets(type);
GB_ASSERT(is_type_simple_compare(type));
i64 sz = type_size_of(type);
auto args = array_make<lbValue>(permanent_allocator(), 3);
args[0] = data;
args[1] = seed;
args[2] = lb_const_int(m, t_int, sz);
lbValue res = lb_emit_runtime_call(p, "default_hasher_n", args);
LLVMBuildRet(p->builder, res.value);
if (is_type_simple_compare(type)) {
i64 sz = type_size_of(type);
auto args = array_make<lbValue>(permanent_allocator(), 3);
args[0] = data;
args[1] = seed;
args[2] = lb_const_int(m, t_int, sz);
lbValue res = lb_emit_runtime_call(p, "default_hasher_n", args);
LLVMBuildRet(p->builder, res.value);
} else {
data = lb_emit_conv(p, data, t_u8_ptr);
auto args = array_make<lbValue>(permanent_allocator(), 2);
for_array(i, type->Struct.fields) {
i64 offset = type->Struct.offsets[i];
Entity *field = type->Struct.fields[i];
lbValue field_hasher = lb_get_hasher_proc_for_type(m, field->type);
lbValue ptr = lb_emit_ptr_offset(p, data, lb_const_int(m, t_uintptr, offset));
args[0] = ptr;
args[1] = seed;
seed = lb_emit_call(p, field_hasher, args);
}
LLVMBuildRet(p->builder, seed.value);
}
} else if (type->kind == Type_Array) {
if (is_type_simple_compare(type)) {
i64 sz = type_size_of(type);
auto args = array_make<lbValue>(permanent_allocator(), 3);
args[0] = data;
args[1] = seed;
args[2] = lb_const_int(m, t_int, sz);
lbValue res = lb_emit_runtime_call(p, "default_hasher_n", args);
LLVMBuildRet(p->builder, res.value);
} else {
lbAddr pres = lb_add_local_generated(p, t_uintptr, false);
lb_addr_store(p, pres, seed);
auto args = array_make<lbValue>(permanent_allocator(), 2);
lbValue elem_hasher = lb_get_hasher_proc_for_type(m, type->Array.elem);
auto loop_data = lb_loop_start(p, type->Array.count, t_i32);
data = lb_emit_conv(p, data, pt);
lbValue ptr = lb_emit_array_ep(p, data, loop_data.idx);
args[0] = ptr;
args[1] = lb_addr_load(p, pres);
lbValue new_seed = lb_emit_call(p, elem_hasher, args);
lb_addr_store(p, pres, new_seed);
lb_loop_end(p, loop_data);
lbValue res = lb_addr_load(p, pres);
LLVMBuildRet(p->builder, res.value);
}
} else if (type->kind == Type_EnumeratedArray) {
if (is_type_simple_compare(type)) {
i64 sz = type_size_of(type);
auto args = array_make<lbValue>(permanent_allocator(), 3);
args[0] = data;
args[1] = seed;
args[2] = lb_const_int(m, t_int, sz);
lbValue res = lb_emit_runtime_call(p, "default_hasher_n", args);
LLVMBuildRet(p->builder, res.value);
} else {
lbAddr res = lb_add_local_generated(p, t_uintptr, false);
lb_addr_store(p, res, seed);
auto args = array_make<lbValue>(permanent_allocator(), 2);
lbValue elem_hasher = lb_get_hasher_proc_for_type(m, type->EnumeratedArray.elem);
auto loop_data = lb_loop_start(p, type->EnumeratedArray.count, t_i32);
data = lb_emit_conv(p, data, pt);
lbValue ptr = lb_emit_array_ep(p, data, loop_data.idx);
args[0] = ptr;
args[1] = lb_addr_load(p, res);
lbValue new_seed = lb_emit_call(p, elem_hasher, args);
lb_addr_store(p, res, new_seed);
lb_loop_end(p, loop_data);
lbValue vres = lb_addr_load(p, res);
LLVMBuildRet(p->builder, vres.value);
}
} else if (is_type_cstring(type)) {
auto args = array_make<lbValue>(permanent_allocator(), 2);
args[0] = data;
+6
View File
@@ -1542,6 +1542,8 @@ bool is_type_valid_for_keys(Type *t) {
if (is_type_untyped(t)) {
return false;
}
return is_type_comparable(t);
#if 0
if (is_type_integer(t)) {
return true;
}
@@ -1560,8 +1562,12 @@ bool is_type_valid_for_keys(Type *t) {
if (is_type_simple_compare(t)) {
return true;
}
if (is_type_comparable(t)) {
return true;
}
return false;
#endif
}
bool is_type_valid_bit_set_elem(Type *t) {