From c126339090a57ab29a2c75d3ee79333cf3c88278 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Mon, 6 Feb 2017 20:23:51 +0000 Subject: [PATCH] dynamic `map` insertion and lookup --- code/demo.odin | 7 +++--- core/_preload.odin | 15 +++++++----- src/check_expr.c | 8 +------ src/check_stmt.c | 10 +++++--- src/ir.c | 60 ++++++++++++++++++++++++++-------------------- 5 files changed, 55 insertions(+), 45 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index e3e85769c..d44f7dca3 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -11,11 +11,12 @@ main :: proc() { - Value :: type f32; - m: map[int]Value; + m: map[int]u32; reserve(^m, 16); defer free(m); - // m[123] = 345.0; + + m[123] = 345; + fmt.println(m[123]); if x, ok := m[123]; ok { fmt.println(x); } diff --git a/core/_preload.odin b/core/_preload.odin index 18a7a4438..1fb821fea 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -511,25 +511,27 @@ __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int) { __dynamic_map_grow(new_header); } } - free(header.m); + free_ptr_with_allocator(header.m.hashes.allocator, header.m.hashes.data); + free_ptr_with_allocator(header.m.entries.allocator, header.m.entries.data); header.m^ = nm; - } __dynamic_map_get :: proc(h: Map_Header, key: Map_Key) -> rawptr { index := __dynamic_map_find(h, key).entry_index; if index >= 0 { data := cast(^byte)__dynamic_map_get_entry(h, index); - return data + h.value_offset; + val := data + h.value_offset; + return val; } return nil; } __dynamic_map_set :: proc(using h: Map_Header, key: Map_Key, value: rawptr) { + index: int; + if m.hashes.count == 0 { __dynamic_map_grow(h); } - index: int; fr := __dynamic_map_find(h, key); if fr.entry_index >= 0 { index = fr.entry_index; @@ -544,7 +546,8 @@ __dynamic_map_set :: proc(using h: Map_Header, key: Map_Key, value: rawptr) { } { data := cast(^byte)__dynamic_map_get_entry(h, index); - mem.copy(data+value_offset, value, entry_size-value_offset); + val := data+value_offset; + mem.copy(val, value, entry_size-value_offset); } if __dynamic_map_full(h) { @@ -598,7 +601,7 @@ __dynamic_map_add_entry :: proc(using h: Map_Header, key: Map_Key) -> int { end.key = key; end.next = -1; } - return c; + return prev; } diff --git a/src/check_expr.c b/src/check_expr.c index 55563cb2d..20b041e08 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -3829,12 +3829,6 @@ void check_unpack_arguments(Checker *c, ArrayOperand *operands, AstNodeArray arg 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) { array_add(operands, o); } else { @@ -4997,7 +4991,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint goto error; } o->mode = Addressing_MapIndex; - o->type = t->Map.value; + o->type = make_map_tuple_type(c->allocator, t->Map.value); o->expr = node; return Expr_Expr; } diff --git a/src/check_stmt.c b/src/check_stmt.c index 9b26adc5d..489b97fb4 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -256,13 +256,17 @@ 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; + case Addressing_MapIndex: { + Type *t = base_type(assignment_type); GB_ASSERT(is_type_tuple(t)); + t = t->Tuple.variables[0]->type; + assignment_type = t; + } break; default: { if (op_b.expr->kind == AstNode_SelectorExpr) { // NOTE(bill): Extra error checks @@ -287,7 +291,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; } diff --git a/src/ir.c b/src/ir.c index 8c3767d91..d5f52a27a 100644 --- a/src/ir.c +++ b/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) { @@ -1461,6 +1446,23 @@ 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_addr_store(irProcedure *proc, irAddr addr, irValue *value) { if (addr.addr == NULL) { return NULL; @@ -1469,7 +1471,8 @@ irValue *ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) { 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); + irValue *v = ir_emit_conv(proc, 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); @@ -1487,7 +1490,7 @@ irValue *ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) { // 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)); + irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr)); return ir_emit_store(proc, addr.addr, v); // } } @@ -1527,7 +1530,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) { @@ -3778,7 +3786,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { 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; @@ -4598,8 +4607,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]); } }