diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/codegen.cpp | 137 | ||||
| -rw-r--r-- | src/codegen/print_llvm.cpp | 46 | ||||
| -rw-r--r-- | src/codegen/ssa.cpp | 75 |
3 files changed, 182 insertions, 76 deletions
diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index 9c71ea917..54ec5f2ba 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -67,16 +67,6 @@ String ssa_mangle_name(ssaGen *s, String path, String name) { } void ssa_gen_tree(ssaGen *s) { - if (v_zero == NULL) { - v_zero = ssa_make_const_int (gb_heap_allocator(), 0); - v_one = ssa_make_const_int (gb_heap_allocator(), 1); - v_zero32 = ssa_make_const_i32 (gb_heap_allocator(), 0); - v_one32 = ssa_make_const_i32 (gb_heap_allocator(), 1); - v_two32 = ssa_make_const_i32 (gb_heap_allocator(), 2); - v_false = ssa_make_const_bool(gb_heap_allocator(), false); - v_true = ssa_make_const_bool(gb_heap_allocator(), true); - } - struct ssaGlobalVariable { ssaValue *var, *init; DeclInfo *decl; @@ -85,9 +75,35 @@ void ssa_gen_tree(ssaGen *s) { ssaModule *m = &s->module; CheckerInfo *info = m->info; gbAllocator a = m->allocator; + + if (v_zero == NULL) { + v_zero = ssa_make_const_int (m->allocator, 0); + v_one = ssa_make_const_int (m->allocator, 1); + v_zero32 = ssa_make_const_i32 (m->allocator, 0); + v_one32 = ssa_make_const_i32 (m->allocator, 1); + v_two32 = ssa_make_const_i32 (m->allocator, 2); + v_false = ssa_make_const_bool(m->allocator, false); + v_true = ssa_make_const_bool(m->allocator, true); + } + + isize global_variable_max_count = 0; + + gb_for_array(i, info->entities.entries) { + auto *entry = &info->entities.entries[i]; + Entity *e = cast(Entity *)cast(uintptr)entry->key.key; + if (e->kind == Entity_Variable) { + global_variable_max_count++; + } + } + + + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); + gbArray(ssaGlobalVariable) global_variables; - gb_array_init(global_variables, gb_heap_allocator()); - defer (gb_array_free(global_variables)); + gb_array_init_reserve(global_variables, m->tmp_allocator, global_variable_max_count); + + gb_for_array(i, info->entities.entries) { auto *entry = &info->entities.entries[i]; @@ -123,7 +139,7 @@ void ssa_gen_tree(ssaGen *s) { ExactValue v = tav->value; if (v.kind == ExactValue_String) { // NOTE(bill): The printer will fix the value correctly - g->Global.value = ssa_add_global_string_array(m, v.value_string); + // g->Global.value = ssa_add_global_string_array(m, v.value_string); } else { g->Global.value = ssa_make_value_constant(a, tav->type, v); } @@ -147,6 +163,8 @@ void ssa_gen_tree(ssaGen *s) { } if (pd->foreign_name.len > 0) { name = pd->foreign_name; + } else if (pd->link_name.len > 0) { + name = pd->link_name; } ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); @@ -171,7 +189,18 @@ void ssa_gen_tree(ssaGen *s) { ssaDebugInfo *compile_unit = m->debug_info.entries[0].value; GB_ASSERT(compile_unit->kind == ssaDebugInfo_CompileUnit); ssaDebugInfo *all_procs = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_AllProcs); - gb_array_init(all_procs->AllProcs.procs, gb_heap_allocator()); + + isize all_proc_max_count = 0; + gb_for_array(i, m->debug_info.entries) { + auto *entry = &m->debug_info.entries[i]; + ssaDebugInfo *di = entry->value; + di->id = i; + if (di->kind == ssaDebugInfo_Proc) { + all_proc_max_count++; + } + } + + gb_array_init_reserve(all_procs->AllProcs.procs, m->allocator, all_proc_max_count); map_set(&m->debug_info, hash_pointer(all_procs), all_procs); // NOTE(bill): This doesn't need to be mapped compile_unit->CompileUnit.all_procs = all_procs; @@ -250,10 +279,12 @@ void ssa_gen_tree(ssaGen *s) { // Useful types Type *t_int_ptr = make_type_pointer(a, t_int); + Type *t_i64_ptr = make_type_pointer(a, t_i64); 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); - + Type *t_i64_slice_ptr = make_type_pointer(a, make_type_slice(a, t_i64)); + Type *t_string_slice_ptr = make_type_pointer(a, make_type_slice(a, t_string)); auto get_type_info_ptr = [](ssaProcedure *proc, ssaValue *type_info_data, Type *type) -> ssaValue * { return ssa_emit_struct_gep(proc, type_info_data, @@ -302,12 +333,12 @@ void ssa_gen_tree(ssaGen *s) { case Basic_i16: case Basic_i32: case Basic_i64: - case Basic_i128: + // case Basic_i128: case Basic_u8: case Basic_u16: case Basic_u32: case Basic_u64: - case Basic_u128: + // case Basic_u128: case Basic_int: case Basic_uint: { tag = ssa_add_local_generated(proc, t_type_info_integer); @@ -467,8 +498,72 @@ void ssa_gen_tree(ssaGen *s) { 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); + ssaValue *base = ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr); + ssa_emit_store(proc, base, get_type_info_ptr(proc, type_info_data, enum_base)); + + if (t->Record.other_field_count > 0) { + Entity **fields = t->Record.other_fields; + isize count = t->Record.other_field_count; + ssaValue *value_array = NULL; + ssaValue *name_array = NULL; + + + { + Token token = {Token_Identifier}; + i32 id = cast(i32)entry_index; + char name_base[] = "__$enum_values"; + isize name_len = gb_size_of(name_base) + 10; + token.string.text = gb_alloc_array(a, u8, name_len); + token.string.len = gb_snprintf(cast(char *)token.string.text, name_len, + "%s-%d", name_base, id)-1; + Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_i64, count)); + value_array = ssa_make_value_global(a, e, NULL); + value_array->Global.is_private = true; + ssa_module_add_value(m, e, value_array); + map_set(&m->members, hash_string(token.string), value_array); + } + { + Token token = {Token_Identifier}; + i32 id = cast(i32)entry_index; + char name_base[] = "__$enum_names"; + isize name_len = gb_size_of(name_base) + 10; + token.string.text = gb_alloc_array(a, u8, name_len); + token.string.len = gb_snprintf(cast(char *)token.string.text, name_len, + "%s-%d", name_base, id)-1; + Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_string, count)); + name_array = ssa_make_value_global(a, e, NULL); + name_array->Global.is_private = true; + ssa_module_add_value(m, e, name_array); + map_set(&m->members, hash_string(token.string), name_array); + } + + for (isize i = 0; i < count; i++) { + ssaValue *value_gep = ssa_emit_struct_gep(proc, value_array, i, t_i64_ptr); + ssaValue *name_gep = ssa_emit_struct_gep(proc, name_array, i, t_string_ptr); + + ssa_emit_store(proc, value_gep, ssa_make_const_i64(a, fields[i]->Constant.value.value_integer)); + ssa_emit_store(proc, name_gep, ssa_emit_global_string(proc, fields[i]->token.string)); + } + + ssaValue *v_count = ssa_make_const_int(a, count); + + + ssaValue *values = ssa_emit_struct_gep(proc, tag, v_one32, t_i64_slice_ptr); + ssaValue *names = ssa_emit_struct_gep(proc, tag, v_two32, t_string_slice_ptr); + ssaValue *value_slice = ssa_add_local_generated(proc, type_deref(t_i64_slice_ptr)); + ssaValue *name_slice = ssa_add_local_generated(proc, type_deref(t_string_slice_ptr)); + + ssa_emit_store(proc, ssa_emit_struct_gep(proc, value_slice, v_zero32, t_i64_ptr), ssa_array_elem(proc, value_array)); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, value_slice, v_one32, t_int_ptr), v_count); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, value_slice, v_two32, t_int_ptr), v_count); + + ssa_emit_store(proc, ssa_emit_struct_gep(proc, name_slice, v_zero32, t_string_ptr), ssa_array_elem(proc, name_array)); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, name_slice, v_one32, t_int_ptr), v_count); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, name_slice, v_two32, t_int_ptr), v_count); + + ssa_emit_store(proc, values, ssa_emit_load(proc, value_slice)); + ssa_emit_store(proc, names, ssa_emit_load(proc, name_slice)); + } } break; } } break; @@ -515,10 +610,10 @@ void ssa_gen_tree(ssaGen *s) { ssaValue *variadic = ssa_emit_struct_gep(proc, tag, v_two32, t_bool_ptr); if (t->Proc.params) { - ssa_emit_store(proc, params, get_type_info_ptr(proc, type_info_data, t->Proc.params)); + ssa_emit_store(proc, params, get_type_info_ptr(proc, type_info_data, t->Proc.params)); } if (t->Proc.results) { - ssa_emit_store(proc, results, get_type_info_ptr(proc, type_info_data, t->Proc.results)); + ssa_emit_store(proc, results, get_type_info_ptr(proc, type_info_data, t->Proc.results)); } ssa_emit_store(proc, variadic, ssa_make_const_bool(a, t->Proc.variadic)); diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index aaaea2cb0..b13644a5f 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -142,12 +142,12 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) { case Basic_i16: ssa_fprintf(f, "i16"); break; case Basic_i32: ssa_fprintf(f, "i32"); break; case Basic_i64: ssa_fprintf(f, "i64"); break; - case Basic_i128: ssa_fprintf(f, "i128"); break; + // case Basic_i128: ssa_fprintf(f, "i128"); break; case Basic_u8: ssa_fprintf(f, "i8"); break; case Basic_u16: ssa_fprintf(f, "i16"); break; case Basic_u32: ssa_fprintf(f, "i32"); break; case Basic_u64: ssa_fprintf(f, "i64"); break; - case Basic_u128: ssa_fprintf(f, "i128"); break; + // case Basic_u128: ssa_fprintf(f, "i128"); break; case Basic_f32: ssa_fprintf(f, "float"); break; case Basic_f64: ssa_fprintf(f, "double"); break; case Basic_rawptr: ssa_fprintf(f, "%%..rawptr"); break; @@ -346,27 +346,27 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type if (scope != NULL) { in_global_scope = scope->is_global || scope->is_init; } - if (type_hint != NULL && is_type_string(type_hint)) { - ssa_fprintf(f, "{i8* getelementptr inbounds ("); - ssa_print_type(f, m, value->Global.entity->type); - ssa_fprintf(f, ", "); - ssa_print_type(f, m, value->Global.entity->type); - ssa_fprintf(f, "* "); - ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope); - ssa_fprintf(f, ", "); - ssa_print_type(f, m, t_int); - ssa_fprintf(f, " 0, i32 0), "); - ssa_print_type(f, m, t_int); - ssa_fprintf(f, " %lld}", 0); - } else { + // if (type_hint != NULL && is_type_string(type_hint)) { + // ssa_fprintf(f, "{i8* getelementptr inbounds ("); + // ssa_print_type(f, m, value->Global.entity->type); + // ssa_fprintf(f, ", "); + // ssa_print_type(f, m, value->Global.entity->type); + // ssa_fprintf(f, "* "); + // ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope); + // ssa_fprintf(f, ", "); + // ssa_print_type(f, m, t_int); + // ssa_fprintf(f, " 0, i32 0), "); + // ssa_print_type(f, m, t_int); + // ssa_fprintf(f, " %lld}", 0); + // } else { ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope); - } + // } } break; case ssaValue_Param: ssa_print_encoded_local(f, value->Param.entity->token.string); break; case ssaValue_Proc: - ssa_print_encoded_global(f, value->Proc.name, (value->Proc.tags & ProcTag_foreign) != 0); + ssa_print_encoded_global(f, value->Proc.name, (value->Proc.tags & (ProcTag_foreign|ProcTag_link_name)) != 0); break; case ssaValue_Instr: ssa_fprintf(f, "%%%d", value->id); @@ -788,11 +788,7 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { } ssa_fprintf(f, " "); - if (are_strings_equal(proc->name, make_string("main"))) { - ssa_print_encoded_global(f, proc->name, true); - } else { - ssa_print_encoded_global(f, proc->name, (proc->tags & ProcTag_foreign) != 0); - } + ssa_print_encoded_global(f, proc->name, (proc->tags & (ProcTag_foreign|ProcTag_link_name)) != 0); ssa_fprintf(f, "("); if (proc_type->param_count > 0) { @@ -818,12 +814,6 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { ssa_fprintf(f, "noinline "); } - // if (proc->tags & ProcTag_stdcall) { - // ssa_fprintf(f, "\"cc\"=\"64\" "); - // } - // if (proc->tags & ProcTag_fastcall) { - // ssa_fprintf(f, "\"cc\"=\"65\" "); - // } if (proc->module->generate_debug_info && proc->entity != NULL) { ssaDebugInfo *di = *map_get(&proc->module->debug_info, hash_pointer(proc->entity)); diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index 630c702ab..dd230577c 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -46,7 +46,9 @@ struct ssaModule { CheckerInfo * info; BaseTypeSizes sizes; gbArena arena; + gbArena tmp_arena; gbAllocator allocator; + gbAllocator tmp_allocator; b32 generate_debug_info; u32 stmt_state_flags; @@ -364,7 +366,9 @@ void ssa_init_module(ssaModule *m, Checker *c) { isize token_count = c->parser->total_token_count; isize arena_size = 4 * token_count * gb_size_of(ssaValue); gb_arena_init_from_allocator(&m->arena, gb_heap_allocator(), arena_size); - m->allocator = gb_arena_allocator(&m->arena); + gb_arena_init_from_allocator(&m->tmp_arena, gb_heap_allocator(), arena_size); + m->allocator = gb_arena_allocator(&m->arena); + m->tmp_allocator = gb_arena_allocator(&m->tmp_arena); m->info = &c->info; m->sizes = c->sizes; @@ -770,6 +774,9 @@ ssaValue *ssa_make_const_int(gbAllocator a, i64 i) { ssaValue *ssa_make_const_i32(gbAllocator a, i64 i) { return ssa_make_value_constant(a, t_i32, make_exact_value_integer(i)); } +ssaValue *ssa_make_const_i64(gbAllocator a, i64 i) { + return ssa_make_value_constant(a, t_i64, make_exact_value_integer(i)); +} ssaValue *ssa_make_const_bool(gbAllocator a, b32 b) { return ssa_make_value_constant(a, t_bool, make_exact_value_bool(b != 0)); } @@ -1066,8 +1073,10 @@ ssaValue *ssa_lvalue_load(ssaProcedure *proc, ssaAddr lval) { void ssa_begin_procedure_body(ssaProcedure *proc) { - gb_array_init(proc->blocks, gb_heap_allocator()); + gb_array_init(proc->blocks, gb_heap_allocator()); gb_array_init(proc->defer_stmts, gb_heap_allocator()); + gb_array_init(proc->children, gb_heap_allocator()); + proc->decl_block = ssa_add_block(proc, proc->type_expr, make_string("decls")); proc->entry_block = ssa_add_block(proc, proc->type_expr, make_string("entry")); proc->curr_block = proc->entry_block; @@ -1466,7 +1475,7 @@ ssaValue *ssa_add_local_slice(ssaProcedure *proc, Type *slice_type, ssaValue *ba ssaValue *ssa_add_global_string_array(ssaModule *m, String string) { - gbAllocator a = gb_heap_allocator(); + gbAllocator a = m->allocator; isize max_len = 4+8+1; u8 *str = cast(u8 *)gb_alloc_array(a, u8, max_len); @@ -2005,9 +2014,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case_end; case_ast_node(pl, ProcLit, expr); - if (proc->children == NULL) { - gb_array_init(proc->children, gb_heap_allocator()); - } // NOTE(bill): Generate a new name // parent$count isize name_len = proc->name.len + 1 + 8 + 1; @@ -2456,6 +2462,20 @@ 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_enum_to_string: { + ssa_emit_comment(proc, make_string("enum_to_string")); + ssaValue *x = ssa_build_expr(proc, ce->args[0]); + Type *t = ssa_type(x); + ssaValue *ti = ssa_type_info(proc, t); + + + ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 2); + args[0] = ti; + args[1] = ssa_emit_conv(proc, x, t_i64); + return ssa_emit_global_call(proc, "__enum_to_string", args, 2); + } break; } } } @@ -2673,7 +2693,6 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { String selector = unparen_expr(se->selector)->Ident.string; Type *type = get_base_type(type_of_expr(proc->module->info, se->expr)); - if (type == t_invalid) { // Imports Entity *imp = entity_of_ident(proc->module->info, se->expr); @@ -3039,13 +3058,15 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_end; case_ast_node(vd, VarDecl, node); + ssaModule *m = proc->module; + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); + if (gb_array_count(vd->names) == gb_array_count(vd->values)) { // 1:1 assigment gbArray(ssaAddr) lvals; gbArray(ssaValue *) inits; - gb_array_init_reserve(lvals, gb_heap_allocator(), gb_array_count(vd->names)); - gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(vd->names)); - defer (gb_array_free(lvals)); - defer (gb_array_free(inits)); + gb_array_init_reserve(lvals, m->tmp_allocator, gb_array_count(vd->names)); + gb_array_init_reserve(inits, m->tmp_allocator, gb_array_count(vd->names)); gb_for_array(i, vd->names) { AstNode *name = vd->names[i]; @@ -3079,10 +3100,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { } else { // Tuple(s) gbArray(ssaAddr) lvals; gbArray(ssaValue *) inits; - gb_array_init_reserve(lvals, gb_heap_allocator(), gb_array_count(vd->names)); - gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(vd->names)); - defer (gb_array_free(lvals)); - defer (gb_array_free(inits)); + gb_array_init_reserve(lvals, m->tmp_allocator, gb_array_count(vd->names)); + gb_array_init_reserve(inits, m->tmp_allocator, gb_array_count(vd->names)); gb_for_array(i, vd->names) { AstNode *name = vd->names[i]; @@ -3118,15 +3137,15 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_end; case_ast_node(pd, ProcDecl, node); - if (proc->children == NULL) { - gb_array_init(proc->children, gb_heap_allocator()); - } - - if (pd->body != NULL) { // NOTE(bill): Generate a new name // parent$name-guid - String pd_name = pd->name->Ident.string; + String original_name = pd->name->Ident.string; + String pd_name = original_name; + if (pd->link_name.len > 0) { + pd_name = pd->link_name; + } + 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); @@ -3205,11 +3224,15 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_ast_node(as, AssignStmt, node); ssa_emit_comment(proc, make_string("AssignStmt")); + + ssaModule *m = proc->module; + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); + switch (as->op.kind) { case Token_Eq: { gbArray(ssaAddr) lvals; - gb_array_init(lvals, gb_heap_allocator()); - defer (gb_array_free(lvals)); + gb_array_init(lvals, m->tmp_allocator); gb_for_array(i, as->lhs) { AstNode *lhs = as->lhs[i]; @@ -3227,8 +3250,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssa_lvalue_store(proc, lvals[0], init); } else { gbArray(ssaValue *) inits; - gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(lvals)); - defer (gb_array_free(inits)); + gb_array_init_reserve(inits, m->tmp_allocator, gb_array_count(lvals)); gb_for_array(i, as->rhs) { ssaValue *init = ssa_build_expr(proc, as->rhs[i]); @@ -3241,8 +3263,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { } } else { gbArray(ssaValue *) inits; - gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(lvals)); - defer (gb_array_free(inits)); + gb_array_init_reserve(inits, m->tmp_allocator, gb_array_count(lvals)); gb_for_array(i, as->rhs) { ssaValue *init = ssa_build_expr(proc, as->rhs[i]); |