mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-14 09:52:23 -07:00
Match statements; Type System change (Type_Record for all sum and product types)
This commit is contained in:
+15
-1
@@ -89,11 +89,25 @@ void ssa_gen_code(ssaGen *s) {
|
||||
|
||||
case Entity_Procedure: {
|
||||
auto *pd = &decl->proc_decl->ProcDecl;
|
||||
String name = e->token.string;
|
||||
String original_name = e->token.string;
|
||||
String name = original_name;
|
||||
AstNode *body = pd->body;
|
||||
if (pd->foreign_name.len > 0) {
|
||||
name = pd->foreign_name;
|
||||
}
|
||||
|
||||
if (are_strings_equal(name, original_name)) {
|
||||
Scope *scope = *map_get(&info->scopes, hash_pointer(pd->type));
|
||||
isize count = multi_map_count(&scope->elements, hash_string(original_name));
|
||||
if (count > 1) {
|
||||
gb_printf("%.*s\n", LIT(name));
|
||||
isize name_len = name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(m->allocator, u8, name_len);
|
||||
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%d", LIT(name), e->guid);
|
||||
name = make_string(name_text, name_len-1);
|
||||
}
|
||||
}
|
||||
|
||||
ssaValue *p = ssa_make_value_procedure(a, m, e->type, decl->type_expr, body, name);
|
||||
p->Proc.tags = pd->tags;
|
||||
|
||||
|
||||
+31
-28
@@ -135,41 +135,44 @@ void ssa_print_type(gbFile *f, BaseTypeSizes s, Type *t) {
|
||||
ssa_print_type(f, s, t->Slice.elem);
|
||||
ssa_fprintf(f, "*, i%lld, i%lld}", word_bits, word_bits);
|
||||
break;
|
||||
case Type_Struct:
|
||||
if (t->Struct.is_packed) {
|
||||
ssa_fprintf(f, "<");
|
||||
}
|
||||
ssa_fprintf(f, "{");
|
||||
for (isize i = 0; i < t->Struct.field_count; i++) {
|
||||
if (i > 0) {
|
||||
ssa_fprintf(f, ", ");
|
||||
case Type_Record: {
|
||||
switch (t->Record.kind) {
|
||||
case TypeRecord_Struct:
|
||||
if (t->Record.struct_is_packed) {
|
||||
ssa_fprintf(f, "<");
|
||||
}
|
||||
Type *ft = t->Struct.fields[i]->type;
|
||||
Type *bft = get_base_type(ft);
|
||||
if (bft->kind != Type_Struct) {
|
||||
ft = bft;
|
||||
ssa_fprintf(f, "{");
|
||||
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||
if (i > 0) {
|
||||
ssa_fprintf(f, ", ");
|
||||
}
|
||||
Type *ft = t->Record.fields[i]->type;
|
||||
Type *bft = get_base_type(ft);
|
||||
if (!is_type_struct(bft)) {
|
||||
ft = bft;
|
||||
}
|
||||
ssa_print_type(f, s, ft);
|
||||
}
|
||||
ssa_print_type(f, s, ft);
|
||||
ssa_fprintf(f, "}");
|
||||
if (t->Record.struct_is_packed) {
|
||||
ssa_fprintf(f, ">");
|
||||
}
|
||||
break;
|
||||
case TypeRecord_RawUnion:
|
||||
ssa_fprintf(f, "[%lld x i8]", type_size_of(s, gb_heap_allocator(), t));
|
||||
break;
|
||||
case TypeRecord_Enum:
|
||||
ssa_print_type(f, s, t->Record.enum_base);
|
||||
break;
|
||||
}
|
||||
ssa_fprintf(f, "}");
|
||||
if (t->Struct.is_packed) {
|
||||
ssa_fprintf(f, ">");
|
||||
}
|
||||
|
||||
break;
|
||||
case Type_Union: {
|
||||
i64 size = type_size_of(s, gb_heap_allocator(), t);
|
||||
ssa_fprintf(f, "[%lld x i8]", size);
|
||||
} break;
|
||||
case Type_Enum:
|
||||
ssa_print_type(f, s, t->Enum.base);
|
||||
break;
|
||||
|
||||
case Type_Pointer:
|
||||
ssa_print_type(f, s, t->Pointer.elem);
|
||||
ssa_fprintf(f, "*");
|
||||
break;
|
||||
case Type_Named:
|
||||
if (get_base_type(t)->kind == Type_Struct) {
|
||||
if (is_type_struct(t)) {
|
||||
ssa_print_encoded_local(f, t->Named.name);
|
||||
} else {
|
||||
ssa_print_type(f, s, get_base_type(t));
|
||||
@@ -271,7 +274,7 @@ void ssa_print_exact_value(gbFile *f, ssaModule *m, ExactValue value, Type *type
|
||||
|
||||
void ssa_print_block_name(gbFile *f, ssaBlock *b) {
|
||||
ssa_print_escape_string(f, b->label, false);
|
||||
ssa_fprintf(f, ".-.%d", b->id);
|
||||
ssa_fprintf(f, "..%d", b->id);
|
||||
}
|
||||
|
||||
void ssa_print_value(gbFile *f, ssaModule *m, ssaValue *value, Type *type_hint) {
|
||||
@@ -753,7 +756,7 @@ void ssa_print_proc(gbFile *f, ssaModule *m, ssaProcedure *proc) {
|
||||
void ssa_print_type_name(gbFile *f, ssaModule *m, ssaValue *v) {
|
||||
GB_ASSERT(v->kind == ssaValue_TypeName);
|
||||
Type *base_type = get_base_type(ssa_type(v));
|
||||
if (base_type->kind != Type_Struct)
|
||||
if (!is_type_struct(base_type))
|
||||
return;
|
||||
ssa_print_encoded_local(f, v->TypeName.name);
|
||||
ssa_fprintf(f, " = type ");
|
||||
|
||||
+124
-24
@@ -25,6 +25,7 @@ struct ssaBlock {
|
||||
isize scope_index;
|
||||
String label;
|
||||
ssaProcedure *parent;
|
||||
b32 added;
|
||||
|
||||
gbArray(ssaValue *) instrs;
|
||||
gbArray(ssaValue *) values;
|
||||
@@ -672,7 +673,7 @@ ssaValue *ssa_make_value_block(ssaProcedure *proc, AstNode *node, Scope *scope,
|
||||
b32 ssa_is_blank_ident(AstNode *node) {
|
||||
if (node->kind == AstNode_Ident) {
|
||||
ast_node(i, Ident, node);
|
||||
return is_blank_ident(i->token.string);
|
||||
return is_blank_ident(i->string);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -710,7 +711,7 @@ ssaValue *ssa_emit(ssaProcedure *proc, ssaValue *instr) {
|
||||
GB_ASSERT(instr->kind == ssaValue_Instr);
|
||||
ssaBlock *b = proc->curr_block;
|
||||
instr->Instr.parent = b;
|
||||
if (b) {
|
||||
if (b != NULL) {
|
||||
ssaInstr *i = ssa_get_last_instr(b);
|
||||
if (!ssa_is_instr_terminating(i)) {
|
||||
gb_array_append(b->instrs, instr);
|
||||
@@ -742,8 +743,11 @@ ssaValue *ssa_add_local_for_identifier(ssaProcedure *proc, AstNode *name) {
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_local_generated(ssaProcedure *proc, Type *type) {
|
||||
Scope *scope = NULL;
|
||||
if (proc->curr_block)
|
||||
scope = proc->curr_block->scope;
|
||||
Entity *entity = make_entity_variable(proc->module->allocator,
|
||||
proc->curr_block->scope,
|
||||
scope,
|
||||
empty_token,
|
||||
type);
|
||||
return ssa_emit(proc, ssa_make_instr_local(proc, entity));
|
||||
@@ -1064,15 +1068,15 @@ ssaValue *ssa_emit_deep_field_gep(ssaProcedure *proc, Type *type, ssaValue *e, S
|
||||
type = get_base_type(type);
|
||||
|
||||
|
||||
if (type->kind == Type_Union) {
|
||||
if (is_type_raw_union(type)) {
|
||||
ssaValue *v = ssa_emit_ptr_offset(proc, e, v_zero);
|
||||
ssa_set_type(v, make_type_pointer(proc->module->allocator, type));
|
||||
type = type->Union.fields[index]->type;
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ssa_emit_conv(proc, v, make_type_pointer(proc->module->allocator, type));
|
||||
e = ssa_emit_ptr_offset(proc, e, v_zero);
|
||||
ssa_set_type(e, type);
|
||||
} else {
|
||||
type = type->Union.fields[index]->type;
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ssa_emit_struct_gep(proc, e, index, type);
|
||||
}
|
||||
}
|
||||
@@ -1095,15 +1099,15 @@ ssaValue *ssa_emit_deep_field_ev(ssaProcedure *proc, Type *type, ssaValue *e, Se
|
||||
type = get_base_type(type);
|
||||
|
||||
|
||||
if (type->kind == Type_Union) {
|
||||
if (is_type_raw_union(type)) {
|
||||
ssaValue *v = ssa_emit_ptr_offset(proc, e, v_zero);
|
||||
ssa_set_type(v, make_type_pointer(proc->module->allocator, type));
|
||||
type = type->Union.fields[index]->type;
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ssa_emit_conv(proc, v, make_type_pointer(proc->module->allocator, type));
|
||||
e = ssa_emit_ptr_offset(proc, e, v_zero);
|
||||
ssa_set_type(e, type);
|
||||
} else {
|
||||
type = type->Union.fields[index]->type;
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ssa_emit_struct_ev(proc, e, index, type);
|
||||
}
|
||||
}
|
||||
@@ -1296,9 +1300,9 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
|
||||
b32 src_is_ptr = src != prev_src;
|
||||
// b32 dst_is_ptr = dst != prev_dst;
|
||||
|
||||
GB_ASSERT(src->kind == Type_Struct);
|
||||
for (isize i = 0; i < src->Struct.field_count; i++) {
|
||||
Entity *f = src->Struct.fields[i];
|
||||
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->Variable.anonymous) {
|
||||
if (are_types_identical(dst, f->type)) {
|
||||
return f->token.string;
|
||||
@@ -1420,7 +1424,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
|
||||
if (is_argument) {
|
||||
Type *sb = get_base_type(type_deref(src));
|
||||
b32 src_is_ptr = src != sb;
|
||||
if (sb->kind == Type_Struct) {
|
||||
if (is_type_struct(sb)) {
|
||||
String field_name = lookup_polymorphic_field(proc->module->info, t, src);
|
||||
// gb_printf("field_name: %.*s\n", LIT(field_name));
|
||||
if (field_name.len > 0) {
|
||||
@@ -1729,8 +1733,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case Type_Struct: {
|
||||
auto *st = &base_type->Struct;
|
||||
case Type_Record: {
|
||||
GB_ASSERT(is_type_struct(base_type));
|
||||
auto *st = &base_type->Record;
|
||||
if (cl->elem_list != NULL) {
|
||||
isize index = 0;
|
||||
AstNode *elem = cl->elem_list;
|
||||
@@ -1743,7 +1748,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
|
||||
if (elem->kind == AstNode_FieldValue) {
|
||||
ast_node(kv, FieldValue, elem);
|
||||
Selection sel = lookup_field(base_type, kv->field->Ident.token.string, false);
|
||||
Selection sel = lookup_field(base_type, kv->field->Ident.string, false);
|
||||
field_index = sel.index[0];
|
||||
field_expr = ssa_build_expr(proc, kv->value);
|
||||
} else {
|
||||
@@ -2198,7 +2203,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
case_ast_node(se, SelectorExpr, expr);
|
||||
Type *type = get_base_type(type_of_expr(proc->module->info, se->expr));
|
||||
|
||||
Selection sel = lookup_field(type, unparen_expr(se->selector)->Ident.token.string, false);
|
||||
Selection sel = lookup_field(type, unparen_expr(se->selector)->Ident.string, false);
|
||||
GB_ASSERT(sel.entity != NULL);
|
||||
|
||||
ssaValue *e = ssa_build_addr(proc, se->expr).addr;
|
||||
@@ -2389,8 +2394,8 @@ void ssa_gen_global_type_name(ssaModule *m, Entity *e, String name) {
|
||||
map_set(&m->members, hash_string(name), t);
|
||||
|
||||
Type *bt = get_base_type(e->type);
|
||||
if (bt->kind == Type_Struct) {
|
||||
auto *s = &bt->Struct;
|
||||
if (is_type_struct(bt)) {
|
||||
auto *s = &bt->Record;
|
||||
for (isize j = 0; j < s->other_field_count; j++) {
|
||||
Entity *field = s->other_fields[j];
|
||||
if (field->kind == Entity_TypeName) {
|
||||
@@ -2519,7 +2524,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
if (pd->body != NULL) {
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent$name-guid
|
||||
String pd_name = pd->name->Ident.token.string;
|
||||
String pd_name = pd->name->Ident.string;
|
||||
isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
i32 guid = cast(i32)gb_array_count(proc->children);
|
||||
@@ -2527,7 +2532,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
String name = make_string(name_text, name_len-1);
|
||||
|
||||
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(pd->name));
|
||||
GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.token.string));
|
||||
GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.string));
|
||||
Entity *e = *found;
|
||||
ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
|
||||
proc->module, e->type, pd->type, pd->body, name);
|
||||
@@ -2538,12 +2543,14 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
gb_array_append(proc->children, &value->Proc);
|
||||
ssa_build_proc(value, proc);
|
||||
} else {
|
||||
String name = pd->name->Ident.token.string;
|
||||
String original_name = pd->name->Ident.string;
|
||||
String name = original_name;
|
||||
if (pd->foreign_name.len > 0) {
|
||||
name = pd->foreign_name;
|
||||
}
|
||||
auto *info = proc->module->info;
|
||||
|
||||
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(pd->name));
|
||||
Entity **found = map_get(&info->definitions, hash_pointer(pd->name));
|
||||
GB_ASSERT(found != NULL);
|
||||
Entity *e = *found;
|
||||
ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
|
||||
@@ -2558,7 +2565,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent_proc.name-guid
|
||||
String td_name = td->name->Ident.token.string;
|
||||
String td_name = td->name->Ident.string;
|
||||
isize name_len = proc->name.len + 1 + td_name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
i32 guid = cast(i32)gb_array_count(proc->module->members.entries);
|
||||
@@ -2806,6 +2813,99 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, MatchStmt, node);
|
||||
if (ms->init != NULL) {
|
||||
ssa_build_stmt(proc, ms->init);
|
||||
}
|
||||
ssaValue *tag = v_true;
|
||||
if (ms->tag != NULL) {
|
||||
tag = ssa_build_expr(proc, ms->tag);
|
||||
}
|
||||
ssaBlock *done = ssa__make_block(proc, node, make_string("match.done")); // NOTE(bill): Append later
|
||||
|
||||
ast_node(body, BlockStmt, ms->body);
|
||||
|
||||
|
||||
AstNode *default_stmts = NULL;
|
||||
ssaBlock *default_fall = NULL;
|
||||
ssaBlock *default_block = NULL;
|
||||
|
||||
ssaBlock *fall = NULL;
|
||||
b32 append_fall = false;
|
||||
|
||||
isize case_count = body->list_count;
|
||||
isize i = 0;
|
||||
for (AstNode *clause = body->list;
|
||||
clause != NULL;
|
||||
clause = clause->next, i++) {
|
||||
ssaBlock *body = fall;
|
||||
b32 append_body = false;
|
||||
|
||||
|
||||
ast_node(cc, CaseClause, clause);
|
||||
|
||||
if (body == NULL) {
|
||||
append_body = true;
|
||||
if (cc->list == NULL) {
|
||||
body = ssa__make_block(proc, clause, make_string("match.dflt.body"));
|
||||
} else {
|
||||
body = ssa__make_block(proc, clause, make_string("match.case.body"));
|
||||
}
|
||||
}
|
||||
if (append_fall && body == fall) {
|
||||
append_fall = false;
|
||||
append_body = true;
|
||||
}
|
||||
|
||||
fall = done;
|
||||
if (i+1 < case_count) {
|
||||
append_fall = true;
|
||||
fall = ssa__make_block(proc, clause, make_string("match.fall.body"));
|
||||
}
|
||||
|
||||
if (cc->list == NULL) {
|
||||
// default case
|
||||
default_stmts = cc->stmts;
|
||||
default_fall = fall;
|
||||
default_block = body;
|
||||
continue;
|
||||
}
|
||||
|
||||
ssaBlock *next_cond = NULL;
|
||||
Token eq = {Token_CmpEq};
|
||||
for (AstNode *expr = cc->list; expr != NULL; expr = expr->next) {
|
||||
next_cond = ssa__make_block(proc, clause, make_string("match.case.next"));
|
||||
|
||||
ssaValue *cond = ssa_emit_comp(proc, eq, tag, ssa_build_expr(proc, expr));
|
||||
ssa_emit_if(proc, cond, body, next_cond);
|
||||
gb_array_append(proc->blocks, next_cond);
|
||||
proc->curr_block = next_cond;
|
||||
}
|
||||
if (append_body) {
|
||||
gb_array_append(proc->blocks, body);
|
||||
}
|
||||
proc->curr_block = body;
|
||||
ssa_push_target_list(proc, done, NULL, fall);
|
||||
ssa_build_stmt_list(proc, cc->stmts);
|
||||
ssa_pop_target_list(proc);
|
||||
ssa_emit_jump(proc, done);
|
||||
proc->curr_block = next_cond;
|
||||
}
|
||||
|
||||
if (default_block != NULL) {
|
||||
ssa_emit_jump(proc, default_block);
|
||||
gb_array_append(proc->blocks, default_block);
|
||||
proc->curr_block = default_block;
|
||||
ssa_push_target_list(proc, done, NULL, default_fall);
|
||||
ssa_build_stmt_list(proc, default_stmts);
|
||||
ssa_pop_target_list(proc);
|
||||
}
|
||||
|
||||
ssa_emit_jump(proc, done);
|
||||
gb_array_append(proc->blocks, done);
|
||||
proc->curr_block = done;
|
||||
case_end;
|
||||
|
||||
case_ast_node(bs, BranchStmt, node);
|
||||
ssaBlock *block = NULL;
|
||||
switch (bs->token.kind) {
|
||||
|
||||
Reference in New Issue
Block a user