aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/ssa.cpp
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-09-01 20:38:44 +0100
committerGinger Bill <bill@gingerbill.org>2016-09-01 20:38:44 +0100
commitfa09d805e23c59cb881573a7a1aee5fbc5752ea2 (patch)
tree5407c69e5f63b0d3dcab9eef6fee323273070445 /src/codegen/ssa.cpp
parentff6e21cb879397982cddf3cf5f47bba681271a2c (diff)
Match statements; Type System change (Type_Record for all sum and product types)
Diffstat (limited to 'src/codegen/ssa.cpp')
-rw-r--r--src/codegen/ssa.cpp148
1 files changed, 124 insertions, 24 deletions
diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp
index 2f7c13dd8..b2eb6c6a4 100644
--- a/src/codegen/ssa.cpp
+++ b/src/codegen/ssa.cpp
@@ -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) {