diff options
| author | gingerBill <bill@gingerbill.org> | 2017-12-17 19:25:35 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2017-12-17 19:25:35 +0000 |
| commit | a69ea58388d498a227094f2cb2f0083c620c9ac7 (patch) | |
| tree | 31e50ae17aeabe7f592989d16937eb9bd5205cef /src | |
| parent | 30530d058ca22eea3dcb0401a6bd6d288deb3ce0 (diff) | |
`map` is internally backed by a pointer (i.e. a "reference type")
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_type.cpp | 3 | ||||
| -rw-r--r-- | src/ir.cpp | 132 | ||||
| -rw-r--r-- | src/ir_print.cpp | 4 | ||||
| -rw-r--r-- | src/types.cpp | 19 |
4 files changed, 95 insertions, 63 deletions
diff --git a/src/check_type.cpp b/src/check_type.cpp index 6fee664d5..8374fd269 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1844,7 +1844,8 @@ void generate_map_internal_types(gbAllocator a, Type *type) { type_set_offsets(a, generated_struct_type); type->Map.generated_struct_type = generated_struct_type; - type->Map.lookup_result_type = make_optional_ok_type(a, value); + type->Map.internal_type = make_type_pointer(a, generated_struct_type); + type->Map.lookup_result_type = make_optional_ok_type(a, value); } void check_map_type(Checker *c, Type *type, AstNode *node) { diff --git a/src/ir.cpp b/src/ir.cpp index d88eac3f8..b50a98655 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1733,8 +1733,8 @@ void ir_emit_startup_runtime(irProcedure *proc) { 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_MSG(is_type_pointer(ir_type(map_val)), "%s", type_to_string(ir_type(map_val))); +irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val_ptr, Type *map_type) { + GB_ASSERT_MSG(is_type_pointer(ir_type(map_val_ptr)), "%s", type_to_string(ir_type(map_val_ptr))); gbAllocator a = proc->module->allocator; irValue *h = ir_add_local_generated(proc, t_map_header); map_type = base_type(map_type); @@ -1744,7 +1744,7 @@ irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val, Type *map_type) // NOTE(bill): Removes unnecessary allocation if split gep irValue *gep0 = ir_emit_struct_ep(proc, h, 0); - irValue *m = ir_emit_conv(proc, map_val, type_deref(ir_type(gep0))); + irValue *m = ir_emit_conv(proc, map_val_ptr, type_deref(ir_type(gep0))); ir_emit_store(proc, gep0, m); if (is_type_string(key_type)) { @@ -2536,14 +2536,18 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { case 2: result_type = t_int_ptr; break; case 3: result_type = t_allocator_ptr; break; } - } else if (is_type_map(t)) { + } /* else if (is_type_map(t)) { generate_map_internal_types(a, t); + Type *itp = make_type_pointer(a, t->Map.internal_type); + s = ir_emit_load(proc, ir_emit_transmute(proc, s, itp)); + Type *gst = t->Map.generated_struct_type; + GB_ASSERT(gst->kind == Type_Struct); switch (index) { case 0: result_type = make_type_pointer(a, gst->Struct.fields[0]->type); break; case 1: result_type = make_type_pointer(a, gst->Struct.fields[1]->type); break; } - }else { + } */else { GB_PANIC("TODO(bill): struct_gep type: %s, %d", type_to_string(ir_type(s)), index); } @@ -2611,15 +2615,15 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) { } break; - case Type_Map: { - generate_map_internal_types(a, t); - Type *gst = t->Map.generated_struct_type; - switch (index) { - case 0: result_type = gst->Struct.fields[0]->type; break; - case 1: result_type = gst->Struct.fields[1]->type; break; - } - break; - } + // case Type_Map: { + // generate_map_internal_types(a, t); + // Type *gst = t->Map.generated_struct_type; + // switch (index) { + // case 0: result_type = gst->Struct.fields[0]->type; break; + // case 1: result_type = gst->Struct.fields[1]->type; break; + // } + // break; + // } default: GB_PANIC("TODO(bill): struct_ev type: %s, %d", type_to_string(ir_type(s)), index); @@ -6192,10 +6196,6 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir irBlock *done = nullptr; irBlock *body = nullptr; - irValue *key = nullptr; - 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_const_int(proc->module->allocator, -1)); @@ -6210,6 +6210,7 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir body = ir_new_block(proc, nullptr, "for.index.body"); done = ir_new_block(proc, nullptr, "for.index.done"); if (count == nullptr) { + GB_ASSERT(count_ptr != nullptr); count = ir_emit_load(proc, count_ptr); } irValue *cond = ir_emit_comp(proc, Token_Lt, incr, count); @@ -6217,52 +6218,59 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir ir_start_block(proc, body); idx = ir_emit_load(proc, index); - if (val_type != nullptr) { - switch (expr_type->kind) { - case Type_Array: { + switch (expr_type->kind) { + case Type_Array: { + if (val_type != nullptr) { val = ir_emit_load(proc, ir_emit_array_ep(proc, expr, idx)); - break; } - case Type_Slice: { + break; + } + case Type_Slice: { + if (val_type != nullptr) { irValue *elem = ir_slice_elem(proc, expr); val = ir_emit_load(proc, ir_emit_ptr_offset(proc, elem, idx)); - break; } - case Type_DynamicArray: { + break; + } + case Type_DynamicArray: { + if (val_type != nullptr) { 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); + break; + } + case Type_Map: { + irValue *key = ir_add_local_generated(proc, expr_type->Map.key); - irValue *entry = ir_emit_ptr_offset(proc, elem, idx); - val = ir_emit_load(proc, ir_emit_struct_ep(proc, entry, 2)); + Type *itp = make_type_pointer(proc->module->allocator, expr_type->Map.internal_type); + irValue *data_ptr = ir_emit_transmute(proc, expr, itp); + irValue *internal_ptr = ir_emit_load(proc, data_ptr); - 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)); - } + irValue *entries = ir_emit_struct_ep(proc, internal_ptr, 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)); - break; - } - default: - GB_PANIC("Cannot do range_indexed of %s", type_to_string(expr_type)); - break; + 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)); } - } - if (key != nullptr) { idx = ir_emit_load(proc, key); + + break; + } + default: + GB_PANIC("Cannot do range_indexed of %s", type_to_string(expr_type)); + break; } if (val_) *val_ = val; @@ -6863,7 +6871,6 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { ir_emit_if(proc, cond, body, done); ir_start_block(proc, body); - irValue *val_ptr = ir_emit_ptr_offset(proc, values_data, offset); ir_emit_increment(proc, offset_); @@ -6885,14 +6892,34 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { switch (et->kind) { case Type_Map: { is_map = true; + gbAllocator a = proc->module->allocator; irAddr addr = ir_build_addr(proc, rs->expr); irValue *map = ir_addr_get_ptr(proc, 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, val1_type, count_ptr, &val, &key, &loop, &done); + irValue *count_ptr = ir_add_local_generated(proc, t_int); + irValue *count_ptr_ptr = ir_add_local_generated(proc, t_int_ptr); + ir_emit_store(proc, count_ptr_ptr, count_ptr); + + irBlock *not_nil_block = ir_new_block(proc, nullptr, "map.not.nil.block"); + irBlock *end_nil_block = ir_new_block(proc, nullptr, "map.end.nil.block"); + { + Type *itp = make_type_pointer(a, et->Map.internal_type); + irValue *data_ptr = ir_emit_transmute(proc, map, itp); + irValue *internal_ptr = ir_emit_load(proc, data_ptr); + + irValue *cond = ir_emit_comp(proc, Token_NotEq, internal_ptr, v_raw_nil); + ir_emit_if(proc, cond, not_nil_block, end_nil_block); + ir_start_block(proc, not_nil_block); + + irValue *entries_ptr = ir_emit_struct_ep(proc, internal_ptr, 1); + irValue *cp = ir_emit_struct_ep(proc, entries_ptr, 1); + ir_emit_store(proc, count_ptr_ptr, cp); + ir_emit_jump(proc, end_nil_block); + } + ir_start_block(proc, end_nil_block); + ir_build_range_indexed(proc, map, val1_type, ir_emit_load(proc, count_ptr_ptr), &val, &key, &loop, &done); break; } case Type_Array: { @@ -6948,6 +6975,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { } } + irAddr val0_addr = {}; irAddr val1_addr = {}; if (val0_type) val0_addr = ir_build_addr(proc, rs->val0); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 8a67cb6e2..2c341ad57 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -427,8 +427,8 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { case Type_Map: { generate_map_internal_types(m->allocator, t); - GB_ASSERT(t->Map.generated_struct_type != nullptr); - ir_print_type(f, m, t->Map.generated_struct_type); + GB_ASSERT(t->Map.internal_type != nullptr); + ir_print_type(f, m, t->Map.internal_type); break; } diff --git a/src/types.cpp b/src/types.cpp index 453f4fd71..9ccb97a6e 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -162,6 +162,7 @@ struct TypeStruct { Type * value; \ Type * entry_type; \ Type * generated_struct_type; \ + Type * internal_type; \ Type * lookup_result_type; \ }) \ TYPE_KIND(BitFieldValue, struct { u32 bits; }) \ @@ -1365,10 +1366,10 @@ i64 union_tag_size(gbAllocator a, Type *u) { return u->Union.tag_size; } - i64 tag_size = type_align_of(a, u); - if (tag_size < 1) { - tag_size = build_context.word_size; - } + u64 n = cast(u64)u->Union.variants.count; + i64 bytes = next_pow2(cast(i64)(floor_log2(n)/8 + 1)); + i64 tag_size = gb_max(bytes, 1); + u->Union.tag_size = tag_size; return tag_size; } @@ -1383,7 +1384,7 @@ Type *union_tag_type(gbAllocator a, Type *u) { case 16: return t_u128; } GB_PANIC("Invalid union_tag_size"); - return t_int; + return t_uint; } @@ -1870,7 +1871,8 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Map: generate_map_internal_types(allocator, t); - return type_align_of_internal(allocator, t->Map.generated_struct_type, path); + // return type_align_of_internal(allocator, t->Map.generated_struct_type, path); + return build_context.word_size; case Type_Enum: return type_align_of_internal(allocator, t->Enum.base_type, path); @@ -2063,7 +2065,8 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Map: generate_map_internal_types(allocator, t); - return type_size_of_internal(allocator, t->Map.generated_struct_type, path); + // return type_size_of_internal(allocator, t->Map.generated_struct_type, path); + return build_context.word_size; case Type_Tuple: { i64 count, align, size; @@ -2101,7 +2104,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { } // NOTE(bill): Align to tag - i64 tag_size = gb_max(align, 1); + i64 tag_size = union_tag_size(allocator, t); i64 size = align_formula(max, tag_size); // NOTE(bill): Calculate the padding between the common fields and the tag t->Union.tag_size = tag_size; |