mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-10 06:53:03 +00:00
Fix find_using_index_expr
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
34
src/ir.c
34
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"));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
14
src/types.c
14
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user