Fix find_using_index_expr

This commit is contained in:
Ginger Bill
2017-04-23 11:04:22 +01:00
parent 3fd37c6dc5
commit c2fa79012e
7 changed files with 62 additions and 33 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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"));

View File

@@ -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);
}

View File

@@ -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