From 61fcfd6f3d3c6cffd7e610abab83445b4cd1950d Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Wed, 7 Sep 2016 14:03:17 +0100 Subject: Begin Type_Info Missing stuff in records, procedures, and tuples --- src/codegen/codegen.cpp | 164 +++++++++++++++++++++++++++++++++++++++------ src/codegen/print_llvm.cpp | 20 ++---- src/codegen/ssa.cpp | 110 +++++++++++++++++------------- 3 files changed, 211 insertions(+), 83 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index 7ad1d56e2..5d8df5060 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -31,27 +31,6 @@ b32 ssa_gen_init(ssaGen *s, Checker *c) { if (err != gbFileError_None) return false; -#if 0 - Map type_map; // Key: Type * - map_init(&type_map, gb_heap_allocator()); - i32 index = 0; - gb_for_array(i, c->info.types.entries) { - TypeAndValue tav = c->info.types.entries[i].value; - Type *type = tav.type; - HashKey key = hash_pointer(type); - auto found = map_get(&type_map, key); - if (!found) { - map_set(&type_map, key, index); - index++; - } - } - gb_for_array(i, type_map.entries) { - auto *e = &type_map.entries[i]; - Type *t = cast(Type *)cast(uintptr)e->key.key; - gb_printf("%s\n", type_to_string(t)); - } -#endif - return true; } @@ -199,6 +178,149 @@ void ssa_gen_tree(ssaGen *s) { } } + { // NOTE(bill): Setup type_info data + ssaValue **found = map_get(&proc->module->members, hash_string(make_string("__type_info_data"))); + GB_ASSERT(found != NULL); + ssaValue *type_info_data = *found; + CheckerInfo *info = proc->module->info; + + + Type *t_int_ptr = make_type_pointer(a, t_int); + Type *t_bool_ptr = make_type_pointer(a, t_bool); + Type *t_string_ptr = make_type_pointer(a, t_string); + Type *t_type_info_ptr_ptr = make_type_pointer(a, t_type_info_ptr); + + auto get_type_info_ptr = [](ssaProcedure *proc, ssaValue *type_info_data, Type *type) -> ssaValue * { + auto *info = proc->module->info; + MapFindResult fr = map__find(&info->type_info_types, hash_pointer(type)); + GB_ASSERT(fr.entry_index >= 0); + return ssa_emit_struct_gep(proc, type_info_data, fr.entry_index, t_type_info_ptr); + }; + + + gb_for_array(entry_index, info->type_info_types.entries) { + auto *entry = &info->type_info_types.entries[entry_index]; + Type *t = entry->value; + + ssaValue *tag = NULL; + + switch (t->kind) { + case Type_Named: { + tag = ssa_add_local_generated(proc, t_type_info_named); + + ssaValue *gsa = ssa_add_global_string_array(proc, make_exact_value_string(t->Named.name)); + ssaValue *elem = ssa_array_elem(proc, gsa); + ssaValue *len = ssa_array_len(proc, ssa_emit_load(proc, gsa)); + ssaValue *name = ssa_emit_string(proc, elem, len); + + ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Named.base); + + ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero, t_string_ptr), name); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_type_info_ptr), gep); + } break; + + case Type_Basic: + switch (t->Basic.kind) { + case Basic_bool: + tag = ssa_add_local_generated(proc, t_type_info_boolean); + break; + case Basic_i8: + case Basic_i16: + case Basic_i32: + case Basic_i64: + case Basic_i128: + case Basic_u8: + case Basic_u16: + case Basic_u32: + case Basic_u64: + case Basic_u128: + case Basic_int: + case Basic_uint: { + tag = ssa_add_local_generated(proc, t_type_info_integer); + b32 is_unsigned = (basic_types[t->Basic.kind].flags & BasicFlag_Unsigned) != 0; + ssaValue *bits = ssa_make_value_constant(a, t_int, make_exact_value_integer(8*type_size_of(m->sizes, a, t))); + ssaValue *is_signed = ssa_make_value_constant(a, t_bool, make_exact_value_bool(!is_unsigned)); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_int_ptr), bits); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_bool_ptr), is_signed); + } break; + + case Basic_f32: + case Basic_f64: { + tag = ssa_add_local_generated(proc, t_type_info_float); + ssaValue *bits = ssa_make_value_constant(a, t_int, make_exact_value_integer(8*type_size_of(m->sizes, a, t))); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_int_ptr), bits); + } break; + + case Basic_rawptr: + tag = ssa_add_local_generated(proc, t_type_info_pointer); + break; + + case Basic_string: + tag = ssa_add_local_generated(proc, t_type_info_string); + break; + } + break; + + case Type_Pointer: { + tag = ssa_add_local_generated(proc, t_type_info_pointer); + ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Pointer.elem); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep); + } break; + case Type_Array: { + tag = ssa_add_local_generated(proc, t_type_info_array); + ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Array.elem); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep); + } break; + case Type_Slice: { + tag = ssa_add_local_generated(proc, t_type_info_slice); + ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Slice.elem); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep); + } break; + case Type_Vector: { + tag = ssa_add_local_generated(proc, t_type_info_vector); + ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Vector.elem); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep); + } break; + case Type_Record: { + switch (t->Record.kind) { + // TODO(bill): Record members for `Type_Info` + case TypeRecord_Struct: + tag = ssa_add_local_generated(proc, t_type_info_struct); + break; + case TypeRecord_Union: + tag = ssa_add_local_generated(proc, t_type_info_union); + break; + case TypeRecord_RawUnion: + tag = ssa_add_local_generated(proc, t_type_info_raw_union); + break; + case TypeRecord_Enum: { + tag = ssa_add_local_generated(proc, t_type_info_enum); + Type *enum_base = t->Record.enum_base; + if (enum_base == NULL) { + enum_base = t_int; + } + ssaValue *gep = get_type_info_ptr(proc, type_info_data, enum_base); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep); + } break; + } + } break; + + case Type_Tuple: + // TODO(bill): Type_Info for tuples + break; + case Type_Proc: + // TODO(bill): Type_Info for procedures + break; + } + + if (tag != NULL) { + ssaValue *gep = ssa_emit_struct_gep(proc, type_info_data, entry_index, t_type_info_ptr); + ssaValue *val = ssa_emit_conv(proc, ssa_emit_load(proc, tag), t_type_info); + ssa_emit_store(proc, gep, val); + } + } + } + ssa_end_procedure_body(proc); } diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index fffdee805..c8dff6d6b 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -314,7 +314,7 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ void ssa_print_block_name(ssaFileBuffer *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(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type_hint) { @@ -352,7 +352,9 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) { switch (instr->kind) { case ssaInstr_StartupRuntime: { - ssa_fprintf(f, "call void @." SSA_STARTUP_RUNTIME_PROC_NAME "()\n"); + ssa_fprintf(f, "call void "); + ssa_print_encoded_global(f, make_string(SSA_STARTUP_RUNTIME_PROC_NAME)); + ssa_fprintf(f, "()\n"); } break; case ssaInstr_Comment: @@ -642,20 +644,6 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) { ssa_fprintf(f, "\n"); } break; - case ssaInstr_MemCopy: { - ssa_fprintf(f, "call void @.memory_move"); - ssa_fprintf(f, "(i8* "); - ssa_print_value(f, m, instr->CopyMemory.dst, t_rawptr); - ssa_fprintf(f, ", i8* "); - ssa_print_value(f, m, instr->CopyMemory.src, t_rawptr); - ssa_fprintf(f, ", "); - ssa_print_type(f, m->sizes, t_int); - ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->CopyMemory.len, t_int); - ssa_fprintf(f, ")\n"); - } break; - - case ssaInstr_ExtractElement: { Type *vt = ssa_type(instr->ExtractElement.vector); ssa_fprintf(f, "%%%d = extractelement ", value->id); diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index e7d4aaf4b..5bff4a344 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -85,7 +85,6 @@ struct ssaProcedure { SSA_INSTR_KIND(Unreachable), \ SSA_INSTR_KIND(BinaryOp), \ SSA_INSTR_KIND(Call), \ - SSA_INSTR_KIND(MemCopy), \ SSA_INSTR_KIND(NoOp), \ SSA_INSTR_KIND(ExtractElement), \ SSA_INSTR_KIND(InsertElement), \ @@ -198,13 +197,6 @@ struct ssaInstr { ssaValue **args; isize arg_count; } Call; - struct { - ssaValue *dst, *src; - ssaValue *len; - i32 align; - b32 is_volatile; - } CopyMemory; - struct { ssaValue *vector; ssaValue *index; @@ -315,6 +307,25 @@ void ssa_module_init(ssaModule *m, Checker *c) { map_init(&m->values, gb_heap_allocator()); map_init(&m->members, gb_heap_allocator()); + + { + // Add type info data + ssaValue *ssa_make_value_global(gbAllocator a, Entity *e, ssaValue *value); + + + String name = make_string("__type_info_data"); + Token token = {}; + token.kind = Token_Identifier; + token.string = name; + + + isize count = gb_array_count(c->info.type_info_types.entries); + Entity *e = make_entity_variable(m->allocator, NULL, token, make_type_array(m->allocator, t_type_info, count)); + ssaValue *g = ssa_make_value_global(m->allocator, e, NULL); + g->Global.is_private = true; + map_set(&m->values, hash_pointer(e), g); + map_set(&m->members, hash_string(name), g); + } } void ssa_module_destroy(ssaModule *m) { @@ -356,9 +367,6 @@ Type *ssa_type(ssaInstr *instr) { } return NULL; } break; - case ssaInstr_MemCopy: - return t_int; - case ssaInstr_ExtractElement: { Type *vt = ssa_type(instr->ExtractElement.vector); Type *bt = base_vector_type(get_base_type(vt)); @@ -545,16 +553,6 @@ ssaValue *ssa_make_instr_call(ssaProcedure *p, ssaValue *value, ssaValue **args, return v; } -ssaValue *ssa_make_instr_copy_memory(ssaProcedure *p, ssaValue *dst, ssaValue *src, ssaValue *len, i32 align, b32 is_volatile) { - ssaValue *v = ssa_alloc_instr(p, ssaInstr_MemCopy); - v->Instr.CopyMemory.dst = dst; - v->Instr.CopyMemory.src = src; - v->Instr.CopyMemory.len = len; - v->Instr.CopyMemory.align = align; - v->Instr.CopyMemory.is_volatile = is_volatile; - return v; -} - ssaValue *ssa_make_instr_conv(ssaProcedure *p, ssaConvKind kind, ssaValue *value, Type *from, Type *to) { ssaValue *v = ssa_alloc_instr(p, ssaInstr_Conv); v->Instr.Conv.kind = kind; @@ -925,7 +923,6 @@ void ssa_end_procedure_body(ssaProcedure *proc) { case ssaInstr_Br: case ssaInstr_Ret: case ssaInstr_Unreachable: - case ssaInstr_MemCopy: case ssaInstr_StartupRuntime: continue; case ssaInstr_Call: @@ -2008,11 +2005,13 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue make_exact_value_integer(size_of_elem)); ssaValue *byte_count = ssa_emit_arith(proc, mul, len, elem_size, t_int); + ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 3); + args[0] = dst; + args[1] = src; + args[2] = byte_count; - i32 align = cast(i32)type_align_of(proc->module->sizes, proc->module->allocator, elem_type); - b32 is_volatile = false; + ssa_emit_global_call(proc, "memory_move", args, 3); - ssa_emit(proc, ssa_make_instr_copy_memory(proc, dst, src, byte_count, align, is_volatile)); return len; } break; case BuiltinProc_append: { @@ -2056,7 +2055,12 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue item = ssa_emit_ptr_offset(proc, item, v_zero); item = ssa_emit_conv(proc, item, t_rawptr, true); - ssa_emit(proc, ssa_make_instr_copy_memory(proc, offset, item, byte_count, 1, false)); + ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 3); + args[0] = offset; + args[1] = item; + args[2] = byte_count; + + ssa_emit_global_call(proc, "memory_move", args, 3); // Increment slice length Token add = {Token_Add}; @@ -2172,6 +2176,22 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *cond = ssa_emit_comp(proc, lt, x, v_zero); return ssa_emit_select(proc, cond, neg_x, x); } break; + + + case BuiltinProc_type_info: { + ssaValue **found = map_get(&proc->module->members, hash_string(make_string("__type_info_data"))); + GB_ASSERT(found != NULL); + ssaValue *type_info_data = *found; + ssaValue *x = ssa_build_expr(proc, ce->arg_list); + Type *t = default_type(type_of_expr(proc->module->info, ce->arg_list)); + MapFindResult fr = map__find(&proc->module->info->type_info_types, hash_pointer(t)); + GB_ASSERT(fr.entry_index >= 0); + // Zero is null and void + isize offset = fr.entry_index; + + ssaValue *gep = ssa_emit_struct_gep(proc, type_info_data, offset, t_type_info_ptr); + return gep; + } break; } } } @@ -3153,11 +3173,16 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { Type *union_type = type_deref(ssa_type(parent)); GB_ASSERT(is_type_union(union_type)); + ssa_emit_comment(proc, make_string("get union's tag")); ssaValue *tag_index = ssa_emit_struct_gep(proc, parent, v_one32, make_type_pointer(allocator, t_int)); tag_index = ssa_emit_load(proc, tag_index); ssaValue *data = ssa_emit_conv(proc, parent, t_rawptr); + ssaBlock *start_block = ssa_add_block(proc, node, make_string("type-match.case.first")); + ssa_emit_jump(proc, start_block); + proc->curr_block = start_block; + ssaBlock *done = ssa__make_block(proc, node, make_string("type-match.done")); // NOTE(bill): Append later ast_node(body, BlockStmt, ms->body); @@ -3173,30 +3198,22 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { for (AstNode *clause = body->list; clause != NULL; clause = clause->next, i++) { - ssaBlock *body = NULL; - 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("type-match.dflt.body")); - } else { - body = ssa__make_block(proc, clause, make_string("type-match.case.body")); - } - } - - if (cc->list == NULL) { // default case default_stmts = cc->stmts; - default_block = body; + default_block = ssa__make_block(proc, clause, make_string("type-match.dflt.body")); continue; } + + ssaBlock *body = ssa__make_block(proc, clause, make_string("type-match.case.body")); + + Scope *scope = *map_get(&proc->module->info->scopes, hash_pointer(clause)); Entity *tag_var_entity = current_scope_lookup_entity(scope, tag_var_name); + GB_ASSERT(tag_var_entity != NULL); ssaValue *tag_var = ssa_add_local(proc, tag_var_entity); ssaValue *data_ptr = ssa_emit_conv(proc, data, tag_var_entity->type); ssa_emit_store(proc, tag_var, data_ptr); @@ -3205,10 +3222,13 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { Type *base_type = type_deref(tag_var_entity->type); ssaValue *index = NULL; - for (isize i = 0; i < get_base_type(union_type)->Record.field_count; i++) { - Entity *f = get_base_type(union_type)->Record.fields[i]; + Type *ut = get_base_type(union_type); + GB_ASSERT(ut->Record.kind == TypeRecord_Union); + for (isize field_index = 1; field_index < ut->Record.field_count; field_index++) { + Entity *f = get_base_type(union_type)->Record.fields[field_index]; if (are_types_identical(f->type, base_type)) { - index = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(i)); + index = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(field_index)); + break; } } GB_ASSERT(index != NULL); @@ -3220,9 +3240,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_array_append(proc->blocks, next_cond); proc->curr_block = next_cond; - if (append_body) { - gb_array_append(proc->blocks, body); - } + gb_array_append(proc->blocks, body); proc->curr_block = body; ssa_push_target_list(proc, done, NULL, NULL); ssa_build_stmt_list(proc, cc->stmts); -- cgit v1.2.3