aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
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
parentff6e21cb879397982cddf3cf5f47bba681271a2c (diff)
Match statements; Type System change (Type_Record for all sum and product types)
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/codegen.cpp16
-rw-r--r--src/codegen/print_llvm.cpp59
-rw-r--r--src/codegen/ssa.cpp148
3 files changed, 170 insertions, 53 deletions
diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp
index 88260be8c..8235fb615 100644
--- a/src/codegen/codegen.cpp
+++ b/src/codegen/codegen.cpp
@@ -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;
diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp
index 689b19ac8..6f63c0108 100644
--- a/src/codegen/print_llvm.cpp
+++ b/src/codegen/print_llvm.cpp
@@ -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->Struct.is_packed) {
- ssa_fprintf(f, ">");
+ 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;
}
-
- 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 ");
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) {