From c2fa79012ea01ad508083f13f86d2b6c8f5045da Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sun, 23 Apr 2017 11:04:22 +0100 Subject: [PATCH] Fix `find_using_index_expr` --- src/check_decl.c | 2 +- src/check_expr.c | 26 +++++++++----------------- src/checker.c | 7 +++++++ src/entity.c | 8 ++++---- src/ir.c | 34 ++++++++++++++++++++++++++++------ src/ssa.c | 4 ++-- src/types.c | 14 +++++++++++--- 7 files changed, 62 insertions(+), 33 deletions(-) diff --git a/src/check_decl.c b/src/check_decl.c index 0321f3b2e..5239b67d8 100644 --- a/src/check_decl.c +++ b/src/check_decl.c @@ -531,7 +531,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod for (isize i = 0; i < params->variable_count; i++) { Entity *e = params->variables[i]; GB_ASSERT(e->kind == Entity_Variable); - if (!(e->flags & EntityFlag_Anonymous)) { + if (!(e->flags & EntityFlag_Using)) { continue; } bool is_immutable = e->Variable.is_immutable; diff --git a/src/check_expr.c b/src/check_expr.c index 15bfa6dbb..169798da5 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -89,7 +89,7 @@ bool check_is_assignable_to_using_subtype(Type *dst, Type *src) { if (is_type_struct(src)) { for (isize i = 0; i < src->Record.field_count; i++) { Entity *f = src->Record.fields[i]; - if (f->kind == Entity_Variable && (f->flags & EntityFlag_Anonymous)) { + if (f->kind == Entity_Variable && (f->flags & EntityFlag_Using)) { if (are_types_identical(dst, f->type)) { return true; } @@ -323,7 +323,7 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, MapEntity *en } else { map_entity_set(entity_map, key, f); add_entity(c, c->context.scope, NULL, f); - if (f->flags & EntityFlag_Anonymous) { + if (f->flags & EntityFlag_Using) { populate_using_entity_map(c, node, f->type, entity_map); } } @@ -406,7 +406,7 @@ isize check_fields(Checker *c, AstNode *node, AstNodeArray decls, bool ok = true; for_array(emi, entity_map.entries) { Entity *e = entity_map.entries.e[emi].value; - if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) { + if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { if (is_type_indexable(e->type)) { if (e->identifier != f->names.e[0]) { ok = false; @@ -419,7 +419,7 @@ isize check_fields(Checker *c, AstNode *node, AstNodeArray decls, if (ok) { using_index_expr = fields[field_index-1]; } else { - fields[field_index-1]->flags &= ~EntityFlag_Anonymous; + fields[field_index-1]->flags &= ~EntityFlag_Using; error(name_token, "Previous `using` for an index expression `%.*s`", LIT(name_token.string)); } } else { @@ -603,6 +603,8 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) { union_type->Record.fields_in_src_order = fields; union_type->Record.field_count = field_count; union_type->Record.are_offsets_set = false; + union_type->Record.is_ordered = true; + for_array(i, ut->variants) { @@ -2056,17 +2058,6 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) { } break; } - #if 0 - // CLEANUP(bill) NOTE(bill): there is an auto assignment to `any` which needs to be checked - if (is_type_any(x->type) && !is_type_any(y->type)) { - err_type = x->type; - defined = false; - } else if (is_type_any(y->type) && !is_type_any(x->type)) { - err_type = y->type; - defined = false; - } - #endif - if (!defined) { if (x->type == err_type && is_operand_nil(*x)) { err_type = y->type; @@ -2223,7 +2214,7 @@ String check_down_cast_name(Type *dst_, Type *src_) { for (isize i = 0; i < dst_s->Record.field_count; i++) { Entity *f = dst_s->Record.fields[i]; GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field); - if (f->flags & EntityFlag_Anonymous) { + if (f->flags & EntityFlag_Using) { if (are_types_identical(f->type, src_)) { return f->token.string; } @@ -4705,7 +4696,8 @@ Entity *find_using_index_expr(Type *t) { for (isize i = 0; i < t->Record.field_count; i++) { Entity *f = t->Record.fields[i]; if (f->kind == Entity_Variable && - f->flags & (EntityFlag_Anonymous|EntityFlag_Field)) { + (f->flags & EntityFlag_Field) != 0 && + (f->flags & EntityFlag_Using) != 0) { if (is_type_indexable(f->type)) { return f; } diff --git a/src/checker.c b/src/checker.c index 6ef7811f3..7ce2dc772 100644 --- a/src/checker.c +++ b/src/checker.c @@ -1984,6 +1984,8 @@ void check_parsed_files(Checker *c) { } } + + // NOTE(bill): Check for illegal cyclic type declarations for_array(i, c->info.definitions.entries) { Entity *e = c->info.definitions.entries.e[i].value; @@ -1991,10 +1993,15 @@ void check_parsed_files(Checker *c) { if (e->type != NULL) { // i64 size = type_size_of(c->sizes, c->allocator, e->type); i64 align = type_align_of(c->allocator, e->type); + if (align > 0) { + // add_type_info_type(c, e->type); + } } } } + // gb_printf_err("Count: %td\n", c->info.type_info_count++); + for_array(i, file_scopes.entries) { Scope *s = file_scopes.entries.e[i].value; if (s->is_init) { diff --git a/src/entity.c b/src/entity.c index bfd8f8064..068169e55 100644 --- a/src/entity.c +++ b/src/entity.c @@ -33,7 +33,7 @@ String const entity_strings[] = { typedef enum EntityFlag { EntityFlag_Visited = 1<<0, EntityFlag_Used = 1<<1, - EntityFlag_Anonymous = 1<<2, + EntityFlag_Using = 1<<2, EntityFlag_Field = 1<<3, EntityFlag_Param = 1<<4, EntityFlag_VectorElem = 1<<5, @@ -159,7 +159,7 @@ Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, T token.pos = parent->token.pos; Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type); entity->using_parent = parent; - entity->flags |= EntityFlag_Anonymous; + entity->flags |= EntityFlag_Using; return entity; } @@ -178,7 +178,7 @@ Entity *make_entity_type_name(gbAllocator a, Scope *scope, Token token, Type *ty Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type, bool anonymous, bool is_immutable) { Entity *entity = make_entity_variable(a, scope, token, type, is_immutable); entity->flags |= EntityFlag_Used; - if (anonymous) entity->flags |= EntityFlag_Anonymous; + if (anonymous) entity->flags |= EntityFlag_Using; entity->flags |= EntityFlag_Param; return entity; } @@ -188,7 +188,7 @@ Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type, entity->Variable.field_src_index = field_src_index; entity->Variable.field_index = field_src_index; entity->flags |= EntityFlag_Field; - entity->flags |= EntityFlag_Anonymous*(anonymous != 0); + entity->flags |= EntityFlag_Using*(anonymous != 0); return entity; } diff --git a/src/ir.c b/src/ir.c index e8d6b3ed0..0c900bc4f 100644 --- a/src/ir.c +++ b/src/ir.c @@ -142,6 +142,7 @@ struct irProcedure { #define IR_TYPE_INFO_TYPES_NAME "__$type_info_types_data" #define IR_TYPE_INFO_NAMES_NAME "__$type_info_names_data" #define IR_TYPE_INFO_OFFSETS_NAME "__$type_info_offsets_data" +#define IR_TYPE_INFO_USINGS_NAME "__$type_info_usings_data" #define IR_INSTR_KINDS \ @@ -2596,7 +2597,7 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) { GB_ASSERT(is_type_struct(src)); for (isize i = 0; i < src->Record.field_count; i++) { Entity *f = src->Record.fields[i]; - if (f->kind == Entity_Variable && f->flags & EntityFlag_Anonymous) { + if (f->kind == Entity_Variable && f->flags & EntityFlag_Using) { if (are_types_identical(dst, f->type)) { return f->token.string; } @@ -3123,11 +3124,13 @@ gb_global irValue *ir_global_type_info_data = NULL; gb_global irValue *ir_global_type_info_member_types = NULL; gb_global irValue *ir_global_type_info_member_names = NULL; gb_global irValue *ir_global_type_info_member_offsets = NULL; +gb_global irValue *ir_global_type_info_member_usings = NULL; gb_global i32 ir_global_type_info_data_index = 0; gb_global i32 ir_global_type_info_member_types_index = 0; gb_global i32 ir_global_type_info_member_names_index = 0; gb_global i32 ir_global_type_info_member_offsets_index = 0; +gb_global i32 ir_global_type_info_member_usings_index = 0; irValue *ir_type_info(irProcedure *proc, Type *type) { @@ -4550,7 +4553,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { } irValue *ir_get_using_variable(irProcedure *proc, Entity *e) { - GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous); + GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Using); String name = e->token.string; Entity *parent = e->using_parent; Selection sel = lookup_field(proc->module->allocator, parent->type, name, false); @@ -4594,7 +4597,7 @@ irAddr ir_build_addr_from_entity(irProcedure *proc, Entity *e, AstNode *expr) { irValue **found = map_ir_value_get(&proc->module->values, hash_pointer(e)); if (found) { v = *found; - } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) { + } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { // NOTE(bill): Calculate the using variable every time v = ir_get_using_variable(proc, e); } @@ -6741,6 +6744,16 @@ void ir_init_module(irModule *m, Checker *c) { map_ir_value_set(&m->members, hash_string(name), g); ir_global_type_info_member_offsets = g; } + + { + String name = str_lit(IR_TYPE_INFO_USINGS_NAME); + Entity *e = make_entity_variable(m->allocator, NULL, make_token_ident(name), + make_type_array(m->allocator, t_bool, count), false); + irValue *g = ir_value_global(m->allocator, e, NULL); + ir_module_add_value(m, e, g); + map_ir_value_set(&m->members, hash_string(name), g); + ir_global_type_info_member_usings = g; + } } } @@ -6832,6 +6845,11 @@ irValue *ir_type_info_member_offsets_offset(irProcedure *proc, isize count) { ir_global_type_info_member_offsets_index += count; return offset; } +irValue *ir_type_info_member_usings_offset(irProcedure *proc, isize count) { + irValue *offset = ir_emit_array_epi(proc, ir_global_type_info_member_usings, ir_global_type_info_member_usings_index); + ir_global_type_info_member_usings_index += count; + return offset; +} @@ -7393,14 +7411,15 @@ void ir_gen_tree(irGen *s) { irValue *packed = ir_const_bool(a, t->Record.is_packed); irValue *ordered = ir_const_bool(a, t->Record.is_ordered); irValue *custom_align = ir_const_bool(a, t->Record.custom_align); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 3), packed); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 4), ordered); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 5), custom_align); + ir_emit_store(proc, ir_emit_struct_ep(proc, record, 4), packed); + ir_emit_store(proc, ir_emit_struct_ep(proc, record, 5), ordered); + ir_emit_store(proc, ir_emit_struct_ep(proc, record, 6), custom_align); } irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count); irValue *memory_names = ir_type_info_member_names_offset(proc, t->Record.field_count); irValue *memory_offsets = ir_type_info_member_offsets_offset(proc, t->Record.field_count); + irValue *memory_usings = ir_type_info_member_usings_offset(proc, t->Record.field_count); type_set_offsets(a, t); // NOTE(bill): Just incase the offsets have not been set yet for (isize source_index = 0; source_index < t->Record.field_count; source_index++) { @@ -7413,6 +7432,7 @@ void ir_gen_tree(irGen *s) { irValue *index = ir_const_int(a, source_index); irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index); irValue *offset = ir_emit_ptr_offset(proc, memory_offsets, index); + irValue *is_using = ir_emit_ptr_offset(proc, memory_usings, index); ir_emit_store(proc, type_info, ir_type_info(proc, f->type)); if (f->token.string.len > 0) { @@ -7420,12 +7440,14 @@ void ir_gen_tree(irGen *s) { ir_emit_store(proc, name, ir_const_string(a, f->token.string)); } ir_emit_store(proc, offset, ir_const_int(a, foffset)); + ir_emit_store(proc, is_using, ir_const_bool(a, f->flags&EntityFlag_Using)); } irValue *count = ir_const_int(a, t->Record.field_count); ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count); ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count); ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, count, count); + ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 3), memory_usings, count, count); } break; case TypeRecord_Union: { ir_emit_comment(proc, str_lit("Type_Info_Union")); diff --git a/src/ssa.c b/src/ssa.c index 6aa3e1d00..2c4394cd3 100644 --- a/src/ssa.c +++ b/src/ssa.c @@ -700,7 +700,7 @@ ssaValue *ssa_addr_load(ssaProc *p, ssaAddr addr) { } ssaValue *ssa_get_using_variable(ssaProc *p, Entity *e) { - GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous); + GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Using); String name = e->token.string; Entity *parent = e->using_parent; Selection sel = lookup_field(p->allocator, parent->type, name, false); @@ -724,7 +724,7 @@ ssaAddr ssa_build_addr_from_entity(ssaProc *p, Entity *e, AstNode *expr) { ssaValue **found = map_ssa_value_get(&p->module->values, hash_pointer(e)); if (found) { v = *found; - } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) { + } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { // NOTE(bill): Calculate the using variable every time v = ssa_get_using_variable(p, e); } diff --git a/src/types.c b/src/types.c index 8c13cfb9a..fc850c2bc 100644 --- a/src/types.c +++ b/src/types.c @@ -935,13 +935,21 @@ bool are_types_identical(Type *x, Type *y) { x->Record.custom_align == y->Record.custom_align) { // TODO(bill); Fix the custom alignment rule for (isize i = 0; i < x->Record.field_count; i++) { - if (!are_types_identical(x->Record.fields[i]->type, y->Record.fields[i]->type)) { + Entity *xf = x->Record.fields[i]; + Entity *yf = y->Record.fields[i]; + if (!are_types_identical(xf->type, yf->type)) { return false; } - if (str_ne(x->Record.fields[i]->token.string, y->Record.fields[i]->token.string)) { + if (str_ne(xf->token.string, yf->token.string)) { + return false; + } + bool xf_is_using = (xf->flags&EntityFlag_Using) != 0; + bool yf_is_using = (yf->flags&EntityFlag_Using) != 0; + if (xf_is_using ^ yf_is_using) { return false; } } + // NOTE(bill): zeroth variant is NULL for (isize i = 1; i < x->Record.variant_count; i++) { if (!are_types_identical(x->Record.variants[i]->type, y->Record.variants[i]->type)) { return false; @@ -1340,7 +1348,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n return sel; } - if (f->flags & EntityFlag_Anonymous) { + if (f->flags & EntityFlag_Using) { isize prev_count = sel.index.count; selection_add_index(&sel, i); // HACK(bill): Leaky memory