mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-17 08:34:08 +00:00
This commit is contained in:
@@ -63,7 +63,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
|
||||
// an extra allocation
|
||||
ArrayOperand operands = {0};
|
||||
array_init_reserve(&operands, c->tmp_allocator, 2*lhs_count);
|
||||
check_unpack_arguments(c, &operands, inits);
|
||||
check_unpack_arguments(c, lhs_count, &operands, inits, true);
|
||||
|
||||
isize rhs_count = operands.count;
|
||||
for_array(i, operands) {
|
||||
|
||||
@@ -1097,8 +1097,8 @@ Type *make_map_tuple_type(gbAllocator a, Type *value) {
|
||||
Type *t = make_type_tuple(a);
|
||||
t->Tuple.variables = gb_alloc_array(a, Entity *, 2);
|
||||
t->Tuple.variable_count = 2;
|
||||
t->Tuple.variables[0] = make_entity_param(a, NULL, blank_token, value, false, false);
|
||||
t->Tuple.variables[1] = make_entity_param(a, NULL, blank_token, t_bool, false, false);
|
||||
t->Tuple.variables[0] = make_entity_field(a, NULL, blank_token, value, false, 0);
|
||||
t->Tuple.variables[1] = make_entity_field(a, NULL, blank_token, t_bool, false, 1);
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -1132,11 +1132,17 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
|
||||
gbAllocator a = c->allocator;
|
||||
|
||||
{
|
||||
// NOTE(bill): The preload types may have not been set yet
|
||||
if (t_map_key == NULL) {
|
||||
init_preload(c);
|
||||
}
|
||||
GB_ASSERT(t_map_key != NULL);
|
||||
|
||||
Type *entry_type = make_type_struct(a);
|
||||
|
||||
/*
|
||||
struct {
|
||||
hash: u64,
|
||||
hash: Map_Key,
|
||||
next: int,
|
||||
key: Key_Type,
|
||||
value: Value_Type,
|
||||
@@ -1148,9 +1154,9 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
|
||||
|
||||
isize field_count = 3;
|
||||
Entity **fields = gb_alloc_array(a, Entity *, field_count);
|
||||
fields[0] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("key")), t_u64, false, false);
|
||||
fields[1] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("next")), t_int, false, false);
|
||||
fields[2] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("value")), value, false, false);
|
||||
fields[0] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("key")), t_map_key, false, 0);
|
||||
fields[1] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("next")), t_int, false, 1);
|
||||
fields[2] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("value")), value, false, 2);
|
||||
|
||||
check_close_scope(c);
|
||||
|
||||
@@ -1159,7 +1165,6 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
|
||||
entry_type->Record.field_count = field_count;
|
||||
|
||||
type_set_offsets(c->sizes, a, entry_type);
|
||||
|
||||
type->Map.entry_type = entry_type;
|
||||
}
|
||||
|
||||
@@ -1181,8 +1186,8 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
|
||||
|
||||
isize field_count = 2;
|
||||
Entity **fields = gb_alloc_array(a, Entity *, field_count);
|
||||
fields[0] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("hashes")), hashes_type, false, false);
|
||||
fields[1] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("entries")), entries_type, false, false);
|
||||
fields[0] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("hashes")), hashes_type, false, 0);
|
||||
fields[1] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("entries")), entries_type, false, 1);
|
||||
|
||||
check_close_scope(c);
|
||||
|
||||
@@ -1191,7 +1196,6 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
|
||||
generated_struct_type->Record.field_count = field_count;
|
||||
|
||||
type_set_offsets(c->sizes, a, generated_struct_type);
|
||||
|
||||
type->Map.generated_struct_type = generated_struct_type;
|
||||
}
|
||||
|
||||
@@ -2676,7 +2680,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
|
||||
gbString op_str = expr_to_string(op_expr);
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
gbString sel_str = expr_to_string(selector);
|
||||
error_node(op_expr, "`%s` (`%s`) has no field `%s`", op_str, type_str, sel_str);
|
||||
error_node(op_expr, "`%s` of type `%s` has no field `%s`", op_str, type_str, sel_str);
|
||||
gb_string_free(sel_str);
|
||||
gb_string_free(type_str);
|
||||
gb_string_free(op_str);
|
||||
@@ -2885,14 +2889,14 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
Type *type = operand->type;
|
||||
if (!is_type_pointer(type)) {
|
||||
gbString str = type_to_string(type);
|
||||
error_node(operand->expr, "Expected a pointer to a dynamic array, got `%s`", str);
|
||||
error_node(operand->expr, "Expected a pointer, got `%s`", str);
|
||||
gb_string_free(str);
|
||||
return false;
|
||||
}
|
||||
type = type_deref(type);
|
||||
if (!is_type_dynamic_array(type)) {
|
||||
if (!is_type_dynamic_array(type) && !is_type_map(type)) {
|
||||
gbString str = type_to_string(type);
|
||||
error_node(operand->expr, "Expected a pointer to a dynamic array, got `%s`", str);
|
||||
error_node(operand->expr, "Expected a pointer to a map or dynamic array, got `%s`", str);
|
||||
gb_string_free(str);
|
||||
return false;
|
||||
}
|
||||
@@ -3824,18 +3828,28 @@ int valid_proc_and_score_cmp(void const *a, void const *b) {
|
||||
|
||||
typedef Array(Operand) ArrayOperand;
|
||||
|
||||
void check_unpack_arguments(Checker *c, ArrayOperand *operands, AstNodeArray args) {
|
||||
void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, AstNodeArray args, bool allow_map_ok) {
|
||||
for_array(i, args) {
|
||||
Operand o = {0};
|
||||
check_multi_expr(c, &o, args.e[i]);
|
||||
|
||||
if (o.mode == Addressing_MapIndex) {
|
||||
Type *tuple_type = make_map_tuple_type(c->allocator, o.type);
|
||||
add_type_and_value(&c->info, o.expr, o.mode, tuple_type, (ExactValue){0});
|
||||
o.type = tuple_type;
|
||||
}
|
||||
|
||||
if (o.type == NULL || o.type->kind != Type_Tuple) {
|
||||
if (o.mode == Addressing_MapIndex &&
|
||||
allow_map_ok &&
|
||||
lhs_count == 2 &&
|
||||
args.count == 1) {
|
||||
Type *tuple = make_map_tuple_type(c->allocator, o.type);
|
||||
add_type_and_value(&c->info, o.expr, o.mode, tuple, o.value);
|
||||
|
||||
Operand val = o;
|
||||
Operand ok = o;
|
||||
val.mode = Addressing_Value;
|
||||
ok.mode = Addressing_Value;
|
||||
ok.type = t_bool;
|
||||
array_add(operands, val);
|
||||
array_add(operands, ok);
|
||||
continue;
|
||||
}
|
||||
array_add(operands, o);
|
||||
} else {
|
||||
TypeTuple *tuple = &o.type->Tuple;
|
||||
@@ -3854,7 +3868,7 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
||||
|
||||
ArrayOperand operands;
|
||||
array_init_reserve(&operands, heap_allocator(), 2*ce->args.count);
|
||||
check_unpack_arguments(c, &operands, ce->args);
|
||||
check_unpack_arguments(c, -1, &operands, ce->args, false);
|
||||
|
||||
if (operand->mode == Addressing_Overload) {
|
||||
GB_ASSERT(operand->overload_entities != NULL &&
|
||||
@@ -4740,6 +4754,31 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type_Map: {
|
||||
if (cl->elems.count == 0) {
|
||||
break;
|
||||
}
|
||||
is_constant = false;
|
||||
{ // Checker values
|
||||
for_array(i, cl->elems) {
|
||||
AstNode *elem = cl->elems.e[i];
|
||||
if (elem->kind != AstNode_FieldValue) {
|
||||
error_node(elem, "Only `field = value` elements are allowed in a map literal");
|
||||
continue;
|
||||
}
|
||||
ast_node(fv, FieldValue, elem);
|
||||
check_expr_with_type_hint(c, o, fv->field, t->Map.key);
|
||||
check_assignment(c, o, t->Map.key, str_lit("map literal"));
|
||||
if (o->mode == Addressing_Invalid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
check_expr_with_type_hint(c, o, fv->value, t->Map.value);
|
||||
check_assignment(c, o, t->Map.value, str_lit("map literal"));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
gbString str = type_to_string(type);
|
||||
error_node(node, "Invalid compound literal type `%s`", str);
|
||||
|
||||
@@ -256,11 +256,11 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
e->flags |= EntityFlag_Used;
|
||||
}
|
||||
|
||||
Type *assignment_type = op_b.type;
|
||||
switch (op_b.mode) {
|
||||
case Addressing_Invalid:
|
||||
return NULL;
|
||||
case Addressing_Variable:
|
||||
break;
|
||||
case Addressing_MapIndex:
|
||||
break;
|
||||
default: {
|
||||
@@ -287,7 +287,7 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
} break;
|
||||
}
|
||||
|
||||
check_assignment(c, op_a, op_b.type, str_lit("assignment"));
|
||||
check_assignment(c, op_a, assignment_type, str_lit("assignment"));
|
||||
if (op_a->mode == Addressing_Invalid) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -719,6 +719,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
val = t->Vector.elem;
|
||||
idx = t_int;
|
||||
break;
|
||||
|
||||
case Type_Map:
|
||||
val = t->Map.value;
|
||||
idx = t->Map.key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -958,6 +958,12 @@ void add_type_info_type(Checker *c, Type *t) {
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type_Map: {
|
||||
add_type_info_type(c, bt->Map.key);
|
||||
add_type_info_type(c, bt->Map.value);
|
||||
add_type_info_type(c, bt->Map.generated_struct_type);
|
||||
} break;
|
||||
|
||||
case Type_Tuple:
|
||||
for (isize i = 0; i < bt->Tuple.variable_count; i++) {
|
||||
Entity *var = bt->Tuple.variables[i];
|
||||
@@ -1093,7 +1099,7 @@ void init_preload(Checker *c) {
|
||||
|
||||
|
||||
|
||||
if (record->field_count != 19) {
|
||||
if (record->field_count != 20) {
|
||||
compiler_error("Invalid `Type_Info` layout");
|
||||
}
|
||||
t_type_info_named = record->fields[ 1]->type;
|
||||
@@ -1114,6 +1120,7 @@ void init_preload(Checker *c) {
|
||||
t_type_info_union = record->fields[16]->type;
|
||||
t_type_info_raw_union = record->fields[17]->type;
|
||||
t_type_info_enum = record->fields[18]->type;
|
||||
t_type_info_map = record->fields[19]->type;
|
||||
|
||||
t_type_info_named_ptr = make_type_pointer(heap_allocator(), t_type_info_named);
|
||||
t_type_info_integer_ptr = make_type_pointer(heap_allocator(), t_type_info_integer);
|
||||
@@ -1133,6 +1140,7 @@ void init_preload(Checker *c) {
|
||||
t_type_info_union_ptr = make_type_pointer(heap_allocator(), t_type_info_union);
|
||||
t_type_info_raw_union_ptr = make_type_pointer(heap_allocator(), t_type_info_raw_union);
|
||||
t_type_info_enum_ptr = make_type_pointer(heap_allocator(), t_type_info_enum);
|
||||
t_type_info_map_ptr = make_type_pointer(heap_allocator(), t_type_info_map);
|
||||
}
|
||||
|
||||
if (t_allocator == NULL) {
|
||||
@@ -1155,12 +1163,12 @@ void init_preload(Checker *c) {
|
||||
}
|
||||
|
||||
if (t_map_key == NULL) {
|
||||
Entity *e = find_core_entity(c, str_lit("Map_Key"));
|
||||
Entity *e = find_core_entity(c, str_lit("__Map_Key"));
|
||||
t_map_key = e->type;
|
||||
}
|
||||
|
||||
if (t_map_header == NULL) {
|
||||
Entity *e = find_core_entity(c, str_lit("Map_Header"));
|
||||
Entity *e = find_core_entity(c, str_lit("__Map_Header"));
|
||||
t_map_header = e->type;
|
||||
}
|
||||
|
||||
|
||||
57
src/gb/gb.h
57
src/gb/gb.h
@@ -58,6 +58,7 @@ TODOS
|
||||
- More date & time functions
|
||||
|
||||
VERSION HISTORY
|
||||
0.27 - OSX fixes and Linux gbAffinity
|
||||
0.26d - Minor changes to how gbFile works
|
||||
0.26c - gb_str_to_f* fix
|
||||
0.26b - Minor fixes
|
||||
@@ -4990,16 +4991,13 @@ isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) {
|
||||
}
|
||||
|
||||
#elif defined(GB_SYSTEM_LINUX)
|
||||
#warning gbAffinity is mostly mostly untested on Linux. All I know is that it compiles and runs.
|
||||
#warning TODO(bill): gb_affinity_set on Linux is a stub
|
||||
|
||||
// I have to read /proc/cpuinfo to get the number of threads per core.
|
||||
// IMPORTANT TODO(bill): This gbAffinity stuff for linux needs be improved a lot!
|
||||
// NOTE(zangent): I have to read /proc/cpuinfo to get the number of threads per core.
|
||||
#include <stdio.h>
|
||||
|
||||
void gb_affinity_init(gbAffinity *a) {
|
||||
usize count, count_size = gb_size_of(count);
|
||||
|
||||
b32 accurate = true;
|
||||
b32 accurate = true;
|
||||
isize threads = 0;
|
||||
|
||||
a->thread_count = 1;
|
||||
a->core_count = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
@@ -5012,37 +5010,43 @@ void gb_affinity_init(gbAffinity *a) {
|
||||
}
|
||||
|
||||
// Parsing /proc/cpuinfo to get the number of threads per core.
|
||||
// NOTE: This calls the CPU's threads "cores", although the wording
|
||||
// is kind of weird. This should be right, though.
|
||||
FILE* cpu_info = fopen("/proc/cpuinfo", "r");
|
||||
|
||||
int threads = 0;
|
||||
|
||||
if(cpu_info) {
|
||||
while(1) {
|
||||
// NOTE(zangent): This calls the CPU's threads "cores", although the wording
|
||||
// is kind of weird. This should be right, though.
|
||||
if (fopen("/proc/cpuinfo", "r") != NULL) {
|
||||
for (;;) {
|
||||
// The 'temporary char'. Everything goes into this char,
|
||||
// so that we can check against EOF at the end of this loop.
|
||||
char c;
|
||||
|
||||
#define check(letter) ((c = getc(cpu_info)) == letter)
|
||||
if(check('c') && check('p') && check('u') && check(' ') &&
|
||||
check('c') && check('o') && check('r') && check('e') && check('s')) {
|
||||
#define AF__CHECK(letter) ((c = getc(cpu_info)) == letter)
|
||||
if (AF__CHECK('c') && AF__CHECK('p') && AF__CHECK('u') && AF__CHECK(' ') &&
|
||||
AF__CHECK('c') && AF__CHECK('o') && AF__CHECK('r') && AF__CHECK('e') && AF__CHECK('s')) {
|
||||
// We're on a CPU info line.
|
||||
while(!check(EOF)) {
|
||||
if(c == '\n') break;
|
||||
else if(c < '0' || c > '9') continue;
|
||||
while (!AF__CHECK(EOF)) {
|
||||
if (c == '\n') {
|
||||
break;
|
||||
} else if (c < '0' || '9' > c) {
|
||||
continue;
|
||||
}
|
||||
threads = threads * 10 + (c - '0');
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
while(!check('\n')) {if(c==EOF) break;}
|
||||
while (!AF__CHECK('\n')) {
|
||||
if (c==EOF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(c == EOF) break;
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
#undef AF__CHECK
|
||||
}
|
||||
}
|
||||
|
||||
if(threads == 0) {
|
||||
threads = 1;
|
||||
if (threads == 0) {
|
||||
threads = 1;
|
||||
accurate = false;
|
||||
}
|
||||
|
||||
@@ -5062,7 +5066,8 @@ b32 gb_affinity_set(gbAffinity *a, isize core, isize thread_index) {
|
||||
}
|
||||
|
||||
isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) {
|
||||
GB_ASSERT(core >= 0 && core < a->core_count);
|
||||
|
||||
GB_ASSERT(0 <= core && core < a->core_count);
|
||||
return a->threads_per_core;
|
||||
}
|
||||
#else
|
||||
|
||||
275
src/ir.c
275
src/ir.c
@@ -372,6 +372,7 @@ typedef struct irAddr {
|
||||
struct {
|
||||
irValue *map_key;
|
||||
Type * map_type;
|
||||
Type * map_result;
|
||||
};
|
||||
};
|
||||
// union {
|
||||
@@ -384,10 +385,11 @@ irAddr ir_make_addr(irValue *addr) {
|
||||
return v;
|
||||
}
|
||||
|
||||
irAddr ir_make_addr_map(irValue *addr, irValue *map_key, Type *map_type) {
|
||||
irAddr ir_make_addr_map(irValue *addr, irValue *map_key, Type *map_type, Type *map_result) {
|
||||
irAddr v = {irAddr_Map, addr};
|
||||
v.map_key = map_key;
|
||||
v.map_type = map_type;
|
||||
v.map_key = map_key;
|
||||
v.map_type = map_type;
|
||||
v.map_result = map_result;
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -589,23 +591,6 @@ Type *ir_type(irValue *value) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Type *ir_addr_type(irAddr addr) {
|
||||
if (addr.addr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (addr.kind == irAddr_Map) {
|
||||
Type *t = base_type(addr.map_type);
|
||||
GB_ASSERT(is_type_map(t));
|
||||
return t->Map.value;
|
||||
}
|
||||
|
||||
Type *t = ir_type(addr.addr);
|
||||
GB_ASSERT(is_type_pointer(t));
|
||||
return type_deref(t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ir_is_blank_ident(AstNode *node) {
|
||||
if (node->kind == AstNode_Ident) {
|
||||
@@ -990,6 +975,9 @@ irValue *ir_make_const_i32(gbAllocator a, i64 i) {
|
||||
irValue *ir_make_const_i64(gbAllocator a, i64 i) {
|
||||
return ir_make_value_constant(a, t_i64, make_exact_value_integer(i));
|
||||
}
|
||||
irValue *ir_make_const_u64(gbAllocator a, u64 i) {
|
||||
return ir_make_value_constant(a, t_u64, make_exact_value_integer(i));
|
||||
}
|
||||
irValue *ir_make_const_f32(gbAllocator a, f32 f) {
|
||||
return ir_make_value_constant(a, t_f32, make_exact_value_float(f));
|
||||
}
|
||||
@@ -1398,12 +1386,16 @@ void ir_emit_startup_runtime(irProcedure *proc) {
|
||||
ir_emit(proc, ir_alloc_instr(proc, irInstr_StartupRuntime));
|
||||
}
|
||||
|
||||
irValue *ir_emit_bitcast(irProcedure *proc, irValue *data, Type *type) {
|
||||
return ir_emit(proc, ir_make_instr_conv(proc, irConv_bitcast, data, ir_type(data), type));
|
||||
}
|
||||
|
||||
|
||||
irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index);
|
||||
irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irValue *right);
|
||||
|
||||
irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val, Type *map_type) {
|
||||
GB_ASSERT(is_type_pointer(ir_type(map_val)));
|
||||
GB_ASSERT_MSG(is_type_pointer(ir_type(map_val)), "%s", type_to_string(ir_type(map_val)));
|
||||
gbAllocator a = proc->module->allocator;
|
||||
irValue *h = ir_add_local_generated(proc, t_map_header);
|
||||
|
||||
@@ -1431,17 +1423,43 @@ irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val, Type *map_type)
|
||||
return ir_emit_load(proc, h);
|
||||
}
|
||||
|
||||
irValue *ir_gen_map_key(irProcedure *proc, irValue *key) {
|
||||
irValue *ir_gen_map_key(irProcedure *proc, irValue *key, Type *key_type) {
|
||||
irValue *v = ir_add_local_generated(proc, t_map_key);
|
||||
irValue *hash = ir_emit_struct_ep(proc, v, 0);
|
||||
Type *t = base_type(ir_type(key));
|
||||
key = ir_emit_conv(proc, key, key_type);
|
||||
if (is_type_integer(t)) {
|
||||
ir_emit_store(proc, hash, ir_emit_conv(proc, key, t_u64));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, key, t_u64));
|
||||
} else if (is_type_pointer(t)) {
|
||||
irValue *p = ir_emit_conv(proc, key, t_uint);
|
||||
ir_emit_store(proc, hash, ir_emit_conv(proc, p, t_u64));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, p, t_u64));
|
||||
} else if (is_type_float(t)) {
|
||||
irValue *bits = NULL;
|
||||
i64 size = type_size_of(proc->module->sizes, proc->module->allocator, t);
|
||||
switch (8*size) {
|
||||
case 32: bits = ir_emit_bitcast(proc, key, t_u32); break;
|
||||
case 64: bits = ir_emit_bitcast(proc, key, t_u64); break;
|
||||
default: GB_PANIC("Unhandled float size: %lld bits", size); break;
|
||||
}
|
||||
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, bits, t_u64));
|
||||
} else if (is_type_string(t)) {
|
||||
irValue *str = ir_emit_conv(proc, key, t_string);
|
||||
irValue *hashed_str = NULL;
|
||||
|
||||
if (str->kind == irValue_Constant) {
|
||||
ExactValue ev = str->Constant.value;
|
||||
GB_ASSERT(ev.kind == ExactValue_String);
|
||||
u64 hs = gb_fnv64a(ev.value_string.text, ev.value_string.len);
|
||||
hashed_str = ir_make_const_u64(proc->module->allocator, hs);
|
||||
} else {
|
||||
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 1);
|
||||
args[0] = str;
|
||||
hashed_str = ir_emit_global_call(proc, "__default_hash_string", args, 1);
|
||||
}
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), hashed_str);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 1), str);
|
||||
} else {
|
||||
GB_PANIC("TODO(bill): Map Key type");
|
||||
GB_PANIC("Unhandled map key type");
|
||||
}
|
||||
|
||||
return ir_emit_load(proc, v);
|
||||
@@ -1461,35 +1479,51 @@ irValue *ir_address_from_load_or_generate_local(irProcedure *proc, irValue *val)
|
||||
}
|
||||
|
||||
|
||||
Type *ir_addr_type(irAddr addr) {
|
||||
if (addr.addr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (addr.kind == irAddr_Map) {
|
||||
Type *t = base_type(addr.map_type);
|
||||
GB_ASSERT(is_type_map(t));
|
||||
return t->Map.value;
|
||||
}
|
||||
|
||||
Type *t = ir_type(addr.addr);
|
||||
GB_ASSERT(is_type_pointer(t));
|
||||
return type_deref(t);
|
||||
}
|
||||
|
||||
irValue *ir_insert_dynamic_map_key_and_value(irProcedure *proc, irValue *addr, Type *map_type,
|
||||
irValue *map_key, irValue *map_value) {
|
||||
map_type = base_type(map_type);
|
||||
|
||||
irValue *h = ir_gen_map_header(proc, addr, map_type);
|
||||
irValue *key = ir_gen_map_key(proc, map_key, map_type->Map.key);
|
||||
irValue *v = ir_emit_conv(proc, map_value, map_type->Map.value);
|
||||
irValue *ptr = ir_address_from_load_or_generate_local(proc, v);
|
||||
ptr = ir_emit_conv(proc, ptr, t_rawptr);
|
||||
|
||||
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 3);
|
||||
args[0] = h;
|
||||
args[1] = key;
|
||||
args[2] = ptr;
|
||||
|
||||
return ir_emit_global_call(proc, "__dynamic_map_set", args, 3);
|
||||
}
|
||||
|
||||
|
||||
irValue *ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) {
|
||||
if (addr.addr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (addr.kind == irAddr_Map) {
|
||||
Type *map_type = base_type(addr.map_type);
|
||||
irValue *h = ir_gen_map_header(proc, addr.addr, map_type);
|
||||
irValue *key = ir_gen_map_key(proc, addr.map_key);
|
||||
irValue *ptr =ir_address_from_load_or_generate_local(proc, value);
|
||||
ptr = ir_emit_conv(proc, ptr, t_rawptr);
|
||||
|
||||
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 3);
|
||||
args[0] = h;
|
||||
args[1] = key;
|
||||
args[2] = ptr;
|
||||
|
||||
return ir_emit_global_call(proc, "__dynamic_map_set", args, 3);
|
||||
return ir_insert_dynamic_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value);
|
||||
}
|
||||
|
||||
// if (addr.kind == irAddr_Vector) {
|
||||
// irValue *v = ir_emit_load(proc, addr.addr);
|
||||
// Type *elem_type = base_type(ir_type(v))->Vector.elem;
|
||||
// irValue *elem = ir_emit_conv(proc, value, elem_type);
|
||||
// irValue *out = ir_emit(proc, ir_make_instr_insert_element(proc, v, elem, addr.Vector.index));
|
||||
// return ir_emit_store(proc, addr.addr, out);
|
||||
// } else {
|
||||
irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr));
|
||||
return ir_emit_store(proc, addr.addr, v);
|
||||
// }
|
||||
irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr));
|
||||
return ir_emit_store(proc, addr.addr, v);
|
||||
}
|
||||
|
||||
irValue *ir_addr_load(irProcedure *proc, irAddr addr) {
|
||||
@@ -1503,7 +1537,7 @@ irValue *ir_addr_load(irProcedure *proc, irAddr addr) {
|
||||
Type *map_type = base_type(addr.map_type);
|
||||
irValue *v = ir_add_local_generated(proc, map_type->Map.lookup_result_type);
|
||||
irValue *h = ir_gen_map_header(proc, addr.addr, map_type);
|
||||
irValue *key = ir_gen_map_key(proc, addr.map_key);
|
||||
irValue *key = ir_gen_map_key(proc, addr.map_key, map_type->Map.key);
|
||||
|
||||
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 2);
|
||||
args[0] = h;
|
||||
@@ -1527,7 +1561,12 @@ irValue *ir_addr_load(irProcedure *proc, irAddr addr) {
|
||||
ir_start_block(proc, done);
|
||||
|
||||
|
||||
return ir_emit_load(proc, v);
|
||||
if (is_type_tuple(addr.map_result)) {
|
||||
return ir_emit_load(proc, v);
|
||||
} else {
|
||||
irValue *single = ir_emit_struct_ep(proc, v, 0);
|
||||
return ir_emit_load(proc, single);
|
||||
}
|
||||
}
|
||||
|
||||
// if (addr.kind == irAddr_Vector) {
|
||||
@@ -1886,6 +1925,13 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, Type *type, irValue *e, Selec
|
||||
e = ir_emit_array_epi(proc, e, index);
|
||||
} else if (type->kind == Type_Array) {
|
||||
e = ir_emit_array_epi(proc, e, index);
|
||||
} else if (type->kind == Type_Map) {
|
||||
e = ir_emit_struct_ep(proc, e, 1);
|
||||
switch (index) {
|
||||
case 0: e = ir_emit_struct_ep(proc, e, 1); break; // count
|
||||
case 1: e = ir_emit_struct_ep(proc, e, 2); break; // capacity
|
||||
case 2: e = ir_emit_struct_ep(proc, e, 3); break; // allocator
|
||||
}
|
||||
} else {
|
||||
GB_PANIC("un-gep-able type");
|
||||
}
|
||||
@@ -1912,6 +1958,13 @@ irValue *ir_emit_deep_field_ev(irProcedure *proc, Type *type, irValue *e, Select
|
||||
GB_PANIC("TODO(bill): IS THIS EVEN CORRECT?");
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ir_emit_conv(proc, e, type);
|
||||
} else if (type->kind == Type_Map) {
|
||||
e = ir_emit_struct_ev(proc, e, 1);
|
||||
switch (index) {
|
||||
case 0: e = ir_emit_struct_ev(proc, e, 1); break; // count
|
||||
case 1: e = ir_emit_struct_ev(proc, e, 2); break; // capacity
|
||||
case 2: e = ir_emit_struct_ev(proc, e, 3); break; // allocator
|
||||
}
|
||||
} else {
|
||||
e = ir_emit_struct_ev(proc, e, index);
|
||||
}
|
||||
@@ -2068,9 +2121,6 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
|
||||
return str_lit("");
|
||||
}
|
||||
|
||||
irValue *ir_emit_bitcast(irProcedure *proc, irValue *data, Type *type) {
|
||||
return ir_emit(proc, ir_make_instr_conv(proc, irConv_bitcast, data, ir_type(data), type));
|
||||
}
|
||||
|
||||
|
||||
irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
||||
@@ -2977,7 +3027,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
||||
|
||||
|
||||
case_ast_node(cl, CompoundLit, expr);
|
||||
return ir_emit_load(proc, ir_build_addr(proc, expr).addr);
|
||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||
case_end;
|
||||
|
||||
|
||||
@@ -3159,9 +3209,19 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
||||
|
||||
case BuiltinProc_clear: {
|
||||
ir_emit_comment(proc, str_lit("reserve"));
|
||||
irValue *array_ptr = ir_build_expr(proc, ce->args.e[0]);
|
||||
irValue *count_ptr = ir_emit_struct_ep(proc, array_ptr, 1);
|
||||
ir_emit_store(proc, count_ptr, v_zero);
|
||||
irValue *ptr = ir_build_expr(proc, ce->args.e[0]);
|
||||
Type *t = base_type(type_deref(ir_type(ptr)));
|
||||
if (is_type_dynamic_array(t)) {
|
||||
irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1);
|
||||
ir_emit_store(proc, count_ptr, v_zero);
|
||||
} else if (is_type_dynamic_map(t)) {
|
||||
irValue *ha = ir_emit_struct_ep(proc, ptr, 0);
|
||||
irValue *ea = ir_emit_struct_ep(proc, ptr, 1);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, ha, 1), v_zero);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, ea, 1), v_zero);
|
||||
} else {
|
||||
GB_PANIC("TODO(bill): ir clear for `%s`", type_to_string(t));
|
||||
}
|
||||
return NULL;
|
||||
} break;
|
||||
|
||||
@@ -3537,11 +3597,11 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
||||
case_end;
|
||||
|
||||
case_ast_node(de, DemaybeExpr, expr);
|
||||
return ir_emit_load(proc, ir_build_addr(proc, expr).addr);
|
||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||
case_end;
|
||||
|
||||
case_ast_node(se, SliceExpr, expr);
|
||||
return ir_emit_load(proc, ir_build_addr(proc, expr).addr);
|
||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||
case_end;
|
||||
|
||||
case_ast_node(ie, IndexExpr, expr);
|
||||
@@ -3764,21 +3824,17 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
Type *t = base_type(type_of_expr(proc->module->info, ie->expr));
|
||||
gbAllocator a = proc->module->allocator;
|
||||
|
||||
|
||||
bool deref = is_type_pointer(t);
|
||||
t = base_type(type_deref(t));
|
||||
|
||||
if (is_type_map(t)) {
|
||||
irAddr map_addr = ir_build_addr(proc, ie->expr);
|
||||
irValue *map_val = map_addr.addr;
|
||||
if (deref) {
|
||||
map_val = ir_addr_load(proc, map_addr);
|
||||
}
|
||||
|
||||
irValue *key = ir_build_expr(proc, ie->index);
|
||||
key = ir_emit_conv(proc, key, t->Map.key);
|
||||
|
||||
return ir_make_addr_map(map_val, key, t);
|
||||
Type *result_type = type_of_expr(proc->module->info, expr);
|
||||
return ir_make_addr_map(map_val, key, t, result_type);
|
||||
}
|
||||
|
||||
irValue *using_addr = NULL;
|
||||
@@ -4127,6 +4183,28 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type_Map: {
|
||||
if (cl->elems.count == 0) {
|
||||
break;
|
||||
}
|
||||
gbAllocator a = proc->module->allocator;
|
||||
{
|
||||
irValue **args = gb_alloc_array(a, irValue *, 4);
|
||||
args[0] = ir_gen_map_header(proc, v, type);
|
||||
args[1] = ir_make_const_int(a, 2*cl->elems.count);
|
||||
ir_emit_global_call(proc, "__dynamic_map_reserve", args, 2);
|
||||
}
|
||||
for_array(field_index, cl->elems) {
|
||||
AstNode *elem = cl->elems.e[field_index];
|
||||
ast_node(fv, FieldValue, elem);
|
||||
|
||||
irValue *key = ir_build_expr(proc, fv->field);
|
||||
irValue *value = ir_build_expr(proc, fv->value);
|
||||
ir_insert_dynamic_map_key_and_value(proc, v, type, key, value);
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type_Array: {
|
||||
if (cl->elems.count > 0) {
|
||||
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
|
||||
@@ -4346,6 +4424,7 @@ void ir_emit_increment(irProcedure *proc, irValue *addr) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, irValue *count_ptr,
|
||||
irValue **val_, irValue **idx_, irBlock **loop_, irBlock **done_) {
|
||||
irValue *count = NULL;
|
||||
@@ -4365,6 +4444,11 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir
|
||||
irBlock *done = NULL;
|
||||
irBlock *body = NULL;
|
||||
|
||||
irValue *key = NULL;
|
||||
if (expr_type->kind == Type_Map) {
|
||||
key = ir_add_local_generated(proc, expr_type->Map.key);
|
||||
}
|
||||
|
||||
irValue *index = ir_add_local_generated(proc, t_int);
|
||||
ir_emit_store(proc, index, ir_make_const_int(proc->module->allocator, -1));
|
||||
|
||||
@@ -4401,6 +4485,26 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir
|
||||
irValue *elem = ir_emit_struct_ep(proc, expr, 0);
|
||||
elem = ir_emit_load(proc, elem);
|
||||
val = ir_emit_load(proc, ir_emit_ptr_offset(proc, elem, idx));
|
||||
} break;
|
||||
case Type_Map: {
|
||||
irValue *entries = ir_emit_struct_ep(proc, expr, 1);
|
||||
irValue *elem = ir_emit_struct_ep(proc, entries, 0);
|
||||
elem = ir_emit_load(proc, elem);
|
||||
|
||||
irValue *entry = ir_emit_ptr_offset(proc, elem, idx);
|
||||
val = ir_emit_load(proc, ir_emit_struct_ep(proc, entry, 2));
|
||||
|
||||
irValue *hash = ir_emit_struct_ep(proc, entry, 0);
|
||||
if (is_type_string(expr_type->Map.key)) {
|
||||
irValue *str = ir_emit_struct_ep(proc, hash, 1);
|
||||
ir_emit_store(proc, key, ir_emit_load(proc, str));
|
||||
} else {
|
||||
irValue *hash_ptr = ir_emit_struct_ep(proc, hash, 0);
|
||||
hash_ptr = ir_emit_conv(proc, hash_ptr, ir_type(key));
|
||||
ir_emit_store(proc, key, ir_emit_load(proc, hash_ptr));
|
||||
}
|
||||
|
||||
|
||||
} break;
|
||||
default:
|
||||
GB_PANIC("Cannot do range_indexed of %s", type_to_string(expr_type));
|
||||
@@ -4408,6 +4512,10 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir
|
||||
}
|
||||
}
|
||||
|
||||
if (key != NULL) {
|
||||
idx = ir_emit_load(proc, key);
|
||||
}
|
||||
|
||||
if (val_) *val_ = val;
|
||||
if (idx_) *idx_ = idx;
|
||||
if (loop_) *loop_ = loop;
|
||||
@@ -4598,8 +4706,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
if (lvals.e[i].addr == NULL) {
|
||||
continue;
|
||||
}
|
||||
irValue *v = ir_emit_conv(proc, inits.e[i], ir_addr_type(lvals.e[i]));
|
||||
ir_addr_store(proc, lvals.e[i], v);
|
||||
ir_addr_store(proc, lvals.e[i], inits.e[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4957,6 +5064,16 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
Type *expr_type = type_of_expr(proc->module->info, rs->expr);
|
||||
Type *et = base_type(type_deref(expr_type));
|
||||
switch (et->kind) {
|
||||
case Type_Map: {
|
||||
irAddr addr = ir_build_addr(proc, rs->expr);
|
||||
irValue *map = addr.addr;
|
||||
if (is_type_pointer(type_deref(ir_addr_type(addr)))) {
|
||||
map = ir_addr_load(proc, addr);
|
||||
}
|
||||
irValue *entries_ptr = ir_emit_struct_ep(proc, map, 1);
|
||||
irValue *count_ptr = ir_emit_struct_ep(proc, entries_ptr, 1);
|
||||
ir_build_range_indexed(proc, map, val_type, count_ptr, &val, &index, &loop, &done);
|
||||
} break;
|
||||
case Type_Array: {
|
||||
irValue *count_ptr = NULL;
|
||||
irValue *array = ir_build_addr(proc, rs->expr).addr;
|
||||
@@ -6164,14 +6281,16 @@ void ir_gen_tree(irGen *s) {
|
||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_struct_ptr);
|
||||
|
||||
{
|
||||
irValue *packed = ir_make_const_bool(a, t->Record.struct_is_packed);
|
||||
irValue *ordered = ir_make_const_bool(a, t->Record.struct_is_ordered);
|
||||
irValue *size = ir_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||
irValue *align = ir_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||
irValue *size = ir_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||
irValue *align = ir_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||
irValue *packed = ir_make_const_bool(a, t->Record.struct_is_packed);
|
||||
irValue *ordered = ir_make_const_bool(a, t->Record.struct_is_ordered);
|
||||
irValue *custom_align = ir_make_const_bool(a, t->Record.custom_align);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), size);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), align);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), packed);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 4), ordered);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 5), custom_align);
|
||||
}
|
||||
|
||||
irValue *memory = ir_type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
|
||||
@@ -6394,6 +6513,20 @@ void ir_gen_tree(irGen *s) {
|
||||
|
||||
// TODO(bill): Type_Info for procedures
|
||||
} break;
|
||||
|
||||
case Type_Map: {
|
||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_map_ptr);
|
||||
|
||||
irValue *key = ir_emit_struct_ep(proc, tag, 0);
|
||||
irValue *value = ir_emit_struct_ep(proc, tag, 1);
|
||||
irValue *generated_struct = ir_emit_struct_ep(proc, tag, 2);
|
||||
irValue *count = ir_emit_struct_ep(proc, tag, 3);
|
||||
|
||||
ir_emit_store(proc, key, ir_get_type_info_ptr(proc, type_info_data, t->Map.key));
|
||||
ir_emit_store(proc, value, ir_get_type_info_ptr(proc, type_info_data, t->Map.value));
|
||||
ir_emit_store(proc, generated_struct, ir_get_type_info_ptr(proc, type_info_data, t->Map.generated_struct_type));
|
||||
ir_emit_store(proc, count, ir_make_const_int(a, t->Map.count));
|
||||
} break;
|
||||
}
|
||||
|
||||
if (tag != NULL) {
|
||||
|
||||
@@ -1854,6 +1854,7 @@ bool is_literal_type(AstNode *node) {
|
||||
case AstNode_ArrayType:
|
||||
case AstNode_VectorType:
|
||||
case AstNode_StructType:
|
||||
case AstNode_MapType:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
52
src/types.c
52
src/types.c
@@ -300,6 +300,7 @@ gb_global Type *t_type_info_struct = NULL;
|
||||
gb_global Type *t_type_info_union = NULL;
|
||||
gb_global Type *t_type_info_raw_union = NULL;
|
||||
gb_global Type *t_type_info_enum = NULL;
|
||||
gb_global Type *t_type_info_map = NULL;
|
||||
|
||||
|
||||
gb_global Type *t_type_info_named_ptr = NULL;
|
||||
@@ -320,6 +321,7 @@ gb_global Type *t_type_info_struct_ptr = NULL;
|
||||
gb_global Type *t_type_info_union_ptr = NULL;
|
||||
gb_global Type *t_type_info_raw_union_ptr = NULL;
|
||||
gb_global Type *t_type_info_enum_ptr = NULL;
|
||||
gb_global Type *t_type_info_map_ptr = NULL;
|
||||
|
||||
|
||||
|
||||
@@ -921,6 +923,14 @@ bool are_types_identical(Type *x, Type *y) {
|
||||
are_types_identical(x->Proc.results, y->Proc.results);
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Map:
|
||||
if (y->kind == Type_Map) {
|
||||
return x->Map.count == y->Map.count &&
|
||||
are_types_identical(x->Map.key, y->Map.key) &&
|
||||
are_types_identical(x->Map.value, y->Map.value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1073,6 +1083,10 @@ gb_global Entity *entity__dynamic_array_count = NULL;
|
||||
gb_global Entity *entity__dynamic_array_capacity = NULL;
|
||||
gb_global Entity *entity__dynamic_array_allocator = NULL;
|
||||
|
||||
gb_global Entity *entity__dynamic_map_count = NULL;
|
||||
gb_global Entity *entity__dynamic_map_capacity = NULL;
|
||||
gb_global Entity *entity__dynamic_map_allocator = NULL;
|
||||
|
||||
Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel);
|
||||
|
||||
Selection lookup_field(gbAllocator a, Type *type_, String field_name, bool is_type) {
|
||||
@@ -1240,7 +1254,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
||||
sel.entity = entity__slice_count;
|
||||
return sel;
|
||||
}
|
||||
} else if (type->kind == Type_DynamicArray) {
|
||||
} else if (type->kind == Type_DynamicArray) {
|
||||
String data_str = str_lit("data");
|
||||
String count_str = str_lit("count");
|
||||
String capacity_str = str_lit("capacity");
|
||||
@@ -1273,6 +1287,36 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
||||
sel.entity = entity__dynamic_array_allocator;
|
||||
return sel;
|
||||
}
|
||||
} else if (type->kind == Type_Map) {
|
||||
String count_str = str_lit("count");
|
||||
String capacity_str = str_lit("capacity");
|
||||
String allocator_str = str_lit("allocator");
|
||||
|
||||
if (str_eq(field_name, count_str)) {
|
||||
selection_add_index(&sel, 0);
|
||||
if (entity__dynamic_map_count == NULL) {
|
||||
entity__dynamic_map_count = make_entity_field(a, NULL, make_token_ident(count_str), t_int, false, 0);
|
||||
entity__dynamic_map_count->Variable.is_immutable = true;
|
||||
}
|
||||
sel.entity = entity__dynamic_map_count;
|
||||
return sel;
|
||||
} else if (str_eq(field_name, capacity_str)) {
|
||||
selection_add_index(&sel, 1);
|
||||
if (entity__dynamic_map_capacity == NULL) {
|
||||
entity__dynamic_map_capacity = make_entity_field(a, NULL, make_token_ident(capacity_str), t_int, false, 1);
|
||||
entity__dynamic_map_capacity->Variable.is_immutable = true;
|
||||
}
|
||||
sel.entity = entity__dynamic_map_capacity;
|
||||
return sel;
|
||||
} else if (str_eq(field_name, allocator_str)) {
|
||||
selection_add_index(&sel, 2);
|
||||
if (entity__dynamic_map_allocator == NULL) {
|
||||
entity__dynamic_map_allocator = make_entity_field(a, NULL, make_token_ident(allocator_str), t_allocator, false, 2);
|
||||
entity__dynamic_map_allocator->Variable.is_immutable = true;
|
||||
}
|
||||
sel.entity = entity__dynamic_map_allocator;
|
||||
return sel;
|
||||
}
|
||||
}
|
||||
|
||||
if (type->kind != Type_Record) {
|
||||
@@ -1527,8 +1571,7 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type
|
||||
|
||||
case Type_Map: {
|
||||
if (t->Map.count == 0) { // Dynamic
|
||||
// NOTE(bill): same as a dynamic array
|
||||
return s.word_size;
|
||||
return type_align_of_internal(s, allocator, t->Map.generated_struct_type, path);
|
||||
}
|
||||
GB_PANIC("TODO(bill): Fixed map alignment");
|
||||
} break;
|
||||
@@ -1744,8 +1787,7 @@ i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypeP
|
||||
|
||||
case Type_Map: {
|
||||
if (t->Map.count == 0) { // Dynamic
|
||||
// NOTE(bill): same as a two dynamic arrays
|
||||
return 2 * type_size_of_internal(s, allocator, t_raw_dynamic_array, path);
|
||||
return type_size_of_internal(s, allocator, t->Map.generated_struct_type, path);
|
||||
}
|
||||
GB_PANIC("TODO(bill): Fixed map size");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user