aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/ssa.cpp127
1 files changed, 117 insertions, 10 deletions
diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp
index 80f5b7e12..b93d42d21 100644
--- a/src/codegen/ssa.cpp
+++ b/src/codegen/ssa.cpp
@@ -840,7 +840,7 @@ ssaValue *ssa_make_instr_get_element_ptr(ssaProcedure *p, ssaValue *address,
i->GetElementPtr.indices[1] = index1;
i->GetElementPtr.index_count = index_count;
i->GetElementPtr.elem_type = ssa_type(address);
- i->GetElementPtr.inbounds = inbounds;
+
GB_ASSERT_MSG(is_type_pointer(ssa_type(address)),
"%s", type_to_string(ssa_type(address)));
return v;
@@ -1169,8 +1169,12 @@ ssaValue *ssa_add_local_generated(ssaProcedure *proc, Type *type) {
ssaValue *ssa_add_param(ssaProcedure *proc, Entity *e) {
ssaValue *v = ssa_make_value_param(proc->module->allocator, proc, e);
+#if 1
ssaValue *l = ssa_add_local(proc, e);
ssa_emit_store(proc, l, v);
+#else
+ ssa_module_add_value(proc->module, e, v);
+#endif
return v;
}
@@ -1418,7 +1422,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
proc->curr_block = proc->decl_block;
ssa_emit_jump(proc, proc->entry_block);
-#if 0
+#if 1
ssa_optimize_blocks(proc);
ssa_build_referrers(proc);
ssa_build_dom_tree(proc);
@@ -1902,6 +1906,10 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
return make_string("");
}
+ssaValue *ssa_emit_bitcast(ssaProcedure *proc, ssaValue *data, Type *type) {
+ return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, data, ssa_type(data), type));
+}
+
ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_argument) {
Type *src_type = ssa_type(value);
@@ -2029,7 +2037,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
Type *tag_type = src_type;
Type *tag_type_ptr = make_type_pointer(allocator, tag_type);
- ssaValue *underlying = ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, data, t_rawptr, tag_type_ptr));
+ ssaValue *underlying = ssa_emit_bitcast(proc, data, tag_type_ptr);
ssa_emit_store(proc, underlying, value);
return ssa_emit_load(proc, parent);
@@ -2063,23 +2071,23 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
// Pointer <-> Pointer
if (is_type_pointer(src) && is_type_pointer(dst)) {
- return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst));
+ return ssa_emit_bitcast(proc, value, dst);
}
// proc <-> proc
if (is_type_proc(src) && is_type_proc(dst)) {
- return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst));
+ return ssa_emit_bitcast(proc, value, dst);
}
// pointer -> proc
if (is_type_pointer(src) && is_type_proc(dst)) {
- return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst));
+ return ssa_emit_bitcast(proc, value, dst);
}
// proc -> pointer
if (is_type_proc(src) && is_type_pointer(dst)) {
- return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst));
+ return ssa_emit_bitcast(proc, value, dst);
}
@@ -2180,7 +2188,7 @@ ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *t) {
i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
if (sz == dz) {
- return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst));
+ return ssa_emit_bitcast(proc, value, dst);
}
@@ -2205,6 +2213,94 @@ ssaValue *ssa_emit_down_cast(ssaProcedure *proc, ssaValue *value, Type *t) {
return ssa_emit_conv(proc, head, t);
}
+ssaValue *ssa_emit_union_cast(ssaProcedure *proc, ssaValue *value, Type *tuple) {
+ GB_ASSERT(tuple->kind == Type_Tuple);
+ gbAllocator a = proc->module->allocator;
+
+ Type *src_type = ssa_type(value);
+ b32 is_ptr = is_type_pointer(src_type);
+
+ Type *t_bool_ptr = make_type_pointer(a, t_bool);
+ Type *t_int_ptr = make_type_pointer(a, t_int);
+
+ ssaValue *v = ssa_add_local_generated(proc, tuple);
+
+ if (is_ptr) {
+ Type *src = base_type(type_deref(src_type));
+ Type *src_ptr = src_type;
+ GB_ASSERT(is_type_union(src));
+ Type *dst_ptr = tuple->Tuple.variables[0]->type;
+ Type *dst = type_deref(dst_ptr);
+
+ ssaValue *tag = ssa_emit_load(proc, ssa_emit_struct_gep(proc, value, v_one32, t_int_ptr));
+ ssaValue *dst_tag = NULL;
+ for (isize i = 1; i < src->Record.field_count; i++) {
+ Entity *f = src->Record.fields[i];
+ if (are_types_identical(f->type, dst)) {
+ dst_tag = ssa_make_const_int(a, i);
+ break;
+ }
+ }
+ GB_ASSERT(dst_tag != NULL);
+
+
+ ssaBlock *ok_block = ssa_add_block(proc, NULL, "union_cast.ok");
+ ssaBlock *end_block = ssa_add_block(proc, NULL, "union_cast.end");
+ ssaValue *cond = ssa_emit_comp(proc, Token_CmpEq, tag, dst_tag);
+ ssa_emit_if(proc, cond, ok_block, end_block);
+ proc->curr_block = ok_block;
+
+ ssaValue *gep0 = ssa_emit_struct_gep(proc, v, v_zero32, make_type_pointer(a, dst_ptr));
+ ssaValue *gep1 = ssa_emit_struct_gep(proc, v, v_one32, t_bool_ptr);
+
+ ssaValue *data = ssa_emit_conv(proc, value, dst_ptr);
+ ssa_emit_store(proc, gep0, data);
+ ssa_emit_store(proc, gep1, v_true);
+
+ ssa_emit_jump(proc, end_block);
+ proc->curr_block = end_block;
+
+ } else {
+ Type *src = base_type(src_type);
+ GB_ASSERT(is_type_union(src));
+ Type *dst = tuple->Tuple.variables[0]->type;
+ Type *dst_ptr = make_type_pointer(a, dst);
+
+ ssaValue *tag = ssa_emit_struct_ev(proc, value, 1, t_int);
+ ssaValue *dst_tag = NULL;
+ for (isize i = 1; i < src->Record.field_count; i++) {
+ Entity *f = src->Record.fields[i];
+ if (are_types_identical(f->type, dst)) {
+ dst_tag = ssa_make_const_int(a, i);
+ break;
+ }
+ }
+ GB_ASSERT(dst_tag != NULL);
+
+ // HACK(bill): This is probably not very efficient
+ ssaValue *union_copy = ssa_add_local_generated(proc, src_type);
+ ssa_emit_store(proc, union_copy, value);
+
+ ssaBlock *ok_block = ssa_add_block(proc, NULL, "union_cast.ok");
+ ssaBlock *end_block = ssa_add_block(proc, NULL, "union_cast.end");
+ ssaValue *cond = ssa_emit_comp(proc, Token_CmpEq, tag, dst_tag);
+ ssa_emit_if(proc, cond, ok_block, end_block);
+ proc->curr_block = ok_block;
+
+ ssaValue *gep0 = ssa_emit_struct_gep(proc, v, v_zero32, dst_ptr);
+ ssaValue *gep1 = ssa_emit_struct_gep(proc, v, v_one32, t_bool_ptr);
+
+ ssaValue *data = ssa_emit_load(proc, ssa_emit_conv(proc, union_copy, dst_ptr));
+ ssa_emit_store(proc, gep0, data);
+ ssa_emit_store(proc, gep1, v_true);
+
+ ssa_emit_jump(proc, end_block);
+ proc->curr_block = end_block;
+
+ }
+ return ssa_emit_load(proc, v);
+}
+
void ssa_build_cond(ssaProcedure *proc, AstNode *cond, ssaBlock *true_block, ssaBlock *false_block);
ssaValue *ssa_emit_logical_binary_expr(ssaProcedure *proc, AstNode *expr) {
@@ -2325,6 +2421,7 @@ ssaValue *ssa_find_implicit_value_backing(ssaProcedure *proc, ImplicitValueId id
ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv) {
+ expr = unparen_expr(expr);
switch (expr->kind) {
case_ast_node(bl, BasicLit, expr);
GB_PANIC("Non-constant basic literal");
@@ -2350,13 +2447,17 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
if (v->kind == ssaValue_Proc) {
return v;
}
+ // if (e->kind == Entity_Variable && e->Variable.param) {
+ // return v;
+ // }
return ssa_emit_load(proc, v);
}
return NULL;
case_end;
- case_ast_node(pe, ParenExpr, expr);
- return ssa_build_single_expr(proc, unparen_expr(expr), tv);
+ case_ast_node(re, RunExpr, expr);
+ // TODO(bill): Run Expression
+ return ssa_build_single_expr(proc, re->expr, tv);
case_end;
case_ast_node(de, DerefExpr, expr);
@@ -2364,6 +2465,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case_end;
case_ast_node(se, SelectorExpr, expr);
+ TypeAndValue *tav = map_get(&proc->module->info->types, hash_pointer(expr));
+ GB_ASSERT(tav != NULL);
return ssa_lvalue_load(proc, ssa_build_addr(proc, expr));
case_end;
@@ -2441,6 +2544,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssa_emit_comment(proc, make_string("cast - down_cast"));
return ssa_emit_down_cast(proc, ssa_build_expr(proc, be->left), tv->type);
+ case Token_union_cast:
+ ssa_emit_comment(proc, make_string("cast - union_cast"));
+ return ssa_emit_union_cast(proc, ssa_build_expr(proc, be->left), tv->type);
+
default:
GB_PANIC("Invalid binary expression");
break;