aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/ssa.cpp
diff options
context:
space:
mode:
authorgingerBill <ginger.bill.22@gmail.com>2016-08-14 15:31:11 +0100
committergingerBill <ginger.bill.22@gmail.com>2016-08-14 15:31:11 +0100
commitb44bc99b889bb07dfe4f843ddeefd7483e0fba82 (patch)
tree9ce3fe6b7267e35a8a498c98c7fc88b77771090d /src/codegen/ssa.cpp
parentee002364120a773753d37cf5575baa6e86d0502c (diff)
append :: proc(s: ^[]T, i: T) -> bool
Diffstat (limited to 'src/codegen/ssa.cpp')
-rw-r--r--src/codegen/ssa.cpp137
1 files changed, 112 insertions, 25 deletions
diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp
index 42e7046cf..1b70b2678 100644
--- a/src/codegen/ssa.cpp
+++ b/src/codegen/ssa.cpp
@@ -401,6 +401,7 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr);
ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv);
ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr);
ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *a_type);
+ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *a_type);
void ssa_build_proc(ssaValue *value, ssaProcedure *parent);
@@ -1077,7 +1078,7 @@ ssaValue *ssa_emit_slice(ssaProcedure *proc, Type *slice_type, ssaValue *base, s
switch (base_type->kind) {
case Type_Array: elem = ssa_array_elem(proc, base); break;
case Type_Slice: elem = ssa_slice_elem(proc, base); break;
- case Type_Pointer: elem = base; break;
+ case Type_Pointer: elem = ssa_emit_load(proc, base); break;
}
elem = ssa_emit_ptr_offset(proc, elem, low);
@@ -1176,8 +1177,6 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
if (are_types_identical(t, src_type))
return value;
-
-
if (value->kind == ssaValue_Constant) {
if (dst->kind == Type_Basic) {
ExactValue ev = value->constant.value;
@@ -1291,6 +1290,31 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
}
+ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *t) {
+ Type *src_type = ssa_value_type(value);
+ if (are_types_identical(t, src_type)) {
+ return value;
+ }
+
+ Type *src = get_base_type(src_type);
+ Type *dst = get_base_type(t);
+ if (are_types_identical(t, src_type))
+ return value;
+
+ i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src);
+ 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));
+ }
+
+
+ GB_PANIC("Invalid transmute conversion: `%s` to `%s`", type_to_string(src_type), type_to_string(t));
+
+ return NULL;
+}
+
+
@@ -1392,6 +1416,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case Token_as:
return ssa_emit_conv(proc, ssa_build_expr(proc, be->left), tv->type);
+ case Token_transmute:
+ return ssa_emit_transmute(proc, ssa_build_expr(proc, be->left), tv->type);
+
default:
GB_PANIC("Invalid binary expression");
break;
@@ -1583,8 +1610,44 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
return len;
} break;
case BuiltinProc_append: {
- // copy :: proc(s: ^[]Type, value: Type) -> bool
- GB_PANIC("TODO(bill): BuiltinProc_append");
+ // append :: proc(s: ^[]Type, item: Type) -> bool
+ AstNode *sptr_node = ce->arg_list;
+ AstNode *item_node = ce->arg_list->next;
+ ssaValue *slice = ssa_build_addr(proc, sptr_node).address;
+ ssaValue *item = ssa_build_addr(proc, item_node).address;
+ Type *item_type = type_deref(ssa_value_type(item));
+
+ ssaValue *elem = ssa_slice_elem(proc, slice);
+ ssaValue *len = ssa_slice_len(proc, slice);
+ ssaValue *cap = ssa_slice_cap(proc, slice);
+
+ // NOTE(bill): Check if can append is possible
+ Token lt = {Token_Lt};
+ ssaValue *cond = ssa_emit_comp(proc, lt, len, cap);
+ ssaBlock *able = ssa_add_block(proc, NULL, make_string("builtin.append.able"));
+ ssaBlock *done = ssa__make_block(proc, NULL, make_string("builtin.append.done"));
+
+ ssa_emit_if(proc, cond, able, done);
+ proc->curr_block = able;
+
+ // Add new slice item
+ ssaValue *offset = ssa_emit_ptr_offset(proc, elem, len);
+ i64 item_size = type_size_of(proc->module->sizes, proc->module->allocator, item_type);
+ ssaValue *byte_count = ssa_make_value_constant(proc->module->allocator, t_int,
+ make_exact_value_integer(item_size));
+ ssa_emit(proc, ssa_make_instr_copy_memory(proc, offset, item, byte_count, 1, false));
+
+ // Increment slice length
+ Token add = {Token_Add};
+ ssaValue *new_len = ssa_emit_arith(proc, add, len, v_one, t_int);
+ ssaValue *gep = ssa_emit_struct_gep(proc, slice, v_one32, t_int);
+ ssa_emit_store(proc, gep, new_len);
+
+ ssa_emit_jump(proc, done);
+ gb_array_append(proc->blocks, done);
+ proc->curr_block = done;
+
+ return ssa_emit_conv(proc, cond, t_bool);
} break;
case BuiltinProc_print: {
// print :: proc(...)
@@ -1735,12 +1798,21 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
case_ast_node(be, BinaryExpr, expr);
switch (be->op.kind) {
case Token_as: {
+ // HACK(bill): Do have to make new variable to do this?
// NOTE(bill): Needed for dereference of pointer conversion
Type *type = type_of_expr(proc->module->info, expr);
ssaValue *v = ssa_add_local_generated(proc, type);
ssa_emit_store(proc, v, ssa_emit_conv(proc, ssa_build_expr(proc, be->left), type));
return ssa_make_lvalue(v, expr);
}
+ case Token_transmute: {
+ // HACK(bill): Do have to make new variable to do this?
+ // NOTE(bill): Needed for dereference of pointer conversion
+ Type *type = type_of_expr(proc->module->info, expr);
+ ssaValue *v = ssa_add_local_generated(proc, type);
+ ssa_emit_store(proc, v, ssa_emit_transmute(proc, ssa_build_expr(proc, be->left), type));
+ return ssa_make_lvalue(v, expr);
+ }
default:
GB_PANIC("Invalid binary expression for ssa_build_addr: %.*s\n", LIT(be->op.string));
break;
@@ -1971,33 +2043,48 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
if (proc->children == NULL) {
gb_array_init(proc->children, gb_heap_allocator());
}
- // NOTE(bill): Generate a new name
- // parent$name
- String pd_name = pd->name->Ident.token.string;
- isize name_len = proc->name.len + 1 + pd_name.len + 1;
- u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
- name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%.*s", LIT(proc->name), LIT(pd_name));
- String name = make_string(name_text, name_len-1);
-
- Entity **found = map_get(&proc->module->info->definitions, hash_pointer(pd->name));
- GB_ASSERT(found != NULL);
- Entity *e = *found;
- ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
- proc->module, e->type, pd->type, pd->body, name);
-
- ssa_module_add_value(proc->module, e, value);
- gb_array_append(proc->children, &value->proc);
- ssa_build_proc(value, proc);
+ if (pd->body != NULL) {
+ // NOTE(bill): Generate a new name
+ // parent$name-guid
+ String pd_name = pd->name->Ident.token.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);
+ name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%.*s-%d", LIT(proc->name), LIT(pd_name), guid);
+ String name = make_string(name_text, name_len-1);
+
+ Entity **found = map_get(&proc->module->info->definitions, hash_pointer(pd->name));
+ GB_ASSERT(found != NULL);
+ Entity *e = *found;
+ ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
+ proc->module, e->type, pd->type, pd->body, name);
+
+ ssa_module_add_value(proc->module, e, value);
+ gb_array_append(proc->children, &value->proc);
+ ssa_build_proc(value, proc);
+ } else {
+ String name = pd->name->Ident.token.string;
+
+ Entity **found = map_get(&proc->module->info->definitions, hash_pointer(pd->name));
+ GB_ASSERT(found != NULL);
+ Entity *e = *found;
+ ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
+ proc->module, e->type, pd->type, pd->body, name);
+ ssa_module_add_value(proc->module, e, value);
+ gb_array_append(proc->children, &value->proc);
+ ssa_build_proc(value, proc);
+ }
case_end;
case_ast_node(td, TypeDecl, node);
// NOTE(bill): Generate a new name
- // parent_proc.name
+ // parent_proc.name-guid
String td_name = td->name->Ident.token.string;
- isize name_len = proc->name.len + 1 + td_name.len + 1;
+ 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);
- name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s", LIT(proc->name), LIT(td_name));
+ i32 guid = cast(i32)gb_array_count(proc->module->nested_type_names);
+ name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(td_name), guid);
String name = make_string(name_text, name_len-1);
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(td->name));