Merge pull request #2181 from odin-lang/map-dev

New `map` internals
This commit is contained in:
gingerBill
2022-11-17 15:29:28 +00:00
committed by GitHub
35 changed files with 2147 additions and 896 deletions
+2
View File
@@ -307,6 +307,8 @@ struct BuildContext {
bool disallow_rtti;
bool use_static_map_calls;
RelocMode reloc_mode;
bool disable_red_zone;
+37
View File
@@ -5370,6 +5370,43 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
break;
}
case BuiltinProc_type_map_info:
{
Operand op = {};
Type *bt = check_type(c, ce->args[0]);
Type *type = base_type(bt);
if (type == nullptr || type == t_invalid) {
error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name));
return false;
}
if (!is_type_map(type)) {
gbString t = type_to_string(type);
error(ce->args[0], "Expected a map type for '%.*s', got %s", LIT(builtin_name), t);
gb_string_free(t);
return false;
}
add_map_key_type_dependencies(c, type);
operand->mode = Addressing_Value;
operand->type = t_map_info_ptr;
break;
}
case BuiltinProc_type_map_cell_info:
{
Operand op = {};
Type *bt = check_type(c, ce->args[0]);
Type *type = base_type(bt);
if (type == nullptr || type == t_invalid) {
error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name));
return false;
}
operand->mode = Addressing_Value;
operand->type = t_map_cell_info_ptr;
break;
}
case BuiltinProc_constant_utf16_cstring:
{
String value = {};
+36 -7
View File
@@ -285,6 +285,37 @@ void error_operand_no_value(Operand *o) {
}
}
void add_map_get_dependencies(CheckerContext *c) {
if (build_context.use_static_map_calls) {
add_package_dependency(c, "runtime", "map_desired_position");
add_package_dependency(c, "runtime", "map_probe_distance");
} else {
add_package_dependency(c, "runtime", "__dynamic_map_get");
}
}
void add_map_set_dependencies(CheckerContext *c) {
init_core_source_code_location(c->checker);
if (t_map_set_proc == nullptr) {
Type *map_set_args[5] = {/*map*/t_rawptr, /*hash*/t_uintptr, /*key*/t_rawptr, /*value*/t_rawptr, /*#caller_location*/t_source_code_location};
t_map_set_proc = alloc_type_proc_from_types(map_set_args, gb_count_of(map_set_args), t_rawptr, false, ProcCC_Odin);
}
if (build_context.use_static_map_calls) {
add_package_dependency(c, "runtime", "__dynamic_map_check_grow");
add_package_dependency(c, "runtime", "map_insert_hash_dynamic");
} else {
add_package_dependency(c, "runtime", "__dynamic_map_set");
}
}
void add_map_reserve_dependencies(CheckerContext *c) {
init_core_source_code_location(c->checker);
add_package_dependency(c, "runtime", "__dynamic_map_reserve");
}
void check_scope_decls(CheckerContext *c, Slice<Ast *> const &nodes, isize reserve_size) {
Scope *s = c->scope;
@@ -1364,8 +1395,6 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
bool key = is_polymorphic_type_assignable(c, poly->Map.key, source->Map.key, true, modify_type);
bool value = is_polymorphic_type_assignable(c, poly->Map.value, source->Map.value, true, modify_type);
if (key || value) {
poly->Map.entry_type = nullptr;
poly->Map.internal_type = nullptr;
poly->Map.lookup_result_type = nullptr;
init_map_internal_types(poly);
return true;
@@ -3246,7 +3275,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
check_assignment(c, x, yt->Map.key, str_lit("map 'not_in'"));
}
add_package_dependency(c, "runtime", "__dynamic_map_get");
add_map_get_dependencies(c);
} else if (is_type_bit_set(rhs_type)) {
Type *yt = base_type(rhs_type);
@@ -8557,8 +8586,8 @@ ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *
if (build_context.no_dynamic_literals && cl->elems.count) {
error(node, "Compound literals of dynamic types have been disabled");
} else {
add_package_dependency(c, "runtime", "__dynamic_map_reserve");
add_package_dependency(c, "runtime", "__dynamic_map_set");
add_map_reserve_dependencies(c);
add_map_set_dependencies(c);
}
break;
}
@@ -8994,8 +9023,8 @@ ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_h
o->type = t->Map.value;
o->expr = node;
add_package_dependency(c, "runtime", "__dynamic_map_get");
add_package_dependency(c, "runtime", "__dynamic_map_set");
add_map_get_dependencies(c);
add_map_set_dependencies(c);
return Expr_Expr;
}
+23 -65
View File
@@ -2176,70 +2176,36 @@ Type *make_optional_ok_type(Type *value, bool typed) {
return t;
}
void init_map_entry_type(Type *type) {
GB_ASSERT(type->kind == Type_Map);
if (type->Map.entry_type != nullptr) return;
// NOTE(bill): The preload types may have not been set yet
GB_ASSERT(t_map_hash != nullptr);
// IMPORTANT NOTE(bill): This must match the definition in dynamic_map_internal.odin
enum : i64 {
MAP_CACHE_LINE_LOG2 = 6,
MAP_CACHE_LINE_SIZE = 1 << MAP_CACHE_LINE_LOG2
};
GB_STATIC_ASSERT(MAP_CACHE_LINE_SIZE >= 64);
void map_cell_size_and_len(Type *type, i64 *size_, i64 *len_) {
i64 elem_sz = type_size_of(type);
/*
struct {
hash: uintptr,
next: int,
key: Key,
value: Value,
i64 len = 1;
if (0 < elem_sz && elem_sz < MAP_CACHE_LINE_SIZE) {
len = MAP_CACHE_LINE_SIZE / elem_sz;
}
*/
Scope *s = create_scope(nullptr, builtin_pkg->scope);
auto fields = slice_make<Entity *>(permanent_allocator(), 4);
fields[0] = alloc_entity_field(s, make_token_ident(str_lit("hash")), t_uintptr, false, 0, EntityState_Resolved);
fields[1] = alloc_entity_field(s, make_token_ident(str_lit("next")), t_int, false, 1, EntityState_Resolved);
fields[2] = alloc_entity_field(s, make_token_ident(str_lit("key")), type->Map.key, false, 2, EntityState_Resolved);
fields[3] = alloc_entity_field(s, make_token_ident(str_lit("value")), type->Map.value, false, 3, EntityState_Resolved);
Type *entry_type = alloc_type_struct();
entry_type->Struct.fields = fields;
entry_type->Struct.tags = gb_alloc_array(permanent_allocator(), String, fields.count);
type_set_offsets(entry_type);
type->Map.entry_type = entry_type;
i64 size = align_formula(elem_sz * len, MAP_CACHE_LINE_SIZE);
if (size_) *size_ = size;
if (len_) *len_ = len;
}
void init_map_internal_types(Type *type) {
GB_ASSERT(type->kind == Type_Map);
init_map_entry_type(type);
if (type->Map.internal_type != nullptr) return;
GB_ASSERT(t_allocator != nullptr);
if (type->Map.lookup_result_type != nullptr) return;
Type *key = type->Map.key;
Type *value = type->Map.value;
GB_ASSERT(key != nullptr);
GB_ASSERT(value != nullptr);
Type *generated_struct_type = alloc_type_struct();
/*
struct {
hashes: []int;
entries: [dynamic]EntryType;
}
*/
Scope *s = create_scope(nullptr, builtin_pkg->scope);
Type *hashes_type = alloc_type_slice(t_int);
Type *entries_type = alloc_type_dynamic_array(type->Map.entry_type);
auto fields = slice_make<Entity *>(permanent_allocator(), 2);
fields[0] = alloc_entity_field(s, make_token_ident(str_lit("hashes")), hashes_type, false, 0, EntityState_Resolved);
fields[1] = alloc_entity_field(s, make_token_ident(str_lit("entries")), entries_type, false, 1, EntityState_Resolved);
generated_struct_type->Struct.fields = fields;
type_set_offsets(generated_struct_type);
type->Map.internal_type = generated_struct_type;
type->Map.lookup_result_type = make_optional_ok_type(value);
type->Map.lookup_result_type = make_optional_ok_type(value);
}
void add_map_key_type_dependencies(CheckerContext *ctx, Type *key) {
@@ -2255,35 +2221,27 @@ void add_map_key_type_dependencies(CheckerContext *ctx, Type *key) {
}
if (is_type_simple_compare(key)) {
i64 sz = type_size_of(key);
if (1 <= sz && sz <= 16) {
char buf[20] = {};
gb_snprintf(buf, 20, "default_hasher%d", cast(i32)sz);
add_package_dependency(ctx, "runtime", buf);
return;
} else {
add_package_dependency(ctx, "runtime", "default_hasher_n");
return;
}
add_package_dependency(ctx, "runtime", "default_hasher");
return;
}
if (key->kind == Type_Struct) {
add_package_dependency(ctx, "runtime", "default_hasher_n");
add_package_dependency(ctx, "runtime", "default_hasher");
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_Union) {
add_package_dependency(ctx, "runtime", "default_hasher_n");
add_package_dependency(ctx, "runtime", "default_hasher");
for_array(i, key->Union.variants) {
Type *v = key->Union.variants[i];
add_map_key_type_dependencies(ctx, v);
}
} else if (key->kind == Type_EnumeratedArray) {
add_package_dependency(ctx, "runtime", "default_hasher_n");
add_package_dependency(ctx, "runtime", "default_hasher");
add_map_key_type_dependencies(ctx, key->EnumeratedArray.elem);
} else if (key->kind == Type_Array) {
add_package_dependency(ctx, "runtime", "default_hasher_n");
add_package_dependency(ctx, "runtime", "default_hasher");
add_map_key_type_dependencies(ctx, key->Array.elem);
}
}
+19 -9
View File
@@ -922,10 +922,13 @@ void init_universal(void) {
{
Type *equal_args[2] = {t_rawptr, t_rawptr};
t_equal_proc = alloc_type_proc_from_types(equal_args, 2, t_bool, false, ProcCC_Contextless);
t_equal_proc = alloc_type_proc_from_types(equal_args, gb_count_of(equal_args), t_bool, false, ProcCC_Contextless);
Type *hasher_args[2] = {t_rawptr, t_uintptr};
t_hasher_proc = alloc_type_proc_from_types(hasher_args, 2, t_uintptr, false, ProcCC_Contextless);
t_hasher_proc = alloc_type_proc_from_types(hasher_args, gb_count_of(hasher_args), t_uintptr, false, ProcCC_Contextless);
Type *map_get_args[3] = {/*map*/t_rawptr, /*hash*/t_uintptr, /*key*/t_rawptr};
t_map_get_proc = alloc_type_proc_from_types(map_get_args, gb_count_of(map_get_args), t_rawptr, false, ProcCC_Contextless);
}
// Constants
@@ -1933,7 +1936,8 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) {
init_map_internal_types(bt);
add_type_info_type_internal(c, bt->Map.key);
add_type_info_type_internal(c, bt->Map.value);
add_type_info_type_internal(c, bt->Map.internal_type);
add_type_info_type_internal(c, t_uintptr); // hash value
add_type_info_type_internal(c, t_allocator);
break;
case Type_Tuple:
@@ -2155,7 +2159,8 @@ void add_min_dep_type_info(Checker *c, Type *t) {
init_map_internal_types(bt);
add_min_dep_type_info(c, bt->Map.key);
add_min_dep_type_info(c, bt->Map.value);
add_min_dep_type_info(c, bt->Map.internal_type);
add_min_dep_type_info(c, t_uintptr); // hash value
add_min_dep_type_info(c, t_allocator);
break;
case Type_Tuple:
@@ -2838,16 +2843,21 @@ void init_core_source_code_location(Checker *c) {
return;
}
t_source_code_location = find_core_type(c, str_lit("Source_Code_Location"));
t_source_code_location_ptr = alloc_type_pointer(t_allocator);
t_source_code_location_ptr = alloc_type_pointer(t_source_code_location);
}
void init_core_map_type(Checker *c) {
if (t_map_hash != nullptr) {
if (t_map_info != nullptr) {
return;
}
t_map_hash = find_core_type(c, str_lit("Map_Hash"));
t_map_header = find_core_type(c, str_lit("Map_Header"));
t_map_header_table = find_core_type(c, str_lit("Map_Header_Table"));
init_mem_allocator(c);
t_map_info = find_core_type(c, str_lit("Map_Info"));
t_map_cell_info = find_core_type(c, str_lit("Map_Cell_Info"));
t_raw_map = find_core_type(c, str_lit("Raw_Map"));
t_map_info_ptr = alloc_type_pointer(t_map_info);
t_map_cell_info_ptr = alloc_type_pointer(t_map_cell_info);
t_raw_map_ptr = alloc_type_pointer(t_raw_map);
}
void init_preload(Checker *c) {
+6 -2
View File
@@ -277,6 +277,8 @@ BuiltinProc__type_simple_boolean_end,
BuiltinProc_type_equal_proc,
BuiltinProc_type_hasher_proc,
BuiltinProc_type_map_info,
BuiltinProc_type_map_cell_info,
BuiltinProc__type_end,
@@ -570,8 +572,10 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("type_field_index_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_equal_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_hasher_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_equal_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_hasher_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_map_info"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_map_cell_info"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+406 -83
View File
@@ -140,7 +140,7 @@ lbContextData *lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx) {
}
lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) {
lbValue lb_equal_proc_for_type(lbModule *m, Type *type) {
type = base_type(type);
GB_ASSERT(is_type_comparable(type));
@@ -157,8 +157,8 @@ lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) {
static u32 proc_index = 0;
char buf[16] = {};
isize n = gb_snprintf(buf, 16, "__$equal%u", ++proc_index);
char buf[32] = {};
isize n = gb_snprintf(buf, 32, "__$equal%u", ++proc_index);
char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1);
String proc_name = make_string_c(str);
@@ -166,6 +166,9 @@ lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) {
map_set(&m->equal_procs, type, p);
lb_begin_procedure_body(p);
lb_add_attribute_to_proc(m, p->value, "readonly");
lb_add_attribute_to_proc(m, p->value, "nounwind");
LLVMValueRef x = LLVMGetParam(p->value, 0);
LLVMValueRef y = LLVMGetParam(p->value, 1);
x = LLVMBuildPointerCast(p->builder, x, ptr_type, "");
@@ -173,6 +176,8 @@ lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) {
lbValue lhs = {x, pt};
lbValue rhs = {y, pt};
lb_add_proc_attribute_at_index(p, 1+0, "nonnull");
lb_add_proc_attribute_at_index(p, 1+1, "nonnull");
lbBlock *block_same_ptr = lb_create_block(p, "same_ptr");
lbBlock *block_diff_ptr = lb_create_block(p, "diff_ptr");
@@ -277,28 +282,20 @@ lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) {
lbValue lb_simple_compare_hash(lbProcedure *p, Type *type, lbValue data, lbValue seed) {
GB_ASSERT_MSG(is_type_simple_compare(type), "%s", type_to_string(type));
i64 sz = type_size_of(type);
if (1 <= sz && sz <= 16) {
char name[20] = {};
gb_snprintf(name, 20, "default_hasher%d", cast(i32)sz);
auto args = array_make<lbValue>(permanent_allocator(), 2);
args[0] = data;
args[1] = seed;
return lb_emit_runtime_call(p, name, args);
}
auto args = array_make<lbValue>(permanent_allocator(), 3);
args[0] = data;
args[1] = seed;
args[2] = lb_const_int(p->module, t_int, type_size_of(type));
return lb_emit_runtime_call(p, "default_hasher_n", args);
return lb_emit_runtime_call(p, "default_hasher", args);
}
lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
void lb_add_callsite_force_inline(lbProcedure *p, lbValue ret_value) {
LLVMAddCallSiteAttribute(ret_value.value, LLVMAttributeIndex_FunctionIndex, lb_create_enum_attribute(p->module->ctx, "alwaysinline"));
}
lbValue lb_hasher_proc_for_type(lbModule *m, Type *type) {
type = core_type(type);
GB_ASSERT(is_type_valid_for_keys(type));
GB_ASSERT_MSG(is_type_valid_for_keys(type), "%s", type_to_string(type));
Type *pt = alloc_type_pointer(type);
@@ -310,8 +307,8 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
static u32 proc_index = 0;
char buf[16] = {};
isize n = gb_snprintf(buf, 16, "__$hasher%u", ++proc_index);
char buf[32] = {};
isize n = gb_snprintf(buf, 32, "__$hasher%u", ++proc_index);
char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1);
String proc_name = make_string_c(str);
@@ -320,16 +317,20 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
lb_begin_procedure_body(p);
defer (lb_end_procedure_body(p));
lb_add_attribute_to_proc(m, p->value, "readonly");
lb_add_attribute_to_proc(m, p->value, "nounwind");
LLVMValueRef x = LLVMGetParam(p->value, 0);
LLVMValueRef y = LLVMGetParam(p->value, 1);
lbValue data = {x, t_rawptr};
lbValue seed = {y, t_uintptr};
LLVMAttributeRef nonnull_attr = lb_create_enum_attribute(m->ctx, "nonnull");
LLVMAddAttributeAtIndex(p->value, 1+0, nonnull_attr);
lb_add_proc_attribute_at_index(p, 1+0, "nonnull");
lb_add_proc_attribute_at_index(p, 1+0, "readonly");
if (is_type_simple_compare(type)) {
lbValue res = lb_simple_compare_hash(p, type, data, seed);
lb_add_callsite_force_inline(p, res);
LLVMBuildRet(p->builder, res.value);
return {p->value, p->type};
}
@@ -343,7 +344,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
GB_ASSERT(type->Struct.offsets != nullptr);
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 field_hasher = lb_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;
@@ -356,11 +357,12 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
if (is_type_union_maybe_pointer(type)) {
Type *v = type->Union.variants[0];
lbValue variant_hasher = lb_get_hasher_proc_for_type(m, v);
lbValue variant_hasher = lb_hasher_proc_for_type(m, v);
args[0] = data;
args[1] = seed;
lbValue res = lb_emit_call(p, variant_hasher, args);
lb_add_callsite_force_inline(p, res);
LLVMBuildRet(p->builder, res.value);
}
@@ -379,7 +381,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
Type *v = type->Union.variants[i];
lbValue case_tag = lb_const_union_tag(p->module, type, v);
lbValue variant_hasher = lb_get_hasher_proc_for_type(m, v);
lbValue variant_hasher = lb_hasher_proc_for_type(m, v);
args[0] = data;
args[1] = seed;
@@ -397,7 +399,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
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);
lbValue elem_hasher = lb_hasher_proc_for_type(m, type->Array.elem);
auto loop_data = lb_loop_start(p, cast(isize)type->Array.count, t_i32);
@@ -418,7 +420,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
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);
lbValue elem_hasher = lb_hasher_proc_for_type(m, type->EnumeratedArray.elem);
auto loop_data = lb_loop_start(p, cast(isize)type->EnumeratedArray.count, t_i32);
@@ -439,12 +441,14 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
args[0] = data;
args[1] = seed;
lbValue res = lb_emit_runtime_call(p, "default_hasher_cstring", args);
lb_add_callsite_force_inline(p, res);
LLVMBuildRet(p->builder, res.value);
} else if (is_type_string(type)) {
auto args = array_make<lbValue>(permanent_allocator(), 2);
args[0] = data;
args[1] = seed;
lbValue res = lb_emit_runtime_call(p, "default_hasher_string", args);
lb_add_callsite_force_inline(p, res);
LLVMBuildRet(p->builder, res.value);
} else {
GB_PANIC("Unhandled type for hasher: %s", type_to_string(type));
@@ -454,6 +458,279 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
}
lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) {
GB_ASSERT(build_context.use_static_map_calls);
type = base_type(type);
GB_ASSERT(type->kind == Type_Map);
lbProcedure **found = map_get(&m->map_get_procs, type);
if (found) {
GB_ASSERT(*found != nullptr);
return {(*found)->value, (*found)->type};
}
static u32 proc_index = 0;
char buf[32] = {};
isize n = gb_snprintf(buf, 32, "__$map_get-%u", ++proc_index);
char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1);
String proc_name = make_string_c(str);
lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_map_get_proc);
map_set(&m->map_get_procs, type, p);
lb_begin_procedure_body(p);
defer (lb_end_procedure_body(p));
LLVMSetLinkage(p->value, LLVMInternalLinkage);
lb_add_attribute_to_proc(m, p->value, "readonly");
lb_add_attribute_to_proc(m, p->value, "nounwind");
if (build_context.ODIN_DEBUG) {
lb_add_attribute_to_proc(m, p->value, "noinline");
}
LLVMValueRef x = LLVMGetParam(p->value, 0);
LLVMValueRef y = LLVMGetParam(p->value, 1);
LLVMValueRef z = LLVMGetParam(p->value, 2);
lbValue map_ptr = {x, t_rawptr};
lbValue h = {y, t_uintptr};
lbValue key_ptr = {z, t_rawptr};
lb_add_proc_attribute_at_index(p, 1+0, "nonnull");
lb_add_proc_attribute_at_index(p, 1+0, "noalias");
lb_add_proc_attribute_at_index(p, 1+0, "readonly");
lb_add_proc_attribute_at_index(p, 1+2, "nonnull");
lb_add_proc_attribute_at_index(p, 1+2, "noalias");
lb_add_proc_attribute_at_index(p, 1+2, "readonly");
lbBlock *loop_block = lb_create_block(p, "loop");
lbBlock *hash_block = lb_create_block(p, "hash");
lbBlock *probe_block = lb_create_block(p, "probe");
lbBlock *increment_block = lb_create_block(p, "increment");
lbBlock *hash_compare_block = lb_create_block(p, "hash_compare");
lbBlock *key_compare_block = lb_create_block(p, "key_compare");
lbBlock *value_block = lb_create_block(p, "value");
lbBlock *nil_block = lb_create_block(p, "nil");
map_ptr = lb_emit_conv(p, map_ptr, t_raw_map_ptr);
lbValue map = lb_emit_load(p, map_ptr);
lbValue length = lb_map_len(p, map);
lb_emit_if(p, lb_emit_comp(p, Token_CmpEq, length, lb_const_nil(m, t_int)), nil_block, hash_block);
lb_start_block(p, hash_block);
key_ptr = lb_emit_conv(p, key_ptr, alloc_type_pointer(type->Map.key));
lbValue key = lb_emit_load(p, key_ptr);
lbAddr pos = lb_add_local_generated(p, t_uintptr, false);
lbAddr distance = lb_add_local_generated(p, t_uintptr, true);
lbValue capacity = lb_map_cap(p, map);
lbValue mask = lb_emit_conv(p, lb_emit_arith(p, Token_Sub, capacity, lb_const_int(m, t_int, 1), t_int), t_uintptr);
{
auto args = array_make<lbValue>(heap_allocator(), 2);
args[0] = map;
args[1] = h;
lb_addr_store(p, pos, lb_emit_runtime_call(p, "map_desired_position", args));
}
lbValue zero_uintptr = lb_const_int(m, t_uintptr, 0);
lbValue one_uintptr = lb_const_int(m, t_uintptr, 1);
lbValue ks = lb_map_data_uintptr(p, map);
lbValue vs = lb_map_cell_index_static(p, type->Map.key, ks, capacity);
lbValue hs = lb_map_cell_index_static(p, type->Map.value, vs, capacity);
ks = lb_emit_conv(p, ks, alloc_type_pointer(type->Map.key));
vs = lb_emit_conv(p, vs, alloc_type_pointer(type->Map.value));
hs = lb_emit_conv(p, hs, alloc_type_pointer(t_uintptr));
lb_emit_jump(p, loop_block);
lb_start_block(p, loop_block);
lbValue element_hash = lb_emit_load(p, lb_emit_ptr_offset(p, hs, lb_addr_load(p, pos)));
{
// if element_hash == 0 { return nil }
lb_emit_if(p, lb_emit_comp(p, Token_CmpEq, element_hash, zero_uintptr), nil_block, probe_block);
}
lb_start_block(p, probe_block);
{
auto args = array_make<lbValue>(heap_allocator(), 3);
args[0] = map;
args[1] = element_hash;
args[2] = lb_addr_load(p, pos);
lbValue probe_distance = lb_emit_runtime_call(p, "map_probe_distance", args);
lbValue cond = lb_emit_comp(p, Token_Gt, lb_addr_load(p, distance), probe_distance);
lb_emit_if(p, cond, nil_block, hash_compare_block);
}
lb_start_block(p, hash_compare_block);
{
lb_emit_if(p, lb_emit_comp(p, Token_CmpEq, element_hash, h), key_compare_block, increment_block);
}
lb_start_block(p, key_compare_block);
{
lbValue element_key = lb_map_cell_index_static(p, type->Map.key, ks, lb_addr_load(p, pos));
element_key = lb_emit_conv(p, element_key, ks.type);
lbValue cond = lb_emit_comp(p, Token_CmpEq, lb_emit_load(p, element_key), key);
lb_emit_if(p, cond, value_block, increment_block);
}
lb_start_block(p, value_block);
{
lbValue element_value = lb_map_cell_index_static(p, type->Map.value, vs, lb_addr_load(p, pos));
element_value = lb_emit_conv(p, element_value, t_rawptr);
LLVMBuildRet(p->builder, element_value.value);
}
lb_start_block(p, increment_block);
{
lbValue pp = lb_addr_load(p, pos);
pp = lb_emit_arith(p, Token_Add, pp, one_uintptr, t_uintptr);
pp = lb_emit_arith(p, Token_And, pp, mask, t_uintptr);
lb_addr_store(p, pos, pp);
lb_emit_increment(p, distance.addr);
}
lb_emit_jump(p, loop_block);
lb_start_block(p, nil_block);
{
lbValue res = lb_const_nil(m, t_rawptr);
LLVMBuildRet(p->builder, res.value);
}
return {p->value, p->type};
}
void lb_debug_print(lbProcedure *p, String const &str) {
auto args = array_make<lbValue>(heap_allocator(), 1);
args[0] = lb_const_string(p->module, str);
lb_emit_runtime_call(p, "print_string", args);
}
lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) {
GB_ASSERT(build_context.use_static_map_calls);
type = base_type(type);
GB_ASSERT(type->kind == Type_Map);
lbProcedure **found = map_get(&m->map_set_procs, type);
if (found) {
GB_ASSERT(*found != nullptr);
return {(*found)->value, (*found)->type};
}
static u32 proc_index = 0;
char buf[32] = {};
isize n = gb_snprintf(buf, 32, "__$map_set-%u", ++proc_index);
char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1);
String proc_name = make_string_c(str);
lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_map_set_proc);
map_set(&m->map_set_procs, type, p);
lb_begin_procedure_body(p);
defer (lb_end_procedure_body(p));
LLVMSetLinkage(p->value, LLVMInternalLinkage);
lb_add_attribute_to_proc(m, p->value, "nounwind");
if (build_context.ODIN_DEBUG) {
lb_add_attribute_to_proc(m, p->value, "noinline");
}
lbValue map_ptr = {LLVMGetParam(p->value, 0), t_rawptr};
lbValue hash = {LLVMGetParam(p->value, 1), t_uintptr};
lbValue key_ptr = {LLVMGetParam(p->value, 2), t_rawptr};
lbValue value_ptr = {LLVMGetParam(p->value, 3), t_rawptr};
lbValue location_ptr = {LLVMGetParam(p->value, 4), t_source_code_location_ptr};
map_ptr = lb_emit_conv(p, map_ptr, alloc_type_pointer(type));
key_ptr = lb_emit_conv(p, key_ptr, alloc_type_pointer(type->Map.key));
lb_add_proc_attribute_at_index(p, 1+0, "nonnull");
lb_add_proc_attribute_at_index(p, 1+0, "noalias");
lb_add_proc_attribute_at_index(p, 1+2, "nonnull");
if (!are_types_identical(type->Map.key, type->Map.value)) {
lb_add_proc_attribute_at_index(p, 1+2, "noalias");
}
lb_add_proc_attribute_at_index(p, 1+2, "readonly");
lb_add_proc_attribute_at_index(p, 1+3, "nonnull");
if (!are_types_identical(type->Map.key, type->Map.value)) {
lb_add_proc_attribute_at_index(p, 1+3, "noalias");
}
lb_add_proc_attribute_at_index(p, 1+3, "readonly");
lb_add_proc_attribute_at_index(p, 1+4, "nonnull");
lb_add_proc_attribute_at_index(p, 1+4, "noalias");
lb_add_proc_attribute_at_index(p, 1+4, "readonly");
////
lbValue found_ptr = {};
{
lbValue map_get_proc = lb_map_get_proc_for_type(m, type);
auto args = array_make<lbValue>(permanent_allocator(), 3);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = hash;
args[2] = key_ptr;
found_ptr = lb_emit_call(p, map_get_proc, args);
}
lbBlock *found_block = lb_create_block(p, "found");
lbBlock *check_grow_block = lb_create_block(p, "check-grow");
lbBlock *grow_fail_block = lb_create_block(p, "grow-fail");
lbBlock *insert_block = lb_create_block(p, "insert");
lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, found_ptr), found_block, check_grow_block);
lb_start_block(p, found_block);
{
lb_mem_copy_non_overlapping(p, found_ptr, value_ptr, lb_const_int(m, t_int, type_size_of(type->Map.value)));
LLVMBuildRet(p->builder, lb_emit_conv(p, found_ptr, t_rawptr).value);
}
lb_start_block(p, check_grow_block);
lbValue map_info = lb_gen_map_info_ptr(p->module, type);
{
auto args = array_make<lbValue>(permanent_allocator(), 3);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = map_info;
args[2] = lb_emit_load(p, location_ptr);
lbValue grow_err = lb_emit_runtime_call(p, "__dynamic_map_check_grow", args);
lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, grow_err), grow_fail_block, insert_block);
lb_start_block(p, grow_fail_block);
LLVMBuildRet(p->builder, LLVMConstNull(lb_type(m, t_rawptr)));
}
lb_start_block(p, insert_block);
{
auto args = array_make<lbValue>(permanent_allocator(), 5);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = map_info;
args[2] = hash;
args[3] = lb_emit_conv(p, key_ptr, t_uintptr);
args[4] = lb_emit_conv(p, value_ptr, t_uintptr);
lbValue result = lb_emit_runtime_call(p, "map_insert_hash_dynamic", args);
lb_emit_increment(p, lb_map_len_ptr(p, map_ptr));
LLVMBuildRet(p->builder, lb_emit_conv(p, result, t_rawptr).value);
}
return {p->value, p->type};
}
lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent) {
lbProcedure **found = map_get(&m->gen->anonymous_proc_lits, expr);
if (found) {
@@ -500,51 +777,60 @@ lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, A
return value;
}
lbValue lb_gen_map_header_table_internal(lbProcedure *p, Type *map_type) {
lbModule *m = p->module;
lbValue lb_gen_map_cell_info_ptr(lbModule *m, Type *type) {
lbAddr *found = map_get(&m->map_cell_info_map, type);
if (found) {
return found->addr;
}
i64 size = 0, len = 0;
map_cell_size_and_len(type, &size, &len);
LLVMValueRef const_values[4] = {};
const_values[0] = lb_const_int(m, t_uintptr, type_size_of(type)).value;
const_values[1] = lb_const_int(m, t_uintptr, type_align_of(type)).value;
const_values[2] = lb_const_int(m, t_uintptr, size).value;
const_values[3] = lb_const_int(m, t_uintptr, len).value;
LLVMValueRef llvm_res = llvm_const_named_struct(m, t_map_cell_info, const_values, gb_count_of(const_values));
lbValue res = {llvm_res, t_map_cell_info};
lbAddr addr = lb_add_global_generated(m, t_map_cell_info, res, nullptr);
lb_make_global_private_const(addr);
map_set(&m->map_cell_info_map, type, addr);
return addr.addr;
}
lbValue lb_gen_map_info_ptr(lbModule *m, Type *map_type) {
map_type = base_type(map_type);
GB_ASSERT(map_type->kind == Type_Map);
lbAddr *found = map_get(&m->map_header_table_map, map_type);
lbAddr *found = map_get(&m->map_info_map, map_type);
if (found) {
return lb_addr_load(p, *found);
return found->addr;
}
GB_ASSERT(map_type->Map.entry_type->kind == Type_Struct);
i64 entry_size = type_size_of (map_type->Map.entry_type);
i64 entry_align = type_align_of (map_type->Map.entry_type);
GB_ASSERT(t_map_info != nullptr);
GB_ASSERT(t_map_cell_info != nullptr);
i64 key_offset = type_offset_of(map_type->Map.entry_type, 2);
i64 key_size = type_size_of (map_type->Map.key);
LLVMValueRef key_cell_info = lb_gen_map_cell_info_ptr(m, map_type->Map.key).value;
LLVMValueRef value_cell_info = lb_gen_map_cell_info_ptr(m, map_type->Map.value).value;
i64 value_offset = type_offset_of(map_type->Map.entry_type, 3);
i64 value_size = type_size_of (map_type->Map.value);
LLVMValueRef const_values[4] = {};
const_values[0] = key_cell_info;
const_values[1] = value_cell_info;
const_values[2] = lb_hasher_proc_for_type(m, map_type->Map.key).value;
const_values[3] = lb_equal_proc_for_type(m, map_type->Map.key).value;
Type *key_type = map_type->Map.key;
Type *val_type = map_type->Map.value;
gb_unused(val_type);
LLVMValueRef llvm_res = llvm_const_named_struct(m, t_map_info, const_values, gb_count_of(const_values));
lbValue res = {llvm_res, t_map_info};
Type *st = base_type(t_map_header_table);
GB_ASSERT(st->Struct.fields.count == 7);
LLVMValueRef const_values[7] = {};
const_values[0] = lb_get_equal_proc_for_type(m, key_type) .value;
const_values[1] = lb_const_int(m, t_int, entry_size) .value;
const_values[2] = lb_const_int(m, t_int, entry_align) .value;
const_values[3] = lb_const_int(m, t_uintptr, key_offset) .value;
const_values[4] = lb_const_int(m, t_int, key_size) .value;
const_values[5] = lb_const_int(m, t_uintptr, value_offset).value;
const_values[6] = lb_const_int(m, t_int, value_size) .value;
LLVMValueRef llvm_res = llvm_const_named_struct(m, t_map_header_table, const_values, gb_count_of(const_values));
lbValue res = {llvm_res, t_map_header_table};
lbAddr addr = lb_add_global_generated(m, t_map_header_table, res, nullptr);
lbAddr addr = lb_add_global_generated(m, t_map_info, res, nullptr);
lb_make_global_private_const(addr);
map_set(&m->map_header_table_map, map_type, addr);
return lb_addr_load(p, addr);
map_set(&m->map_info_map, map_type, addr);
return addr.addr;
}
lbValue lb_const_hash(lbModule *m, lbValue key, Type *key_type) {
@@ -602,7 +888,7 @@ lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue key, Type *key_type, lbValue
lbValue hashed_key = lb_const_hash(p->module, key, key_type);
if (hashed_key.value == nullptr) {
lbValue hasher = lb_get_hasher_proc_for_type(p->module, key_type);
lbValue hasher = lb_hasher_proc_for_type(p->module, key_type);
auto args = array_make<lbValue>(permanent_allocator(), 2);
args[0] = key_ptr;
@@ -615,42 +901,68 @@ lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue key, Type *key_type, lbValue
lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map_ptr, lbValue const &key) {
Type *map_type = base_type(type_deref(map_ptr.type));
GB_ASSERT(map_type->kind == Type_Map);
lbValue ptr = {};
lbValue key_ptr = {};
auto args = array_make<lbValue>(permanent_allocator(), 4);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = lb_gen_map_header_table_internal(p, map_type);
args[2] = lb_gen_map_key_hash(p, key, map_type->Map.key, &key_ptr);
args[3] = key_ptr;
lbValue hash = lb_gen_map_key_hash(p, key, map_type->Map.key, &key_ptr);
lbValue ptr = lb_emit_runtime_call(p, "__dynamic_map_get", args);
if (build_context.use_static_map_calls) {
lbValue map_get_proc = lb_map_get_proc_for_type(p->module, map_type);
auto args = array_make<lbValue>(permanent_allocator(), 3);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = hash;
args[2] = key_ptr;
ptr = lb_emit_call(p, map_get_proc, args);
} else {
auto args = array_make<lbValue>(permanent_allocator(), 4);
args[0] = lb_emit_transmute(p, map_ptr, t_raw_map_ptr);
args[1] = lb_gen_map_info_ptr(p->module, map_type);
args[2] = hash;
args[3] = key_ptr;
ptr = lb_emit_runtime_call(p, "__dynamic_map_get", args);
}
return lb_emit_conv(p, ptr, alloc_type_pointer(map_type->Map.value));
}
void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbValue const &map_ptr, Type *map_type,
lbValue const &map_key, lbValue const &map_value, Ast *node) {
void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_ptr, Type *map_type,
lbValue const &map_key, lbValue const &map_value, Ast *node) {
map_type = base_type(map_type);
GB_ASSERT(map_type->kind == Type_Map);
lbValue key_ptr = {};
lbValue key_hash = lb_gen_map_key_hash(p, map_key, map_type->Map.key, &key_ptr);
lbValue hash = lb_gen_map_key_hash(p, map_key, map_type->Map.key, &key_ptr);
lbValue v = lb_emit_conv(p, map_value, map_type->Map.value);
lbValue value_ptr = lb_address_from_load_or_generate_local(p, v);
lbAddr value_addr = lb_add_local_generated(p, v.type, false);
lb_addr_store(p, value_addr, v);
if (build_context.use_static_map_calls) {
lbValue map_set_proc = lb_map_set_proc_for_type(p->module, map_type);
auto args = array_make<lbValue>(permanent_allocator(), 6);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = lb_gen_map_header_table_internal(p, map_type);
args[2] = key_hash;
args[3] = key_ptr;
args[4] = lb_emit_conv(p, value_addr.addr, t_rawptr);
args[5] = lb_emit_source_code_location_as_global(p, node);
lb_emit_runtime_call(p, "__dynamic_map_set", args);
auto args = array_make<lbValue>(permanent_allocator(), 5);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = hash;
args[2] = lb_emit_conv(p, key_ptr, t_rawptr);
args[3] = lb_emit_conv(p, value_ptr, t_rawptr);
args[4] = lb_emit_source_code_location_as_global(p, node);
lb_emit_call(p, map_set_proc, args);
} else {
auto args = array_make<lbValue>(permanent_allocator(), 6);
args[0] = lb_emit_conv(p, map_ptr, t_raw_map_ptr);
args[1] = lb_gen_map_info_ptr(p->module, map_type);
args[2] = hash;
args[3] = lb_emit_conv(p, key_ptr, t_rawptr);
args[4] = lb_emit_conv(p, value_ptr, t_rawptr);
args[5] = lb_emit_source_code_location_as_global(p, node);
lb_emit_runtime_call(p, "__dynamic_map_set", args);
}
}
void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos) {
lbValue lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos) {
GB_ASSERT(!build_context.no_dynamic_literals);
String proc_name = {};
@@ -660,10 +972,10 @@ void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const
auto args = array_make<lbValue>(permanent_allocator(), 4);
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = lb_gen_map_header_table_internal(p, type_deref(map_ptr.type));
args[2] = lb_const_int(p->module, t_int, capacity);
args[1] = lb_gen_map_info_ptr(p->module, type_deref(map_ptr.type));
args[2] = lb_const_int(p->module, t_uint, capacity);
args[3] = lb_emit_source_code_location_as_global(p, proc_name, pos);
lb_emit_runtime_call(p, "__dynamic_map_reserve", args);
return lb_emit_runtime_call(p, "__dynamic_map_reserve", args);
}
@@ -688,6 +1000,8 @@ lbProcedure *lb_create_startup_type_info(lbModule *m) {
p->is_startup = true;
LLVMSetLinkage(p->value, LLVMInternalLinkage);
lb_add_attribute_to_proc(m, p->value, "nounwind");
lb_begin_procedure_body(p);
lb_setup_type_info_data(p);
@@ -712,6 +1026,7 @@ lbProcedure *lb_create_objc_names(lbModule *main_module) {
}
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl);
lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit("__$init_objc_names"), proc_type);
lb_add_attribute_to_proc(p->module, p->value, "nounwind");
p->is_startup = true;
return p;
}
@@ -1198,6 +1513,14 @@ WORKER_TASK_PROC(lb_llvm_function_pass_worker_proc) {
lbProcedure *p = m->hasher_procs.entries[i].value;
lb_run_function_pass_manager(default_function_pass_manager, p);
}
for_array(i, m->map_get_procs.entries) {
lbProcedure *p = m->map_get_procs.entries[i].value;
lb_run_function_pass_manager(default_function_pass_manager, p);
}
for_array(i, m->map_set_procs.entries) {
lbProcedure *p = m->map_set_procs.entries[i].value;
lb_run_function_pass_manager(default_function_pass_manager, p);
}
return 0;
}
+10 -7
View File
@@ -144,6 +144,8 @@ struct lbModule {
PtrMap<Type *, lbProcedure *> equal_procs;
PtrMap<Type *, lbProcedure *> hasher_procs;
PtrMap<Type *, lbProcedure *> map_get_procs;
PtrMap<Type *, lbProcedure *> map_set_procs;
u32 nested_type_name_guid;
@@ -160,7 +162,8 @@ struct lbModule {
StringMap<lbAddr> objc_classes;
StringMap<lbAddr> objc_selectors;
PtrMap<Type *, lbAddr> map_header_table_map;
PtrMap<Type *, lbAddr> map_cell_info_map; // address of runtime.Map_Info
PtrMap<Type *, lbAddr> map_info_map; // address of runtime.Map_Cell_Info
};
struct lbGenerator {
@@ -422,8 +425,6 @@ lbValue lb_dynamic_array_elem(lbProcedure *p, lbValue da);
lbValue lb_dynamic_array_len(lbProcedure *p, lbValue da);
lbValue lb_dynamic_array_cap(lbProcedure *p, lbValue da);
lbValue lb_dynamic_array_allocator(lbProcedure *p, lbValue da);
lbValue lb_map_entries(lbProcedure *p, lbValue value);
lbValue lb_map_entries_ptr(lbProcedure *p, lbValue value);
lbValue lb_map_len(lbProcedure *p, lbValue value);
lbValue lb_map_cap(lbProcedure *p, lbValue value);
lbValue lb_soa_struct_len(lbProcedure *p, lbValue value);
@@ -447,10 +448,12 @@ String lb_get_const_string(lbModule *m, lbValue value);
lbValue lb_generate_local_array(lbProcedure *p, Type *elem_type, i64 count, bool zero_init=true);
lbValue lb_generate_global_array(lbModule *m, Type *elem_type, i64 count, String prefix, i64 id);
lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue key, Type *key_type, lbValue *key_ptr_);
lbValue lb_gen_map_cell_info_ptr(lbModule *m, Type *type);
lbValue lb_gen_map_info_ptr(lbModule *m, Type *map_type);
lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue const &map_ptr, lbValue const &key);
void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbValue const &map_ptr, Type *map_type, lbValue const &map_key, lbValue const &map_value, Ast *node);
void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos);
void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_ptr, Type *map_type, lbValue const &map_key, lbValue const &map_value, Ast *node);
lbValue lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos);
lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e);
lbValue lb_find_value_from_entity(lbModule *m, Entity *e);
@@ -461,8 +464,8 @@ lbValue lb_emit_source_code_location_const(lbProcedure *p, String const &procedu
lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterValue const &param_value, TokenPos const &pos);
lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type);
lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type);
lbValue lb_equal_proc_for_type(lbModule *m, Type *type);
lbValue lb_hasher_proc_for_type(lbModule *m, Type *type);
lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t);
LLVMMetadataRef lb_debug_type(lbModule *m, Type *type);
+13 -4
View File
@@ -283,19 +283,28 @@ lbValue lb_emit_source_code_location_const(lbProcedure *p, Ast *node) {
return lb_emit_source_code_location_const(p, proc_name, pos);
}
lbValue lb_emit_source_code_location_as_global(lbProcedure *p, String const &procedure, TokenPos const &pos) {
lbValue lb_emit_source_code_location_as_global_ptr(lbProcedure *p, String const &procedure, TokenPos const &pos) {
lbValue loc = lb_emit_source_code_location_const(p, procedure, pos);
lbAddr addr = lb_add_global_generated(p->module, loc.type, loc, nullptr);
lb_make_global_private_const(addr);
return lb_addr_load(p, addr);
return addr.addr;
}
lbValue lb_emit_source_code_location_as_global(lbProcedure *p, Ast *node) {
lbValue lb_emit_source_code_location_as_global_ptr(lbProcedure *p, Ast *node) {
lbValue loc = lb_emit_source_code_location_const(p, node);
lbAddr addr = lb_add_global_generated(p->module, loc.type, loc, nullptr);
lb_make_global_private_const(addr);
return lb_addr_load(p, addr);
return addr.addr;
}
lbValue lb_emit_source_code_location_as_global(lbProcedure *p, String const &procedure, TokenPos const &pos) {
return lb_emit_load(p, lb_emit_source_code_location_as_global_ptr(p, procedure, pos));
}
lbValue lb_emit_source_code_location_as_global(lbProcedure *p, Ast *node) {
return lb_emit_load(p, lb_emit_source_code_location_as_global_ptr(p, node));
}
+2 -1
View File
@@ -671,7 +671,8 @@ void lb_debug_complete_types(lbModule *m) {
break;
case Type_Map:
bt = bt->Map.internal_type;
GB_ASSERT(t_raw_map != nullptr);
bt = base_type(t_raw_map);
/*fallthrough*/
case Type_Struct:
if (file == nullptr) {
+4 -3
View File
@@ -2215,7 +2215,7 @@ lbValue lb_compare_records(lbProcedure *p, TokenKind op_kind, lbValue left, lbVa
args[2] = lb_const_int(p->module, t_int, type_size_of(type));
res = lb_emit_runtime_call(p, "memory_equal", args);
} else {
lbValue value = lb_get_equal_proc_for_type(p->module, type);
lbValue value = lb_equal_proc_for_type(p->module, type);
auto args = array_make<lbValue>(permanent_allocator(), 2);
args[0] = lb_emit_conv(p, left_ptr, t_rawptr);
args[1] = lb_emit_conv(p, right_ptr, t_rawptr);
@@ -4131,7 +4131,8 @@ lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
}
GB_ASSERT(!build_context.no_dynamic_literals);
lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos);
lbValue err = lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos);
gb_unused(err);
for_array(field_index, cl->elems) {
Ast *elem = cl->elems[field_index];
@@ -4139,7 +4140,7 @@ lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
lbValue key = lb_build_expr(p, fv->field);
lbValue value = lb_build_expr(p, fv->value);
lb_insert_dynamic_map_key_and_value(p, v.addr, type, key, value, elem);
lb_internal_dynamic_map_set(p, v.addr, type, key, value, elem);
}
break;
}
+7 -34
View File
@@ -67,6 +67,8 @@ void lb_init_module(lbModule *m, Checker *c) {
map_init(&m->function_type_map, a);
map_init(&m->equal_procs, a);
map_init(&m->hasher_procs, a);
map_init(&m->map_get_procs, a);
map_init(&m->map_set_procs, a);
array_init(&m->procedures_to_generate, a, 0, 1024);
array_init(&m->missing_procedures_to_check, a, 0, 16);
map_init(&m->debug_values, a);
@@ -75,7 +77,8 @@ void lb_init_module(lbModule *m, Checker *c) {
string_map_init(&m->objc_classes, a);
string_map_init(&m->objc_selectors, a);
map_init(&m->map_header_table_map, a, 0);
map_init(&m->map_info_map, a, 0);
map_init(&m->map_cell_info_map, a, 0);
}
@@ -725,7 +728,7 @@ void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) {
return;
} else if (addr.kind == lbAddr_Map) {
lb_insert_dynamic_map_key_and_value(p, addr.addr, addr.map.type, addr.map.key, value, p->curr_stmt);
lb_internal_dynamic_map_set(p, addr.addr, addr.map.type, addr.map.key, value, p->curr_stmt);
return;
} else if (addr.kind == lbAddr_Context) {
lbAddr old_addr = lb_find_or_generate_context_ptr(p);
@@ -1931,38 +1934,8 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
case Type_Map:
init_map_internal_types(type);
{
Type *internal_type = type->Map.internal_type;
GB_ASSERT(internal_type->kind == Type_Struct);
m->internal_type_level -= 1;
defer (m->internal_type_level += 1);
unsigned field_count = cast(unsigned)(internal_type->Struct.fields.count);
GB_ASSERT(field_count == 2);
LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count);
LLVMTypeRef entries_fields[] = {
lb_type(m, t_rawptr), // data
lb_type(m, t_int), // len
lb_type(m, t_int), // cap
lb_type(m, t_allocator), // allocator
};
fields[0] = lb_type(m, internal_type->Struct.fields[0]->type);
fields[1] = LLVMStructTypeInContext(ctx, entries_fields, gb_count_of(entries_fields), false);
{ // Add this to simplify things
lbStructFieldRemapping entries_field_remapping = {};
slice_init(&entries_field_remapping, permanent_allocator(), gb_count_of(entries_fields));
for_array(i, entries_field_remapping) {
entries_field_remapping[i] = cast(i32)i;
}
map_set(&m->struct_field_remapping, cast(void *)fields[1], entries_field_remapping);
}
return LLVMStructTypeInContext(ctx, fields, field_count, false);
}
GB_ASSERT(t_raw_map != nullptr);
return lb_type_internal(m, t_raw_map);
case Type_Struct:
{
+10 -2
View File
@@ -586,6 +586,7 @@ void lb_begin_procedure_body(lbProcedure *p) {
// defer x = ... // defer is executed after the `defer`
// return // the values returned should be zeroed
// }
// NOTE(bill): REALLY, don't even bother.
lbAddr res = lb_add_local(p, e->type, e);
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
@@ -2319,10 +2320,17 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
case BuiltinProc_type_equal_proc:
return lb_get_equal_proc_for_type(p->module, ce->args[0]->tav.type);
return lb_equal_proc_for_type(p->module, ce->args[0]->tav.type);
case BuiltinProc_type_hasher_proc:
return lb_get_hasher_proc_for_type(p->module, ce->args[0]->tav.type);
return lb_hasher_proc_for_type(p->module, ce->args[0]->tav.type);
case BuiltinProc_type_map_info:
return lb_gen_map_info_ptr(p->module, ce->args[0]->tav.type);
case BuiltinProc_type_map_cell_info:
return lb_gen_map_cell_info_ptr(p->module, ce->args[0]->tav.type);
case BuiltinProc_fixed_point_mul:
case BuiltinProc_fixed_point_div:
+124 -13
View File
@@ -354,16 +354,6 @@ void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValu
}
break;
}
case Type_Map: {
lbValue entries = lb_map_entries_ptr(p, expr);
lbValue elem = lb_emit_struct_ep(p, entries, 0);
elem = lb_emit_load(p, elem);
lbValue entry = lb_emit_ptr_offset(p, elem, idx);
idx = lb_emit_load(p, lb_emit_struct_ep(p, entry, 2));
val = lb_emit_load(p, lb_emit_struct_ep(p, entry, 3));
break;
}
case Type_Struct: {
GB_ASSERT(is_type_soa_struct(expr_type));
break;
@@ -380,6 +370,129 @@ void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValu
if (done_) *done_ = done;
}
lbValue lb_map_cell_index_static(lbProcedure *p, Type *type, lbValue cells_ptr, lbValue index) {
i64 size, len;
i64 elem_sz = type_size_of(type);
map_cell_size_and_len(type, &size, &len);
index = lb_emit_conv(p, index, t_uintptr);
if (size == len*elem_sz) {
lbValue elems_ptr = lb_emit_conv(p, cells_ptr, alloc_type_pointer(type));
return lb_emit_ptr_offset(p, elems_ptr, index);
}
lbValue cell_index = {};
lbValue data_index = {};
lbValue size_const = lb_const_int(p->module, t_uintptr, size);
lbValue len_const = lb_const_int(p->module, t_uintptr, len);
if (is_power_of_two(len)) {
u64 log2_len = floor_log2(cast(u64)len);
cell_index = log2_len == 0 ? index : lb_emit_arith(p, Token_Shr, index, lb_const_int(p->module, t_uintptr, log2_len), t_uintptr);
data_index = lb_emit_arith(p, Token_And, index, lb_const_int(p->module, t_uintptr, len-1), t_uintptr);
} else {
cell_index = lb_emit_arith(p, Token_Quo, index, len_const, t_uintptr);
data_index = lb_emit_arith(p, Token_Mod, index, len_const, t_uintptr);
}
lbValue elems_ptr = lb_emit_conv(p, cells_ptr, t_uintptr);
lbValue cell_offset = lb_emit_arith(p, Token_Mul, size_const, cell_index, t_uintptr);
elems_ptr = lb_emit_arith(p, Token_Add, elems_ptr, cell_offset, t_uintptr);
elems_ptr = lb_emit_conv(p, elems_ptr, alloc_type_pointer(type));
return lb_emit_ptr_offset(p, elems_ptr, data_index);
}
void lb_map_kvh_data_static(lbProcedure *p, lbValue map_value, lbValue *ks_, lbValue *vs_, lbValue *hs_) {
lbValue capacity = lb_map_cap(p, map_value);
lbValue ks = lb_map_data_uintptr(p, map_value);
lbValue vs = {};
lbValue hs = {};
if (ks_) *ks_ = ks;
if (vs_) *vs_ = vs;
if (hs_) *hs_ = hs;
}
lbValue lb_map_hash_is_valid(lbProcedure *p, lbValue hash) {
// N :: size_of(uintptr)*8 - 1
// (hash != 0) & (hash>>N == 0)
u64 top_bit_index = cast(u64)(type_size_of(t_uintptr)*8 - 1);
lbValue shift_amount = lb_const_int(p->module, t_uintptr, top_bit_index);
lbValue zero = lb_const_int(p->module, t_uintptr, 0);
lbValue not_empty = lb_emit_comp(p, Token_NotEq, hash, zero);
lbValue not_deleted = lb_emit_arith(p, Token_Shr, hash, shift_amount, t_uintptr);
not_deleted = lb_emit_comp(p, Token_CmpEq, not_deleted, zero);
return lb_emit_arith(p, Token_And, not_deleted, not_empty, t_uintptr);
}
void lb_build_range_map(lbProcedure *p, lbValue expr, Type *val_type,
lbValue *val_, lbValue *key_, lbBlock **loop_, lbBlock **done_) {
lbModule *m = p->module;
Type *type = base_type(type_deref(expr.type));
GB_ASSERT(type->kind == Type_Map);
lbValue idx = {};
lbBlock *loop = nullptr;
lbBlock *done = nullptr;
lbBlock *body = nullptr;
lbBlock *hash_check = nullptr;
lbAddr index = lb_add_local_generated(p, t_int, false);
lb_addr_store(p, index, lb_const_int(m, t_int, cast(u64)-1));
loop = lb_create_block(p, "for.index.loop");
lb_emit_jump(p, loop);
lb_start_block(p, loop);
lbValue incr = lb_emit_arith(p, Token_Add, lb_addr_load(p, index), lb_const_int(m, t_int, 1), t_int);
lb_addr_store(p, index, incr);
hash_check = lb_create_block(p, "for.index.hash_check");
body = lb_create_block(p, "for.index.body");
done = lb_create_block(p, "for.index.done");
lbValue map_value = lb_emit_load(p, expr);
lbValue capacity = lb_map_cap(p, map_value);
lbValue cond = lb_emit_comp(p, Token_Lt, incr, capacity);
lb_emit_if(p, cond, hash_check, done);
lb_start_block(p, hash_check);
idx = lb_addr_load(p, index);
lbValue ks = lb_map_data_uintptr(p, map_value);
lbValue vs = lb_emit_conv(p, lb_map_cell_index_static(p, type->Map.key, ks, capacity), alloc_type_pointer(type->Map.value));
lbValue hs = lb_emit_conv(p, lb_map_cell_index_static(p, type->Map.value, vs, capacity), alloc_type_pointer(t_uintptr));
// NOTE(bill): no need to use lb_map_cell_index_static for that hashes
// since it will always be packed without padding into the cells
lbValue hash = lb_emit_load(p, lb_emit_ptr_offset(p, hs, idx));
lbValue hash_cond = lb_map_hash_is_valid(p, hash);
lb_emit_if(p, hash_cond, body, loop);
lb_start_block(p, body);
lbValue key_ptr = lb_map_cell_index_static(p, type->Map.key, ks, idx);
lbValue val_ptr = lb_map_cell_index_static(p, type->Map.value, vs, idx);
lbValue key = lb_emit_load(p, key_ptr);
lbValue val = lb_emit_load(p, val_ptr);
if (val_) *val_ = val;
if (key_) *key_ = key;
if (loop_) *loop_ = loop;
if (done_) *done_ = done;
}
void lb_build_range_string(lbProcedure *p, lbValue expr, Type *val_type,
lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_) {
@@ -749,9 +862,7 @@ void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *scope) {
if (is_type_pointer(type_deref(map.type))) {
map = lb_emit_load(p, map);
}
lbValue entries_ptr = lb_map_entries_ptr(p, map);
lbValue count_ptr = lb_emit_struct_ep(p, entries_ptr, 1);
lb_build_range_indexed(p, map, val1_type, count_ptr, &val, &key, &loop, &done);
lb_build_range_map(p, map, val1_type, &val, &key, &loop, &done);
break;
}
case Type_Array: {
+4 -8
View File
@@ -666,7 +666,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
}
if (is_type_comparable(t) && !is_type_simple_compare(t)) {
vals[3] = lb_get_equal_proc_for_type(m, t).value;
vals[3] = lb_equal_proc_for_type(m, t).value;
}
vals[4] = lb_const_bool(m, t_bool, t->Union.custom_align != 0).value;
@@ -702,7 +702,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
vals[6] = is_raw_union.value;
vals[7] = is_custom_align.value;
if (is_type_comparable(t) && !is_type_simple_compare(t)) {
vals[8] = lb_get_equal_proc_for_type(m, t).value;
vals[8] = lb_equal_proc_for_type(m, t).value;
}
@@ -788,15 +788,11 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
case Type_Map: {
tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_map_ptr);
init_map_internal_types(t);
lbValue gst = lb_type_info(m, t->Map.internal_type);
LLVMValueRef vals[5] = {
LLVMValueRef vals[3] = {
lb_type_info(m, t->Map.key).value,
lb_type_info(m, t->Map.value).value,
gst.value,
lb_get_equal_proc_for_type(m, t->Map.key).value,
lb_get_hasher_proc_for_type(m, t->Map.key).value
lb_gen_map_info_ptr(p->module, t).value
};
lbValue res = {};
+51 -44
View File
@@ -203,26 +203,19 @@ lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t) {
if (is_type_uintptr(src) && is_type_internally_pointer_like(dst)) {
res.value = LLVMBuildIntToPtr(p->builder, value.value, lb_type(m, t), "");
return res;
}
if (is_type_internally_pointer_like(src) && is_type_uintptr(dst)) {
} else if (is_type_internally_pointer_like(src) && is_type_uintptr(dst)) {
res.value = LLVMBuildPtrToInt(p->builder, value.value, lb_type(m, t), "");
return res;
}
if (is_type_integer(src) && is_type_internally_pointer_like(dst)) {
} else if (is_type_integer(src) && is_type_internally_pointer_like(dst)) {
res.value = LLVMBuildIntToPtr(p->builder, value.value, lb_type(m, t), "");
return res;
} else if (is_type_internally_pointer_like(src) && is_type_integer(dst)) {
res.value = LLVMBuildPtrToInt(p->builder, value.value, lb_type(m, t), "");
return res;
}
if (is_type_internally_pointer_like(src) && is_type_internally_pointer_like(dst)) {
} else if (is_type_internally_pointer_like(src) && is_type_internally_pointer_like(dst)) {
res.value = LLVMBuildPointerCast(p->builder, value.value, lb_type(p->module, t), "");
return res;
}
if (is_type_simd_vector(src) && is_type_simd_vector(dst)) {
} else if (is_type_simd_vector(src) && is_type_simd_vector(dst)) {
res.value = LLVMBuildBitCast(p->builder, value.value, lb_type(p->module, t), "");
return res;
} else if (is_type_array_like(src) && is_type_simd_vector(dst)) {
@@ -239,9 +232,11 @@ lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t) {
ap = lb_emit_conv(p, ap, alloc_type_pointer(value.type));
lb_emit_store(p, ap, value);
return lb_addr_load(p, addr);
}
if (lb_is_type_aggregate(src) || lb_is_type_aggregate(dst)) {
} else if (is_type_map(src) && are_types_identical(t_raw_map, t)) {
res.value = value.value;
res.type = t;
return res;
} else if (lb_is_type_aggregate(src) || lb_is_type_aggregate(dst)) {
lbValue s = lb_address_from_load_or_generate_local(p, value);
lbValue d = lb_emit_transmute(p, s, alloc_type_pointer(t));
return lb_emit_load(p, d);
@@ -990,14 +985,13 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
}
} else if (is_type_map(t)) {
init_map_internal_types(t);
Type *itp = alloc_type_pointer(t->Map.internal_type);
Type *itp = alloc_type_pointer(t_raw_map);
s = lb_emit_transmute(p, s, itp);
Type *gst = t->Map.internal_type;
GB_ASSERT(gst->kind == Type_Struct);
switch (index) {
case 0: result_type = get_struct_field_type(gst, 0); break;
case 1: result_type = get_struct_field_type(gst, 1); break;
case 0: result_type = get_struct_field_type(t_raw_map, 0); break;
case 1: result_type = get_struct_field_type(t_raw_map, 1); break;
case 2: result_type = get_struct_field_type(t_raw_map, 2); break;
}
} else if (is_type_array(t)) {
return lb_emit_array_epi(p, s, index);
@@ -1130,10 +1124,10 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) {
case Type_Map:
{
init_map_internal_types(t);
Type *gst = t->Map.internal_type;
switch (index) {
case 0: result_type = get_struct_field_type(gst, 0); break;
case 1: result_type = get_struct_field_type(gst, 1); break;
case 0: result_type = get_struct_field_type(t_raw_map, 0); break;
case 1: result_type = get_struct_field_type(t_raw_map, 1); break;
case 2: result_type = get_struct_field_type(t_raw_map, 2); break;
}
}
break;
@@ -1439,34 +1433,47 @@ lbValue lb_dynamic_array_allocator(lbProcedure *p, lbValue da) {
return lb_emit_struct_ev(p, da, 3);
}
lbValue lb_map_entries(lbProcedure *p, lbValue value) {
Type *t = base_type(value.type);
GB_ASSERT_MSG(t->kind == Type_Map, "%s", type_to_string(t));
init_map_internal_types(t);
i32 index = 1;
lbValue entries = lb_emit_struct_ev(p, value, index);
return entries;
}
lbValue lb_map_entries_ptr(lbProcedure *p, lbValue value) {
Type *t = base_type(type_deref(value.type));
GB_ASSERT_MSG(t->kind == Type_Map, "%s", type_to_string(t));
init_map_internal_types(t);
i32 index = 1;
lbValue entries = lb_emit_struct_ep(p, value, index);
return entries;
}
lbValue lb_map_len(lbProcedure *p, lbValue value) {
lbValue entries = lb_map_entries(p, value);
return lb_dynamic_array_len(p, entries);
GB_ASSERT_MSG(is_type_map(value.type) || are_types_identical(value.type, t_raw_map), "%s", type_to_string(value.type));
lbValue len = lb_emit_struct_ev(p, value, 1);
return lb_emit_conv(p, len, t_int);
}
lbValue lb_map_len_ptr(lbProcedure *p, lbValue map_ptr) {
Type *type = map_ptr.type;
GB_ASSERT(is_type_pointer(type));
type = type_deref(type);
GB_ASSERT_MSG(is_type_map(type) || are_types_identical(type, t_raw_map), "%s", type_to_string(type));
return lb_emit_struct_ep(p, map_ptr, 1);
}
lbValue lb_map_cap(lbProcedure *p, lbValue value) {
lbValue entries = lb_map_entries(p, value);
return lb_dynamic_array_cap(p, entries);
GB_ASSERT_MSG(is_type_map(value.type) || are_types_identical(value.type, t_raw_map), "%s", type_to_string(value.type));
lbValue zero = lb_const_int(p->module, t_uintptr, 0);
lbValue one = lb_const_int(p->module, t_uintptr, 1);
lbValue mask = lb_const_int(p->module, t_uintptr, MAP_CACHE_LINE_SIZE-1);
lbValue data = lb_emit_struct_ev(p, value, 0);
lbValue log2_cap = lb_emit_arith(p, Token_And, data, mask, t_uintptr);
lbValue cap = lb_emit_arith(p, Token_Shl, one, log2_cap, t_uintptr);
lbValue cmp = lb_emit_comp(p, Token_CmpEq, data, zero);
return lb_emit_conv(p, lb_emit_select(p, cmp, zero, cap), t_int);
}
lbValue lb_map_data_uintptr(lbProcedure *p, lbValue value) {
GB_ASSERT(is_type_map(value.type) || are_types_identical(value.type, t_raw_map));
lbValue data = lb_emit_struct_ev(p, value, 0);
u64 mask_value = 0;
if (build_context.word_size == 4) {
mask_value = 0xfffffffful & ~(MAP_CACHE_LINE_SIZE-1);
} else {
mask_value = 0xffffffffffffffffull & ~(MAP_CACHE_LINE_SIZE-1);
}
lbValue mask = lb_const_int(p->module, t_uintptr, mask_value);
return lb_emit_arith(p, Token_And, data, mask, t_uintptr);
}
lbValue lb_soa_struct_len(lbProcedure *p, lbValue value) {
Type *t = base_type(value.type);
bool is_ptr = false;
+6
View File
@@ -638,6 +638,7 @@ enum BuildFlagKind {
BuildFlag_StrictStyleInitOnly,
BuildFlag_ForeignErrorProcedures,
BuildFlag_DisallowRTTI,
BuildFlag_UseStaticMapCalls,
BuildFlag_Compact,
BuildFlag_GlobalDefinitions,
@@ -814,6 +815,8 @@ bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_DisallowRTTI, str_lit("disallow-rtti"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_UseStaticMapCalls, str_lit("use-static-map-calls"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_Compact, str_lit("compact"), BuildFlagParam_None, Command_query);
add_flag(&build_flags, BuildFlag_GlobalDefinitions, str_lit("global-definitions"), BuildFlagParam_None, Command_query);
@@ -1414,6 +1417,9 @@ bool parse_build_flags(Array<String> args) {
case BuildFlag_DisallowRTTI:
build_context.disallow_rtti = true;
break;
case BuildFlag_UseStaticMapCalls:
build_context.use_static_map_calls = true;
break;
case BuildFlag_DefaultToNilAllocator:
build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR = true;
break;
+15 -16
View File
@@ -226,8 +226,6 @@ struct TypeProc {
TYPE_KIND(Map, struct { \
Type *key; \
Type *value; \
Type *entry_type; \
Type *internal_type; \
Type *lookup_result_type; \
}) \
TYPE_KIND(Struct, TypeStruct) \
@@ -685,13 +683,18 @@ gb_global Type *t_allocator_error = nullptr;
gb_global Type *t_source_code_location = nullptr;
gb_global Type *t_source_code_location_ptr = nullptr;
gb_global Type *t_map_hash = nullptr;
gb_global Type *t_map_header = nullptr;
gb_global Type *t_map_header_table = nullptr;
gb_global Type *t_map_info = nullptr;
gb_global Type *t_map_cell_info = nullptr;
gb_global Type *t_raw_map = nullptr;
gb_global Type *t_map_info_ptr = nullptr;
gb_global Type *t_map_cell_info_ptr = nullptr;
gb_global Type *t_raw_map_ptr = nullptr;
gb_global Type *t_equal_proc = nullptr;
gb_global Type *t_hasher_proc = nullptr;
gb_global Type *t_map_get_proc = nullptr;
gb_global Type *t_map_set_proc = nullptr;
gb_global Type *t_objc_object = nullptr;
gb_global Type *t_objc_selector = nullptr;
@@ -1926,7 +1929,7 @@ bool is_type_valid_for_keys(Type *t) {
if (is_type_untyped(t)) {
return false;
}
return is_type_comparable(t);
return type_size_of(t) > 0 && is_type_comparable(t);
}
bool is_type_valid_bit_set_elem(Type *t) {
@@ -3333,8 +3336,6 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
}
}
} else if (type->kind == Type_DynamicArray) {
// IMPORTANT TODO(bill): Should these members be available to should I only allow them with
// `Raw_Dynamic_Array` type?
GB_ASSERT(t_allocator != nullptr);
String allocator_str = str_lit("allocator");
gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 3);
@@ -3345,15 +3346,12 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
return sel;
}
} else if (type->kind == Type_Map) {
// IMPORTANT TODO(bill): Should these members be available to should I only allow them with
// `Raw_Map` type?
GB_ASSERT(t_allocator != nullptr);
String allocator_str = str_lit("allocator");
gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 3);
gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 2);
if (field_name == allocator_str) {
selection_add_index(&sel, 1);
selection_add_index(&sel, 3);
selection_add_index(&sel, 2);
sel.entity = entity__allocator;
return sel;
}
@@ -3798,11 +3796,12 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
case Type_Map:
/*
struct {
hashes: []int, // 2 words
entries: [dynamic]Entry_Type, // 5 words
data: uintptr, // 1 word
size: uintptr, // 1 word
allocator: runtime.Allocator, // 2 words
}
*/
return (2 + (3 + 2))*build_context.word_size;
return (1 + 1 + 2)*build_context.word_size;
case Type_Tuple: {
i64 count, align, size;