Browse Source

Support map keys for simple compare types

gingerBill 4 years ago
parent
commit
57f5976ac1
5 changed files with 26 additions and 7 deletions
  1. 3 1
      core/runtime/dynamic_map_internal.odin
  2. 4 1
      src/check_type.cpp
  3. 8 2
      src/ir.cpp
  4. 8 2
      src/llvm_backend.cpp
  5. 3 1
      src/types.cpp

+ 3 - 1
core/runtime/dynamic_map_internal.odin

@@ -76,6 +76,7 @@ default_hash_ptr :: inline proc "contextless" (data: rawptr, size: int) -> uintp
 	return default_hash(transmute([]byte)(s));
 }
 
+@(private)
 _default_hasher_const :: inline proc "contextless" (data: rawptr, seed: uintptr, $N: uint) -> uintptr {
 	h := u64(seed) + 0xcbf29ce484222325;
 	p := uintptr(data);
@@ -86,7 +87,8 @@ _default_hasher_const :: inline proc "contextless" (data: rawptr, seed: uintptr,
 	}
 	return uintptr(h);
 }
-_default_hasher_n :: inline proc "contextless" (data: rawptr, seed: uintptr, N: int) -> uintptr {
+
+default_hasher_n :: inline proc "contextless" (data: rawptr, seed: uintptr, N: int) -> uintptr {
 	h := u64(seed) + 0xcbf29ce484222325;
 	p := uintptr(data);
 	for _ in 0..<N {

+ 4 - 1
src/check_type.cpp

@@ -2856,6 +2856,10 @@ void add_map_key_type_dependencies(CheckerContext *ctx, Type *key) {
 	} else if (!is_type_polymorphic(key)) {
 		GB_ASSERT_MSG(is_type_simple_compare(key), "%s", type_to_string(key));
 
+		if (is_type_struct(key)) {
+			add_package_dependency(ctx, "runtime", "default_hasher_n");
+		}
+
 		i64 sz = type_size_of(key);
 		switch (sz) {
 		case  1: add_package_dependency(ctx, "runtime", "default_hasher1");  break;
@@ -2863,7 +2867,6 @@ void add_map_key_type_dependencies(CheckerContext *ctx, Type *key) {
 		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;
-		default: GB_PANIC("unhandled hasher for key type: %s", type_to_string(key));
 		}
 	}
 }

+ 8 - 2
src/ir.cpp

@@ -5006,8 +5006,14 @@ irValue *ir_get_hasher_proc_for_type(irModule *m, Type *type) {
 
 	if (type->kind == Type_Struct) {
 		type_set_offsets(type);
-
-		GB_PANIC("Type_Struct");
+		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));
 	} else if (is_type_cstring(type)) {
 		auto args = array_make<irValue *>(permanent_allocator(), 2);
 		args[0] = data;

+ 8 - 2
src/llvm_backend.cpp

@@ -9284,8 +9284,14 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
 
 	if (type->kind == Type_Struct)  {
 		type_set_offsets(type);
-
-		GB_PANIC("Type_Struct");
+		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);
 	} else if (is_type_cstring(type)) {
 		auto args = array_make<lbValue>(permanent_allocator(), 2);
 		args[0] = data;

+ 3 - 1
src/types.cpp

@@ -964,7 +964,6 @@ bool is_type_valid_for_keys(Type *t);
 
 Type *alloc_type_map(i64 count, Type *key, Type *value) {
 	if (key != nullptr) {
-		GB_ASSERT(is_type_valid_for_keys(key));
 		GB_ASSERT(value != nullptr);
 	}
 	Type *t = alloc_type(Type_Map);
@@ -1558,6 +1557,9 @@ bool is_type_valid_for_keys(Type *t) {
 	if (is_type_typeid(t)) {
 		return true;
 	}
+	if (is_type_simple_compare(t)) {
+		return true;
+	}
 
 	return false;
 }