SSA Phi Node Support

This commit is contained in:
Ginger Bill
2016-10-08 22:03:40 +01:00
parent b705fa7f22
commit e299c3693e
4 changed files with 260 additions and 143 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
#import "fmt.odin" #import "fmt.odin"
main :: proc() { main :: proc() {
x := ?123 fmt.println(123)
} }
-6
View File
@@ -69,7 +69,6 @@ String ssa_mangle_name(ssaGen *s, String path, String name) {
void ssa_gen_tree(ssaGen *s) { void ssa_gen_tree(ssaGen *s) {
ssaModule *m = &s->module; ssaModule *m = &s->module;
CheckerInfo *info = m->info; CheckerInfo *info = m->info;
gbAllocator a = m->allocator; gbAllocator a = m->allocator;
@@ -677,12 +676,7 @@ void ssa_gen_tree(ssaGen *s) {
ssa_build_proc(m->procs[i], m->procs[i]->Proc.parent); ssa_build_proc(m->procs[i], m->procs[i]->Proc.parent);
} }
// m->layout = make_string("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"); // m->layout = make_string("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
} }
+39 -9
View File
@@ -500,8 +500,12 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
} }
void ssa_print_block_name(ssaFileBuffer *f, ssaBlock *b) { void ssa_print_block_name(ssaFileBuffer *f, ssaBlock *b) {
if (b != NULL) {
ssa_print_escape_string(f, b->label, false); ssa_print_escape_string(f, b->label, false);
ssa_fprintf(f, "-%d", b->id); ssa_fprintf(f, "-%td", b->index);
} else {
ssa_fprintf(f, "<INVALID-BLOCK>");
}
} }
void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type_hint) { void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type_hint) {
@@ -648,6 +652,32 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
ssa_fprintf(f, "\n"); ssa_fprintf(f, "\n");
} break; } break;
case ssaInstr_Phi: {
ssa_fprintf(f, "%%%d = phi ", value->id);
ssa_print_type(f, m, instr->Phi.type);
ssa_fprintf(f, " ", value->id);
for (isize i = 0; i < instr->Phi.edges.count; i++) {
ssaValue *edge = instr->Phi.edges[i];
if (i > 0) {
ssa_fprintf(f, ", ");
}
ssaBlock *block = NULL;
if (instr->parent != NULL &&
i < instr->parent->preds.count) {
block = instr->parent->preds[i];
}
ssa_fprintf(f, "[ ");
ssa_print_value(f, m, edge, instr->Phi.type);
ssa_fprintf(f, ", %%");
ssa_print_block_name(f, block);
ssa_fprintf(f, " ]");
}
ssa_fprintf(f, "\n");
} break;
case ssaInstr_ExtractValue: { case ssaInstr_ExtractValue: {
Type *et = instr->ExtractValue.elem_type; Type *et = instr->ExtractValue.elem_type;
ssa_fprintf(f, "%%%d = extractvalue ", value->id); ssa_fprintf(f, "%%%d = extractvalue ", value->id);
@@ -721,12 +751,12 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
ssa_fprintf(f, "%%%d = ", value->id); ssa_fprintf(f, "%%%d = ", value->id);
if (gb_is_between(bo->op.kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) { if (gb_is_between(bo->op, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
if (is_type_string(elem_type)) { if (is_type_string(elem_type)) {
ssa_fprintf(f, "call "); ssa_fprintf(f, "call ");
ssa_print_type(f, m, t_bool); ssa_print_type(f, m, t_bool);
char *runtime_proc = ""; char *runtime_proc = "";
switch (bo->op.kind) { switch (bo->op) {
case Token_CmpEq: runtime_proc = "__string_eq"; break; case Token_CmpEq: runtime_proc = "__string_eq"; break;
case Token_NotEq: runtime_proc = "__string_ne"; break; case Token_NotEq: runtime_proc = "__string_ne"; break;
case Token_Lt: runtime_proc = "__string_lt"; break; case Token_Lt: runtime_proc = "__string_lt"; break;
@@ -750,7 +780,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
} else if (is_type_float(elem_type)) { } else if (is_type_float(elem_type)) {
ssa_fprintf(f, "fcmp "); ssa_fprintf(f, "fcmp ");
switch (bo->op.kind) { switch (bo->op) {
case Token_CmpEq: ssa_fprintf(f, "oeq"); break; case Token_CmpEq: ssa_fprintf(f, "oeq"); break;
case Token_NotEq: ssa_fprintf(f, "one"); break; case Token_NotEq: ssa_fprintf(f, "one"); break;
case Token_Lt: ssa_fprintf(f, "olt"); break; case Token_Lt: ssa_fprintf(f, "olt"); break;
@@ -760,15 +790,15 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
} }
} else { } else {
ssa_fprintf(f, "icmp "); ssa_fprintf(f, "icmp ");
if (bo->op.kind != Token_CmpEq && if (bo->op != Token_CmpEq &&
bo->op.kind != Token_NotEq) { bo->op != Token_NotEq) {
if (is_type_unsigned(elem_type)) { if (is_type_unsigned(elem_type)) {
ssa_fprintf(f, "u"); ssa_fprintf(f, "u");
} else { } else {
ssa_fprintf(f, "s"); ssa_fprintf(f, "s");
} }
} }
switch (bo->op.kind) { switch (bo->op) {
case Token_CmpEq: ssa_fprintf(f, "eq"); break; case Token_CmpEq: ssa_fprintf(f, "eq"); break;
case Token_NotEq: ssa_fprintf(f, "ne"); break; case Token_NotEq: ssa_fprintf(f, "ne"); break;
case Token_Lt: ssa_fprintf(f, "lt"); break; case Token_Lt: ssa_fprintf(f, "lt"); break;
@@ -781,7 +811,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
if (is_type_float(elem_type)) if (is_type_float(elem_type))
ssa_fprintf(f, "f"); ssa_fprintf(f, "f");
switch (bo->op.kind) { switch (bo->op) {
case Token_Add: ssa_fprintf(f, "add"); break; case Token_Add: ssa_fprintf(f, "add"); break;
case Token_Sub: ssa_fprintf(f, "sub"); break; case Token_Sub: ssa_fprintf(f, "sub"); break;
case Token_And: ssa_fprintf(f, "and"); break; case Token_And: ssa_fprintf(f, "and"); break;
@@ -800,7 +830,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
else ssa_fprintf(f, "s"); else ssa_fprintf(f, "s");
} }
switch (bo->op.kind) { switch (bo->op) {
case Token_Quo: ssa_fprintf(f, "div"); break; case Token_Quo: ssa_fprintf(f, "div"); break;
case Token_Mod: ssa_fprintf(f, "rem"); break; case Token_Mod: ssa_fprintf(f, "rem"); break;
} }
+219 -126
View File
@@ -69,7 +69,7 @@ struct ssaModule {
struct ssaBlock { struct ssaBlock {
i32 id; isize index;
AstNode *node; AstNode *node;
Scope *scope; Scope *scope;
isize scope_index; isize scope_index;
@@ -266,12 +266,12 @@ struct ssaInstr {
ssaValue *false_value; ssaValue *false_value;
} Select; } Select;
struct { struct {
String comment;
Array<ssaValue *> edges; Array<ssaValue *> edges;
Type *type;
} Phi; } Phi;
struct { struct {
Type *type; Type *type;
Token op; TokenKind op;
ssaValue *left, *right; ssaValue *left, *right;
} BinaryOp; } BinaryOp;
struct { struct {
@@ -513,6 +513,8 @@ Type *ssa_type(ssaInstr *instr) {
return instr->Load.type; return instr->Load.type;
case ssaInstr_GetElementPtr: case ssaInstr_GetElementPtr:
return instr->GetElementPtr.result_type; return instr->GetElementPtr.result_type;
case ssaInstr_Phi:
return instr->Phi.type;
case ssaInstr_ExtractValue: case ssaInstr_ExtractValue:
return instr->ExtractValue.result_type; return instr->ExtractValue.result_type;
case ssaInstr_InsertValue: case ssaInstr_InsertValue:
@@ -742,7 +744,7 @@ ssaValue *ssa_make_instr_insert_value(ssaProcedure *p, ssaValue *value, ssaValue
} }
ssaValue *ssa_make_instr_binary_op(ssaProcedure *p, Token op, ssaValue *left, ssaValue *right, Type *type) { ssaValue *ssa_make_instr_binary_op(ssaProcedure *p, TokenKind op, ssaValue *left, ssaValue *right, Type *type) {
ssaValue *v = ssa_alloc_instr(p, ssaInstr_BinaryOp); ssaValue *v = ssa_alloc_instr(p, ssaInstr_BinaryOp);
ssaInstr *i = &v->Instr; ssaInstr *i = &v->Instr;
i->BinaryOp.op = op; i->BinaryOp.op = op;
@@ -761,6 +763,14 @@ ssaValue *ssa_make_instr_br(ssaProcedure *p, ssaValue *cond, ssaBlock *true_bloc
return v; return v;
} }
ssaValue *ssa_make_instr_phi(ssaProcedure *p, Array<ssaValue *> edges, Type *type) {
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Phi);
ssaInstr *i = &v->Instr;
i->Phi.edges = edges;
i->Phi.type = type;
return v;
}
ssaValue *ssa_make_instr_unreachable(ssaProcedure *p) { ssaValue *ssa_make_instr_unreachable(ssaProcedure *p) {
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Unreachable); ssaValue *v = ssa_alloc_instr(p, ssaInstr_Unreachable);
return v; return v;
@@ -1065,7 +1075,7 @@ Type *ssa_addr_type(ssaAddr lval) {
return NULL; return NULL;
} }
ssaBlock *ssa__make_block(ssaProcedure *proc, AstNode *node, String label) { ssaBlock *ssa_add_block(ssaProcedure *proc, AstNode *node, char *label) {
Scope *scope = NULL; Scope *scope = NULL;
if (node != NULL) { if (node != NULL) {
Scope **found = map_get(&proc->module->info->scopes, hash_pointer(node)); Scope **found = map_get(&proc->module->info->scopes, hash_pointer(node));
@@ -1076,12 +1086,8 @@ ssaBlock *ssa__make_block(ssaProcedure *proc, AstNode *node, String label) {
} }
} }
ssaValue *block = ssa_make_value_block(proc, node, scope, label); ssaValue *value = ssa_make_value_block(proc, node, scope, make_string(label));
return &block->Block; ssaBlock *block = &value->Block;
}
ssaBlock *ssa_add_block(ssaProcedure *proc, AstNode *node, String label) {
ssaBlock *block = ssa__make_block(proc, node, label);
array_add(&proc->blocks, block); array_add(&proc->blocks, block);
return block; return block;
} }
@@ -1091,13 +1097,12 @@ void ssa_emit_no_op(ssaProcedure *proc);
void ssa_emit_jump(ssaProcedure *proc, ssaBlock *block); void ssa_emit_jump(ssaProcedure *proc, ssaBlock *block);
void ssa_build_defer_stmt(ssaProcedure *proc, ssaDefer d) { void ssa_build_defer_stmt(ssaProcedure *proc, ssaDefer d) {
ssaBlock *b = ssa__make_block(proc, NULL, make_string("defer")); ssaBlock *b = ssa_add_block(proc, NULL, "defer");
// NOTE(bill): The prev block may defer injection before it's terminator // NOTE(bill): The prev block may defer injection before it's terminator
ssaInstr *last_instr = ssa_get_last_instr(proc->curr_block); ssaInstr *last_instr = ssa_get_last_instr(proc->curr_block);
if (last_instr == NULL || !ssa_is_instr_terminating(last_instr)) { if (last_instr == NULL || !ssa_is_instr_terminating(last_instr)) {
ssa_emit_jump(proc, b); ssa_emit_jump(proc, b);
} }
array_add(&proc->blocks, b);
proc->curr_block = b; proc->curr_block = b;
ssa_emit_comment(proc, make_string("defer")); ssa_emit_comment(proc, make_string("defer"));
if (d.kind == ssaDefer_Node) { if (d.kind == ssaDefer_Node) {
@@ -1228,8 +1233,8 @@ void ssa_begin_procedure_body(ssaProcedure *proc) {
array_init(&proc->defer_stmts, gb_heap_allocator()); array_init(&proc->defer_stmts, gb_heap_allocator());
array_init(&proc->children, gb_heap_allocator()); array_init(&proc->children, gb_heap_allocator());
proc->decl_block = ssa_add_block(proc, proc->type_expr, make_string("decls")); proc->decl_block = ssa_add_block(proc, proc->type_expr, "decls");
proc->entry_block = ssa_add_block(proc, proc->type_expr, make_string("entry")); proc->entry_block = ssa_add_block(proc, proc->type_expr, "entry");
proc->curr_block = proc->entry_block; proc->curr_block = proc->entry_block;
if (proc->type->Proc.params != NULL) { if (proc->type->Proc.params != NULL) {
@@ -1241,6 +1246,92 @@ void ssa_begin_procedure_body(ssaProcedure *proc) {
} }
} }
void ssa_remove_pred(ssaBlock *a, ssaBlock *b) {
}
void ssa_remove_dead_blocks(ssaProcedure *proc) {
isize j = 0;
for_array(i, proc->blocks) {
ssaBlock *b = proc->blocks[i];
if (b != NULL) {
// NOTE(bill): Swap order
b->index = j;
proc->blocks[j] = b;
j++;
}
}
proc->blocks.count = j;
}
void ssa_mark_reachable(ssaBlock *b) {
isize const WHITE = 0;
isize const BLACK = -1;
b->index = BLACK;
for_array(i, b->succs) {
ssaBlock *succ = b->succs[i];
if (succ->index == WHITE) {
ssa_mark_reachable(succ);
}
}
}
void ssa_remove_unreachable_blocks(ssaProcedure *proc) {
isize const WHITE = 0;
isize const BLACK = -1;
for_array(i, proc->blocks) {
proc->blocks[i]->index = WHITE;
}
ssa_mark_reachable(proc->blocks[0]);
for_array(i, proc->blocks) {
ssaBlock *b = proc->blocks[i];
if (b->index == WHITE) {
for_array(j, b->succs) {
ssaBlock *c = b->succs[j];
if (c->index == BLACK) {
// ssa_remove_pred(c, b);
}
}
// NOTE(bill): Mark as empty but don't actually free it
// As it's been allocated with an arena
proc->blocks[i] = NULL;
}
}
ssa_remove_dead_blocks(proc);
}
void ssa_optimize_blocks(ssaProcedure *proc) {
ssa_remove_unreachable_blocks(proc);
#if 0
b32 changed = false;
do {
for_array(i, proc->blocks) {
ssaBlock *b = proc->blocks[i];
if (b == NULL) {
continue;
}
// if (ssa_fuse_blocks(proc, b)) {
// changed = true;
// }
if (ssa_jump_threading(proc, b)) {
// x -> y -> z becomes x -> z if y is just a jump
changed = true;
continue;
}
}
} while (changed);
#endif
ssa_remove_dead_blocks(proc);
}
void ssa_end_procedure_body(ssaProcedure *proc) { void ssa_end_procedure_body(ssaProcedure *proc) {
if (proc->type->Proc.result_count == 0) { if (proc->type->Proc.result_count == 0) {
ssa_emit_ret(proc, NULL); ssa_emit_ret(proc, NULL);
@@ -1253,12 +1344,13 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
proc->curr_block = proc->decl_block; proc->curr_block = proc->decl_block;
ssa_emit_jump(proc, proc->entry_block); ssa_emit_jump(proc, proc->entry_block);
ssa_optimize_blocks(proc);
// Number blocks and registers // Number blocks and registers
i32 reg_id = 0; i32 reg_id = 0;
for_array(i, proc->blocks) { for_array(i, proc->blocks) {
ssaBlock *b = proc->blocks[i]; ssaBlock *b = proc->blocks[i];
b->id = i;
for_array(j, b->instrs) { for_array(j, b->instrs) {
ssaValue *value = b->instrs[j]; ssaValue *value = b->instrs[j];
GB_ASSERT(value->kind == ssaValue_Instr); GB_ASSERT(value->kind == ssaValue_Instr);
@@ -1300,17 +1392,17 @@ void ssa_pop_target_list(ssaProcedure *proc) {
ssaValue *ssa_emit_arith(ssaProcedure *proc, Token op, ssaValue *left, ssaValue *right, Type *type) { ssaValue *ssa_emit_arith(ssaProcedure *proc, TokenKind op, ssaValue *left, ssaValue *right, Type *type) {
switch (op.kind) { switch (op) {
case Token_AndNot: { case Token_AndNot: {
// NOTE(bill): x &~ y == x & (~y) == x & (y ~ -1) // NOTE(bill): x &~ y == x & (~y) == x & (y ~ -1)
// NOTE(bill): "not" `x` == `x` "xor" `-1` // NOTE(bill): "not" `x` == `x` "xor" `-1`
ssaValue *neg = ssa_add_module_constant(proc->module, type, make_exact_value_integer(-1)); ssaValue *neg = ssa_add_module_constant(proc->module, type, make_exact_value_integer(-1));
op.kind = Token_Xor; op = Token_Xor;
right = ssa_emit_arith(proc, op, right, neg, type); right = ssa_emit_arith(proc, op, right, neg, type);
GB_ASSERT(right->Instr.kind == ssaInstr_BinaryOp); GB_ASSERT(right->Instr.kind == ssaInstr_BinaryOp);
right->Instr.BinaryOp.type = type; right->Instr.BinaryOp.type = type;
op.kind = Token_And; op = Token_And;
} /* fallthrough */ } /* fallthrough */
case Token_Add: case Token_Add:
case Token_Sub: case Token_Sub:
@@ -1328,7 +1420,7 @@ ssaValue *ssa_emit_arith(ssaProcedure *proc, Token op, ssaValue *left, ssaValue
return ssa_emit(proc, ssa_make_instr_binary_op(proc, op, left, right, type)); return ssa_emit(proc, ssa_make_instr_binary_op(proc, op, left, right, type));
} }
ssaValue *ssa_emit_comp(ssaProcedure *proc, Token op, ssaValue *left, ssaValue *right) { ssaValue *ssa_emit_comp(ssaProcedure *proc, TokenKind op_kind, ssaValue *left, ssaValue *right) {
Type *a = base_type(ssa_type(left)); Type *a = base_type(ssa_type(left));
Type *b = base_type(ssa_type(right)); Type *b = base_type(ssa_type(right));
@@ -1344,7 +1436,7 @@ ssaValue *ssa_emit_comp(ssaProcedure *proc, Token op, ssaValue *left, ssaValue *
if (is_type_vector(a)) { if (is_type_vector(a)) {
result = make_type_vector(proc->module->allocator, t_bool, a->Vector.count); result = make_type_vector(proc->module->allocator, t_bool, a->Vector.count);
} }
return ssa_emit(proc, ssa_make_instr_binary_op(proc, op, left, right, result)); return ssa_emit(proc, ssa_make_instr_binary_op(proc, op_kind, left, right, result));
} }
ssaValue *ssa_emit_ptr_offset(ssaProcedure *proc, ssaValue *ptr, ssaValue *offset) { ssaValue *ssa_emit_ptr_offset(ssaProcedure *proc, ssaValue *ptr, ssaValue *offset) {
@@ -1601,9 +1693,8 @@ ssaValue *ssa_add_local_slice(ssaProcedure *proc, Type *slice_type, ssaValue *ba
} }
GB_ASSERT(max != NULL); GB_ASSERT(max != NULL);
Token op_sub = {Token_Sub}; ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
ssaValue *len = ssa_emit_arith(proc, op_sub, high, low, t_int); ssaValue *cap = ssa_emit_arith(proc, Token_Sub, max, low, t_int);
ssaValue *cap = ssa_emit_arith(proc, op_sub, max, low, t_int);
ssaValue *elem = NULL; ssaValue *elem = NULL;
switch (bt->kind) { switch (bt->kind) {
@@ -1779,8 +1870,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
// integer -> boolean // integer -> boolean
if (is_type_integer(src) && is_type_boolean(dst)) { if (is_type_integer(src) && is_type_boolean(dst)) {
Token op = {Token_NotEq}; return ssa_emit_comp(proc, Token_NotEq, value, v_zero);
return ssa_emit_comp(proc, op, value, v_zero);
} }
@@ -2013,9 +2103,10 @@ void ssa_build_cond(ssaProcedure *proc, AstNode *cond, ssaBlock *true_block, ssa
ssaValue *ssa_emit_logical_binary_expr(ssaProcedure *proc, AstNode *expr) { ssaValue *ssa_emit_logical_binary_expr(ssaProcedure *proc, AstNode *expr) {
ast_node(be, BinaryExpr, expr); ast_node(be, BinaryExpr, expr);
ssaBlock *true_ = ssa_add_block(proc, NULL, make_string("logical.cmp.true")); #if 0
ssaBlock *false_ = ssa_add_block(proc, NULL, make_string("logical.cmp.false")); ssaBlock *true_ = ssa_add_block(proc, NULL, "logical.cmp.true");
ssaBlock *done = ssa__make_block(proc, NULL, make_string("logical.cmp.done")); ssaBlock *false_ = ssa_add_block(proc, NULL, "logical.cmp.false");
ssaBlock *done = ssa_add_block(proc, NULL, "logical.cmp.done");
ssaValue *result = ssa_add_local_generated(proc, t_bool); ssaValue *result = ssa_add_local_generated(proc, t_bool);
ssa_build_cond(proc, expr, true_, false_); ssa_build_cond(proc, expr, true_, false_);
@@ -2028,10 +2119,48 @@ ssaValue *ssa_emit_logical_binary_expr(ssaProcedure *proc, AstNode *expr) {
ssa_emit_store(proc, result, v_false); ssa_emit_store(proc, result, v_false);
ssa_emit_jump(proc, done); ssa_emit_jump(proc, done);
array_add(&proc->blocks, done);
proc->curr_block = done; proc->curr_block = done;
return ssa_emit_load(proc, result); return ssa_emit_load(proc, result);
#else
ssaBlock *rhs = ssa_add_block(proc, NULL, "logical.cmp.rhs");
ssaBlock *done = ssa_add_block(proc, NULL, "logical.cmp.done");
Type *type = type_of_expr(proc->module->info, expr);
type = default_type(type);
ssaValue *short_circuit = NULL;
if (be->op.kind == Token_CmpAnd) {
ssa_build_cond(proc, be->left, rhs, done);
short_circuit = v_false;
} else if (be->op.kind == Token_CmpOr) {
ssa_build_cond(proc, be->left, done, rhs);
short_circuit = v_true;
}
if (rhs->preds.count == 0) {
proc->curr_block = done;
return short_circuit;
}
if (done->preds.count == 0) {
proc->curr_block = rhs;
return ssa_build_expr(proc, be->right);
}
Array<ssaValue *> edges = {};
array_init(&edges, proc->module->allocator, done->preds.count+1);
for_array(i, done->preds) {
array_add(&edges, short_circuit);
}
proc->curr_block = rhs;
array_add(&edges, ssa_build_expr(proc, be->right));
ssa_emit_jump(proc, done);
proc->curr_block = done;
return ssa_emit(proc, ssa_make_instr_phi(proc, edges, type));
#endif
} }
@@ -2125,14 +2254,14 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
return ssa_build_expr(proc, ue->expr); return ssa_build_expr(proc, ue->expr);
case Token_Sub: // NOTE(bill): -`x` == 0 - `x` case Token_Sub: // NOTE(bill): -`x` == 0 - `x`
return ssa_emit_arith(proc, ue->op, v_zero, ssa_build_expr(proc, ue->expr), tv->type); return ssa_emit_arith(proc, ue->op.kind, v_zero, ssa_build_expr(proc, ue->expr), tv->type);
case Token_Not: // Boolean not case Token_Not: // Boolean not
case Token_Xor: { // Bitwise not case Token_Xor: { // Bitwise not
// NOTE(bill): "not" `x` == `x` "xor" `-1` // NOTE(bill): "not" `x` == `x` "xor" `-1`
ssaValue *left = ssa_build_expr(proc, ue->expr); ssaValue *left = ssa_build_expr(proc, ue->expr);
ssaValue *right = ssa_add_module_constant(proc->module, tv->type, make_exact_value_integer(-1)); ssaValue *right = ssa_add_module_constant(proc->module, tv->type, make_exact_value_integer(-1));
return ssa_emit_arith(proc, ue->op, return ssa_emit_arith(proc, ue->op.kind,
left, right, left, right,
tv->type); tv->type);
} break; } break;
@@ -2152,7 +2281,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case Token_AndNot: case Token_AndNot:
case Token_Shl: case Token_Shl:
case Token_Shr: case Token_Shr:
return ssa_emit_arith(proc, be->op, return ssa_emit_arith(proc, be->op.kind,
ssa_build_expr(proc, be->left), ssa_build_expr(proc, be->left),
ssa_build_expr(proc, be->right), ssa_build_expr(proc, be->right),
tv->type); tv->type);
@@ -2167,7 +2296,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssaValue *left = ssa_build_expr(proc, be->left); ssaValue *left = ssa_build_expr(proc, be->left);
ssaValue *right = ssa_build_expr(proc, be->right); ssaValue *right = ssa_build_expr(proc, be->right);
ssaValue *cmp = ssa_emit_comp(proc, be->op, left, right); ssaValue *cmp = ssa_emit_comp(proc, be->op.kind, left, right);
return ssa_emit_conv(proc, cmp, default_type(tv->type)); return ssa_emit_conv(proc, cmp, default_type(tv->type));
} break; } break;
@@ -2420,8 +2549,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssa_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, cap, false); ssa_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, cap, false);
Token mul = {Token_Mul}; ssaValue *slice_size = ssa_emit_arith(proc, Token_Mul, elem_size, cap, t_int);
ssaValue *slice_size = ssa_emit_arith(proc, mul, elem_size, cap, t_int);
ssaValue **args = gb_alloc_array(allocator, ssaValue *, 2); ssaValue **args = gb_alloc_array(allocator, ssaValue *, 2);
args[0] = slice_size; args[0] = slice_size;
@@ -2445,10 +2573,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssaValue *cond = ssa_build_expr(proc, ce->args[0]); ssaValue *cond = ssa_build_expr(proc, ce->args[0]);
GB_ASSERT(is_type_boolean(ssa_type(cond))); GB_ASSERT(is_type_boolean(ssa_type(cond)));
Token eq = {Token_CmpEq}; cond = ssa_emit_comp(proc, Token_CmpEq, cond, v_false);
cond = ssa_emit_comp(proc, eq, cond, v_false); ssaBlock *err = ssa_add_block(proc, NULL, "builtin.assert.err");
ssaBlock *err = ssa_add_block(proc, NULL, make_string("builtin.assert.err")); ssaBlock *done = ssa_add_block(proc, NULL, "builtin.assert.done");
ssaBlock *done = ssa__make_block(proc, NULL, make_string("builtin.assert.done"));
ssa_emit_if(proc, cond, err, done); ssa_emit_if(proc, cond, err, done);
proc->curr_block = err; proc->curr_block = err;
@@ -2471,7 +2598,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssa_emit_global_call(proc, "__assert", args, 4); ssa_emit_global_call(proc, "__assert", args, 4);
ssa_emit_jump(proc, done); ssa_emit_jump(proc, done);
array_add(&proc->blocks, done);
proc->curr_block = done; proc->curr_block = done;
return NULL; return NULL;
@@ -2515,12 +2641,11 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssaValue *len_dst = ssa_slice_len(proc, dst_slice); ssaValue *len_dst = ssa_slice_len(proc, dst_slice);
ssaValue *len_src = ssa_slice_len(proc, src_slice); ssaValue *len_src = ssa_slice_len(proc, src_slice);
Token lt = {Token_Lt}; ssaValue *cond = ssa_emit_comp(proc, Token_Lt, len_dst, len_src);
ssaValue *cond = ssa_emit_comp(proc, lt, len_dst, len_src);
ssaValue *len = ssa_emit_select(proc, cond, len_dst, len_src); ssaValue *len = ssa_emit_select(proc, cond, len_dst, len_src);
Token mul = {Token_Mul};
ssaValue *elem_size = ssa_make_const_int(proc->module->allocator, size_of_elem); ssaValue *elem_size = ssa_make_const_int(proc->module->allocator, size_of_elem);
ssaValue *byte_count = ssa_emit_arith(proc, mul, len, elem_size, t_int); ssaValue *byte_count = ssa_emit_arith(proc, Token_Mul, len, elem_size, t_int);
ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 3); ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 3);
args[0] = dst; args[0] = dst;
@@ -2553,10 +2678,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
// NOTE(bill): Check if can append is possible // NOTE(bill): Check if can append is possible
Token lt = {Token_Lt}; ssaValue *cond = ssa_emit_comp(proc, Token_Lt, len, cap);
ssaValue *cond = ssa_emit_comp(proc, lt, len, cap); ssaBlock *able = ssa_add_block(proc, NULL, "builtin.append.able");
ssaBlock *able = ssa_add_block(proc, NULL, make_string("builtin.append.able")); ssaBlock *done = ssa_add_block(proc, NULL, "builtin.append.done");
ssaBlock *done = ssa__make_block(proc, NULL, make_string("builtin.append.done"));
ssa_emit_if(proc, cond, able, done); ssa_emit_if(proc, cond, able, done);
proc->curr_block = able; proc->curr_block = able;
@@ -2579,13 +2703,11 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssa_emit_global_call(proc, "__mem_copy", args, 3); ssa_emit_global_call(proc, "__mem_copy", args, 3);
// Increment slice length // Increment slice length
Token add = {Token_Add}; ssaValue *new_len = ssa_emit_arith(proc, Token_Add, len, v_one, t_int);
ssaValue *new_len = ssa_emit_arith(proc, add, len, v_one, t_int);
ssaValue *gep = ssa_emit_struct_gep(proc, slice_ptr, v_one32, t_int); ssaValue *gep = ssa_emit_struct_gep(proc, slice_ptr, v_one32, t_int);
ssa_emit_store(proc, gep, new_len); ssa_emit_store(proc, gep, new_len);
ssa_emit_jump(proc, done); ssa_emit_jump(proc, done);
array_add(&proc->blocks, done);
proc->curr_block = done; proc->curr_block = done;
return ssa_emit_conv(proc, cond, t_bool, true); return ssa_emit_conv(proc, cond, t_bool, true);
@@ -2627,12 +2749,11 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
Type *ptr_type = base_type(ssa_type(ptr_a)); Type *ptr_type = base_type(ssa_type(ptr_a));
GB_ASSERT(ptr_type->kind == Type_Pointer); GB_ASSERT(ptr_type->kind == Type_Pointer);
isize elem_size = type_size_of(proc->module->sizes, proc->module->allocator, ptr_type->Pointer.elem); isize elem_size = type_size_of(proc->module->sizes, proc->module->allocator, ptr_type->Pointer.elem);
Token sub = {Token_Sub};
ssaValue *v = ssa_emit_arith(proc, sub, ptr_a, ptr_b, t_int); ssaValue *v = ssa_emit_arith(proc, Token_Sub, ptr_a, ptr_b, t_int);
if (elem_size > 1) { if (elem_size > 1) {
Token quo = {Token_Quo};
ssaValue *ez = ssa_make_const_int(proc->module->allocator, elem_size); ssaValue *ez = ssa_make_const_int(proc->module->allocator, elem_size);
v = ssa_emit_arith(proc, quo, v, ez, t_int); v = ssa_emit_arith(proc, Token_Quo, v, ez, t_int);
} }
return v; return v;
@@ -2665,8 +2786,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssaValue *x = ssa_build_expr(proc, ce->args[0]); ssaValue *x = ssa_build_expr(proc, ce->args[0]);
ssaValue *y = ssa_build_expr(proc, ce->args[1]); ssaValue *y = ssa_build_expr(proc, ce->args[1]);
Type *t = base_type(ssa_type(x)); Type *t = base_type(ssa_type(x));
Token lt = {Token_Lt}; ssaValue *cond = ssa_emit_comp(proc, Token_Lt, x, y);
ssaValue *cond = ssa_emit_comp(proc, lt, x, y);
return ssa_emit_select(proc, cond, x, y); return ssa_emit_select(proc, cond, x, y);
} break; } break;
@@ -2675,21 +2795,18 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssaValue *x = ssa_build_expr(proc, ce->args[0]); ssaValue *x = ssa_build_expr(proc, ce->args[0]);
ssaValue *y = ssa_build_expr(proc, ce->args[1]); ssaValue *y = ssa_build_expr(proc, ce->args[1]);
Type *t = base_type(ssa_type(x)); Type *t = base_type(ssa_type(x));
Token gt = {Token_Gt}; ssaValue *cond = ssa_emit_comp(proc, Token_Gt, x, y);
ssaValue *cond = ssa_emit_comp(proc, gt, x, y);
return ssa_emit_select(proc, cond, x, y); return ssa_emit_select(proc, cond, x, y);
} break; } break;
case BuiltinProc_abs: { case BuiltinProc_abs: {
ssa_emit_comment(proc, make_string("abs")); ssa_emit_comment(proc, make_string("abs"));
Token lt = {Token_Lt};
Token sub = {Token_Sub};
ssaValue *x = ssa_build_expr(proc, ce->args[0]); ssaValue *x = ssa_build_expr(proc, ce->args[0]);
Type *t = ssa_type(x); Type *t = ssa_type(x);
ssaValue *neg_x = ssa_emit_arith(proc, sub, v_zero, x, t); ssaValue *neg_x = ssa_emit_arith(proc, Token_Sub, v_zero, x, t);
ssaValue *cond = ssa_emit_comp(proc, lt, x, v_zero); ssaValue *cond = ssa_emit_comp(proc, Token_Lt, x, v_zero);
return ssa_emit_select(proc, cond, neg_x, x); return ssa_emit_select(proc, cond, neg_x, x);
} break; } break;
@@ -3117,10 +3234,9 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
ssa_slice_bounds_check(proc, se->open, low, high, max, false); ssa_slice_bounds_check(proc, se->open, low, high, max, false);
Token op_sub = {Token_Sub};
ssaValue *elem = ssa_slice_elem(proc, base); ssaValue *elem = ssa_slice_elem(proc, base);
ssaValue *len = ssa_emit_arith(proc, op_sub, high, low, t_int); ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
ssaValue *cap = ssa_emit_arith(proc, op_sub, max, low, t_int); ssaValue *cap = ssa_emit_arith(proc, Token_Sub, max, low, t_int);
ssaValue *slice = ssa_add_local_generated(proc, slice_type); ssaValue *slice = ssa_add_local_generated(proc, slice_type);
ssaValue *gep0 = ssa_emit_struct_gep(proc, slice, v_zero32, ssa_type(elem)); ssaValue *gep0 = ssa_emit_struct_gep(proc, slice, v_zero32, ssa_type(elem));
@@ -3142,10 +3258,9 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
ssa_slice_bounds_check(proc, se->open, low, high, max, false); ssa_slice_bounds_check(proc, se->open, low, high, max, false);
Token op_sub = {Token_Sub};
ssaValue *elem = ssa_array_elem(proc, addr); ssaValue *elem = ssa_array_elem(proc, addr);
ssaValue *len = ssa_emit_arith(proc, op_sub, high, low, t_int); ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
ssaValue *cap = ssa_emit_arith(proc, op_sub, max, low, t_int); ssaValue *cap = ssa_emit_arith(proc, Token_Sub, max, low, t_int);
ssaValue *slice = ssa_add_local_generated(proc, slice_type); ssaValue *slice = ssa_add_local_generated(proc, slice_type);
ssaValue *gep0 = ssa_emit_struct_gep(proc, slice, v_zero32, ssa_type(elem)); ssaValue *gep0 = ssa_emit_struct_gep(proc, slice, v_zero32, ssa_type(elem));
@@ -3166,9 +3281,8 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
ssa_slice_bounds_check(proc, se->open, low, high, high, true); ssa_slice_bounds_check(proc, se->open, low, high, high, true);
Token op_sub = {Token_Sub};
ssaValue *elem, *len; ssaValue *elem, *len;
len = ssa_emit_arith(proc, op_sub, high, low, t_int); len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
elem = ssa_string_elem(proc, base); elem = ssa_string_elem(proc, base);
elem = ssa_emit_ptr_offset(proc, elem, low); elem = ssa_emit_ptr_offset(proc, elem, low);
@@ -3231,7 +3345,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
return ssa_make_addr(NULL, NULL); return ssa_make_addr(NULL, NULL);
} }
void ssa_build_assign_op(ssaProcedure *proc, ssaAddr lhs, ssaValue *value, Token op) { void ssa_build_assign_op(ssaProcedure *proc, ssaAddr lhs, ssaValue *value, TokenKind op) {
ssaValue *old_value = ssa_lvalue_load(proc, lhs); ssaValue *old_value = ssa_lvalue_load(proc, lhs);
Type *type = ssa_type(old_value); Type *type = ssa_type(old_value);
ssaValue *change = ssa_emit_conv(proc, value, type); ssaValue *change = ssa_emit_conv(proc, value, type);
@@ -3255,13 +3369,13 @@ void ssa_build_cond(ssaProcedure *proc, AstNode *cond, ssaBlock *true_block, ssa
case_ast_node(be, BinaryExpr, cond); case_ast_node(be, BinaryExpr, cond);
if (be->op.kind == Token_CmpAnd) { if (be->op.kind == Token_CmpAnd) {
ssaBlock *block = ssa_add_block(proc, NULL, make_string("cmp.and")); ssaBlock *block = ssa_add_block(proc, NULL, "cmp.and");
ssa_build_cond(proc, be->left, block, false_block); ssa_build_cond(proc, be->left, block, false_block);
proc->curr_block = block; proc->curr_block = block;
ssa_build_cond(proc, be->right, true_block, false_block); ssa_build_cond(proc, be->right, true_block, false_block);
return; return;
} else if (be->op.kind == Token_CmpOr) { } else if (be->op.kind == Token_CmpOr) {
ssaBlock *block = ssa_add_block(proc, NULL, make_string("cmp.or")); ssaBlock *block = ssa_add_block(proc, NULL, "cmp.or");
ssa_build_cond(proc, be->left, true_block, block); ssa_build_cond(proc, be->left, true_block, block);
proc->curr_block = block; proc->curr_block = block;
ssa_build_cond(proc, be->right, true_block, false_block); ssa_build_cond(proc, be->right, true_block, false_block);
@@ -3497,11 +3611,11 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
case_ast_node(ids, IncDecStmt, node); case_ast_node(ids, IncDecStmt, node);
ssa_emit_comment(proc, make_string("IncDecStmt")); ssa_emit_comment(proc, make_string("IncDecStmt"));
Token op = ids->op; TokenKind op = ids->op.kind;
if (op.kind == Token_Increment) { if (op == Token_Increment) {
op.kind = Token_Add; op = Token_Add;
} else if (op.kind == Token_Decrement) { } else if (op == Token_Decrement) {
op.kind = Token_Sub; op = Token_Sub;
} }
ssaAddr lval = ssa_build_addr(proc, ids->expr); ssaAddr lval = ssa_build_addr(proc, ids->expr);
ssaValue *one = ssa_emit_conv(proc, v_one, ssa_addr_type(lval)); ssaValue *one = ssa_emit_conv(proc, v_one, ssa_addr_type(lval));
@@ -3577,13 +3691,11 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
default: { default: {
// NOTE(bill): Only 1 += 1 is allowed, no tuples // NOTE(bill): Only 1 += 1 is allowed, no tuples
// +=, -=, etc // +=, -=, etc
Token op = as->op; i32 op = cast(i32)as->op.kind;
i32 kind = op.kind; op += Token_Add - Token_AddEq; // Convert += to +
kind += Token_Add - Token_AddEq; // Convert += to +
op.kind = cast(TokenKind)kind;
ssaAddr lhs = ssa_build_addr(proc, as->lhs[0]); ssaAddr lhs = ssa_build_addr(proc, as->lhs[0]);
ssaValue *value = ssa_build_expr(proc, as->rhs[0]); ssaValue *value = ssa_build_expr(proc, as->rhs[0]);
ssa_build_assign_op(proc, lhs, value, op); ssa_build_assign_op(proc, lhs, value, cast(TokenKind)op);
} break; } break;
} }
case_end; case_end;
@@ -3658,16 +3770,16 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
case_ast_node(is, IfStmt, node); case_ast_node(is, IfStmt, node);
ssa_emit_comment(proc, make_string("IfStmt")); ssa_emit_comment(proc, make_string("IfStmt"));
if (is->init != NULL) { if (is->init != NULL) {
ssaBlock *init = ssa_add_block(proc, node, make_string("if.init")); ssaBlock *init = ssa_add_block(proc, node, "if.init");
ssa_emit_jump(proc, init); ssa_emit_jump(proc, init);
proc->curr_block = init; proc->curr_block = init;
ssa_build_stmt(proc, is->init); ssa_build_stmt(proc, is->init);
} }
ssaBlock *then = ssa_add_block(proc, node, make_string("if.then")); ssaBlock *then = ssa_add_block(proc, node, "if.then");
ssaBlock *done = ssa__make_block(proc, node, make_string("if.done")); // NOTE(bill): Append later ssaBlock *done = ssa_add_block(proc, node, "if.done"); // NOTE(bill): Append later
ssaBlock *else_ = done; ssaBlock *else_ = done;
if (is->else_stmt != NULL) { if (is->else_stmt != NULL) {
else_ = ssa_add_block(proc, is->else_stmt, make_string("if.else")); else_ = ssa_add_block(proc, is->else_stmt, "if.else");
} }
ssa_build_cond(proc, is->cond, then, else_); ssa_build_cond(proc, is->cond, then, else_);
@@ -3688,29 +3800,28 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
ssa_emit_jump(proc, done); ssa_emit_jump(proc, done);
} }
array_add(&proc->blocks, done);
proc->curr_block = done; proc->curr_block = done;
case_end; case_end;
case_ast_node(fs, ForStmt, node); case_ast_node(fs, ForStmt, node);
ssa_emit_comment(proc, make_string("ForStmt")); ssa_emit_comment(proc, make_string("ForStmt"));
if (fs->init != NULL) { if (fs->init != NULL) {
ssaBlock *init = ssa_add_block(proc, node, make_string("for.init")); ssaBlock *init = ssa_add_block(proc, node, "for.init");
ssa_emit_jump(proc, init); ssa_emit_jump(proc, init);
proc->curr_block = init; proc->curr_block = init;
ssa_build_stmt(proc, fs->init); ssa_build_stmt(proc, fs->init);
} }
ssaBlock *body = ssa_add_block(proc, node, make_string("for.body")); ssaBlock *body = ssa_add_block(proc, node, "for.body");
ssaBlock *done = ssa__make_block(proc, node, make_string("for.done")); // NOTE(bill): Append later ssaBlock *done = ssa_add_block(proc, node, "for.done"); // NOTE(bill): Append later
ssaBlock *loop = body; ssaBlock *loop = body;
if (fs->cond != NULL) { if (fs->cond != NULL) {
loop = ssa_add_block(proc, node, make_string("for.loop")); loop = ssa_add_block(proc, node, "for.loop");
} }
ssaBlock *cont = loop; ssaBlock *cont = loop;
if (fs->post != NULL) { if (fs->post != NULL) {
cont = ssa_add_block(proc, node, make_string("for.post")); cont = ssa_add_block(proc, node, "for.post");
} }
ssa_emit_jump(proc, loop); ssa_emit_jump(proc, loop);
@@ -3736,7 +3847,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
} }
array_add(&proc->blocks, done);
proc->curr_block = done; proc->curr_block = done;
case_end; case_end;
@@ -3750,11 +3860,10 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
if (ms->tag != NULL) { if (ms->tag != NULL) {
tag = ssa_build_expr(proc, ms->tag); tag = ssa_build_expr(proc, ms->tag);
} }
ssaBlock *done = ssa__make_block(proc, node, make_string("match.done")); // NOTE(bill): Append later ssaBlock *done = ssa_add_block(proc, node, "match.done"); // NOTE(bill): Append later
ast_node(body, BlockStmt, ms->body); ast_node(body, BlockStmt, ms->body);
AstNodeArray default_stmts = {}; AstNodeArray default_stmts = {};
ssaBlock *default_fall = NULL; ssaBlock *default_fall = NULL;
ssaBlock *default_block = NULL; ssaBlock *default_block = NULL;
@@ -3766,28 +3875,24 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
for_array(i, body->stmts) { for_array(i, body->stmts) {
AstNode *clause = body->stmts[i]; AstNode *clause = body->stmts[i];
ssaBlock *body = fall; ssaBlock *body = fall;
b32 append_body = false;
ast_node(cc, CaseClause, clause); ast_node(cc, CaseClause, clause);
if (body == NULL) { if (body == NULL) {
append_body = true;
if (cc->list.count == 0) { if (cc->list.count == 0) {
body = ssa__make_block(proc, clause, make_string("match.dflt.body")); body = ssa_add_block(proc, clause, "match.dflt.body");
} else { } else {
body = ssa__make_block(proc, clause, make_string("match.case.body")); body = ssa_add_block(proc, clause, "match.case.body");
} }
} }
if (append_fall && body == fall) { if (append_fall && body == fall) {
append_fall = false; append_fall = false;
append_body = true;
} }
fall = done; fall = done;
if (i+1 < case_count) { if (i+1 < case_count) {
append_fall = true; append_fall = true;
fall = ssa__make_block(proc, clause, make_string("match.fall.body")); fall = ssa_add_block(proc, clause, "match.fall.body");
} }
if (cc->list.count == 0) { if (cc->list.count == 0) {
@@ -3799,19 +3904,14 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
} }
ssaBlock *next_cond = NULL; ssaBlock *next_cond = NULL;
Token eq = {Token_CmpEq};
for_array(j, cc->list) { for_array(j, cc->list) {
AstNode *expr = cc->list[j]; AstNode *expr = cc->list[j];
next_cond = ssa__make_block(proc, clause, make_string("match.case.next")); next_cond = ssa_add_block(proc, clause, "match.case.next");
ssaValue *cond = ssa_emit_comp(proc, eq, tag, ssa_build_expr(proc, expr)); ssaValue *cond = ssa_emit_comp(proc, Token_CmpEq, tag, ssa_build_expr(proc, expr));
ssa_emit_if(proc, cond, body, next_cond); ssa_emit_if(proc, cond, body, next_cond);
array_add(&proc->blocks, next_cond);
proc->curr_block = next_cond; proc->curr_block = next_cond;
} }
if (append_body) {
array_add(&proc->blocks, body);
}
proc->curr_block = body; proc->curr_block = body;
ssa_push_target_list(proc, done, NULL, fall); ssa_push_target_list(proc, done, NULL, fall);
@@ -3826,7 +3926,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
if (default_block != NULL) { if (default_block != NULL) {
ssa_emit_jump(proc, default_block); ssa_emit_jump(proc, default_block);
array_add(&proc->blocks, default_block);
proc->curr_block = default_block; proc->curr_block = default_block;
ssa_push_target_list(proc, done, NULL, default_fall); ssa_push_target_list(proc, done, NULL, default_fall);
@@ -3837,7 +3936,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
} }
ssa_emit_jump(proc, done); ssa_emit_jump(proc, done);
array_add(&proc->blocks, done);
proc->curr_block = done; proc->curr_block = done;
case_end; case_end;
@@ -3856,11 +3954,11 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
ssaValue *data = ssa_emit_conv(proc, parent, t_rawptr); ssaValue *data = ssa_emit_conv(proc, parent, t_rawptr);
ssaBlock *start_block = ssa_add_block(proc, node, make_string("type-match.case.first")); ssaBlock *start_block = ssa_add_block(proc, node, "type-match.case.first");
ssa_emit_jump(proc, start_block); ssa_emit_jump(proc, start_block);
proc->curr_block = start_block; proc->curr_block = start_block;
ssaBlock *done = ssa__make_block(proc, node, make_string("type-match.done")); // NOTE(bill): Append later ssaBlock *done = ssa_add_block(proc, node, "type-match.done"); // NOTE(bill): Append later
ast_node(body, BlockStmt, ms->body); ast_node(body, BlockStmt, ms->body);
@@ -3878,12 +3976,12 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
if (cc->list.count == 0) { if (cc->list.count == 0) {
// default case // default case
default_stmts = cc->stmts; default_stmts = cc->stmts;
default_block = ssa__make_block(proc, clause, make_string("type-match.dflt.body")); default_block = ssa_add_block(proc, clause, "type-match.dflt.body");
continue; continue;
} }
ssaBlock *body = ssa__make_block(proc, clause, make_string("type-match.case.body")); ssaBlock *body = ssa_add_block(proc, clause, "type-match.case.body");
Scope *scope = *map_get(&proc->module->info->scopes, hash_pointer(clause)); Scope *scope = *map_get(&proc->module->info->scopes, hash_pointer(clause));
Entity *tag_var_entity = current_scope_lookup_entity(scope, tag_var_name); Entity *tag_var_entity = current_scope_lookup_entity(scope, tag_var_name);
@@ -3907,14 +4005,11 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
} }
GB_ASSERT(index != NULL); GB_ASSERT(index != NULL);
ssaBlock *next_cond = ssa__make_block(proc, clause, make_string("type-match.case.next")); ssaBlock *next_cond = ssa_add_block(proc, clause, "type-match.case.next");
Token eq = {Token_CmpEq}; ssaValue *cond = ssa_emit_comp(proc, Token_CmpEq, tag_index, index);
ssaValue *cond = ssa_emit_comp(proc, eq, tag_index, index);
ssa_emit_if(proc, cond, body, next_cond); ssa_emit_if(proc, cond, body, next_cond);
array_add(&proc->blocks, next_cond);
proc->curr_block = next_cond; proc->curr_block = next_cond;
array_add(&proc->blocks, body);
proc->curr_block = body; proc->curr_block = body;
ssa_push_target_list(proc, done, NULL, NULL); ssa_push_target_list(proc, done, NULL, NULL);
@@ -3929,7 +4024,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
if (default_block != NULL) { if (default_block != NULL) {
ssa_emit_jump(proc, default_block); ssa_emit_jump(proc, default_block);
array_add(&proc->blocks, default_block);
proc->curr_block = default_block; proc->curr_block = default_block;
ssa_push_target_list(proc, done, NULL, NULL); ssa_push_target_list(proc, done, NULL, NULL);
@@ -3940,7 +4034,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
} }
ssa_emit_jump(proc, done); ssa_emit_jump(proc, done);
array_add(&proc->blocks, done);
proc->curr_block = done; proc->curr_block = done;
case_end; case_end;