diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-09-16 19:46:48 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-09-16 19:46:48 +0100 |
| commit | eb424bb315a880bf52fe843733445dfb502c1525 (patch) | |
| tree | 70b625ca5169448662573ec7da75622013b247fc /src/codegen | |
| parent | 968de5aae886e87f395533283c17d77f31eabd0d (diff) | |
#import and #load
#import - imported entities will not get exported
#load - loaded entities will get exported
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/codegen.cpp | 22 | ||||
| -rw-r--r-- | src/codegen/print_llvm.cpp | 104 | ||||
| -rw-r--r-- | src/codegen/ssa.cpp | 140 |
3 files changed, 237 insertions, 29 deletions
diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index f45c852c8..04f1f88ea 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -150,7 +150,7 @@ void ssa_gen_tree(ssaGen *s) { name = pd->foreign_name; } - ssaValue *p = ssa_make_value_procedure(a, m, e->type, decl->type_expr, body, name); + ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); p->Proc.tags = pd->tags; map_set(&m->values, hash_pointer(e), p); @@ -169,6 +169,22 @@ void ssa_gen_tree(ssaGen *s) { ssa_build_proc(v, NULL); } + 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()); + 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; + + + 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) { + gb_array_append(all_procs->AllProcs.procs, di); + } + } { // Startup Runtime @@ -178,7 +194,7 @@ void ssa_gen_tree(ssaGen *s) { NULL, 0, NULL, 0, false); AstNode *body = gb_alloc_item(a, AstNode); - ssaValue *p = ssa_make_value_procedure(a, m, proc_type, NULL, body, name); + ssaValue *p = ssa_make_value_procedure(a, m, NULL, proc_type, NULL, body, name); Token token = {}; token.string = name; Entity *e = make_entity_procedure(a, NULL, token, proc_type); @@ -523,6 +539,8 @@ void ssa_gen_tree(ssaGen *s) { } + + // 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"); diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index d0debf173..a621af244 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -766,8 +766,7 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { if (proc->tags & ProcTag_stdcall) { ssa_fprintf(f, "cc 64 "); - } - if (proc->tags & ProcTag_fastcall) { + } else if (proc->tags & ProcTag_fastcall) { ssa_fprintf(f, "cc 65 "); } @@ -803,28 +802,34 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { ssa_fprintf(f, ") "); - if (proc->tags != 0) { - if (proc->tags & ProcTag_inline) { - ssa_fprintf(f, "alwaysinline "); - } - if (proc->tags & ProcTag_no_inline) { - ssa_fprintf(f, "noinline "); - } + if (proc->tags & ProcTag_inline) { + ssa_fprintf(f, "alwaysinline "); + } + if (proc->tags & ProcTag_no_inline) { + 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->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)); + GB_ASSERT(di->kind == ssaDebugInfo_Proc); + ssa_fprintf(f, "!dbg !%d ", di->id); + } - if (proc->tags & ProcTag_foreign) { - ssa_fprintf(f, "; foreign\n"); - } + + if (proc->tags & ProcTag_foreign) { + ssa_fprintf(f, "; foreign\n"); } if (proc->body != NULL) { // ssa_fprintf(f, "nounwind uwtable {\n"); + ssa_fprintf(f, "{\n"); gb_for_array(i, proc->blocks) { ssaBlock *block = proc->blocks[i]; @@ -934,4 +939,67 @@ void ssa_print_llvm_ir(ssaFileBuffer *f, ssaModule *m) { } ssa_fprintf(f, "\n"); } + + + if (m->generate_debug_info) { + ssa_fprintf(f, "\n"); + ssa_fprintf(f, "!llvm.dbg.cu = !{!0}\n"); + + gb_for_array(di_index, m->debug_info.entries) { + auto *entry = &m->debug_info.entries[di_index]; + ssaDebugInfo *di = entry->value; + ssa_fprintf(f, "!%d = ", di->id); + defer (ssa_fprintf(f, "\n")); + + switch (di->kind) { + case ssaDebugInfo_CompileUnit: { + auto *cu = &di->CompileUnit; + ssaDebugInfo *file = *map_get(&m->debug_info, hash_pointer(cu->file)); + ssa_fprintf(f, + "distinct !DICompileUnit(" + "language: DW_LANG_Go, " // Is this good enough? + "file: !%d, " + "producer: \"%.*s\", " + "flags: \"\", " + "runtimeVersion: 0, " + "isOptimized: false, " + "emissionKind: FullDebug" + ")", + file->id, LIT(cu->producer)); + + } break; + case ssaDebugInfo_File: + ssa_fprintf(f, "!DIFile(filename: \""); + ssa_print_escape_string(f, di->File.filename, false); + ssa_fprintf(f, "\", directory: \""); + ssa_print_escape_string(f, di->File.directory, false); + ssa_fprintf(f, "\")"); + break; + case ssaDebugInfo_Proc: + ssa_fprintf(f, "distinct !DISubprogram(" + "name: \"%.*s\", " + // "linkageName: \"\", " + "file: !%d, " + "line: %td, " + "isDefinition: true, " + "isLocal: false, " + "unit: !0" + ")", + LIT(di->Proc.name), + di->Proc.file->id, + di->Proc.pos.line); + break; + + case ssaDebugInfo_AllProcs: + ssa_fprintf(f, "!{"); + gb_for_array(proc_index, di->AllProcs.procs) { + ssaDebugInfo *p = di->AllProcs.procs[proc_index]; + if (proc_index > 0) {ssa_fprintf(f, ",");} + ssa_fprintf(f, "!%d", p->id); + } + ssa_fprintf(f, "}"); + break; + } + } + } } diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index f1c888fa7..fac8423b0 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -4,19 +4,61 @@ struct ssaBlock; struct ssaValue; +enum ssaDebugInfoKind { + ssaDebugInfo_Invalid, + + ssaDebugInfo_CompileUnit, + ssaDebugInfo_File, + ssaDebugInfo_Proc, + ssaDebugInfo_AllProcs, + + ssaDebugInfo_Count, +}; + +struct ssaDebugInfo { + ssaDebugInfoKind kind; + i32 id; + + union { + struct { + AstFile *file; + String producer; + ssaDebugInfo *all_procs; + } CompileUnit; + struct { + AstFile *file; + String filename; + String directory; + } File; + struct { + Entity * entity; + String name; + ssaDebugInfo *file; + TokenPos pos; + } Proc; + struct { + gbArray(ssaDebugInfo *) procs; + } AllProcs; + }; +}; + struct ssaModule { CheckerInfo * info; BaseTypeSizes sizes; gbArena arena; gbAllocator allocator; + b32 generate_debug_info; u32 stmt_state_flags; + // String source_filename; String layout; + // String triple; - Map<ssaValue *> values; // Key: Entity * - Map<ssaValue *> members; // Key: String - i32 global_string_index; + Map<ssaValue *> values; // Key: Entity * + Map<ssaValue *> members; // Key: String + Map<ssaDebugInfo *> debug_info; // Key: Unique pointer + i32 global_string_index; }; @@ -55,6 +97,7 @@ struct ssaProcedure { ssaProcedure *parent; gbArray(ssaProcedure *) children; + Entity * entity; ssaModule * module; String name; Type * type; @@ -310,6 +353,12 @@ void ssa_module_add_value(ssaModule *m, Entity *e, ssaValue *v) { map_set(&m->values, hash_pointer(e), v); } +ssaDebugInfo *ssa_alloc_debug_info(gbAllocator a, ssaDebugInfoKind kind) { + ssaDebugInfo *di = gb_alloc_item(a, ssaDebugInfo); + di->kind = kind; + return di; +} + void ssa_init_module(ssaModule *m, Checker *c) { // TODO(bill): Determine a decent size for the arena isize token_count = c->parser->total_token_count; @@ -319,8 +368,9 @@ void ssa_init_module(ssaModule *m, Checker *c) { m->info = &c->info; m->sizes = c->sizes; - map_init(&m->values, gb_heap_allocator()); - map_init(&m->members, gb_heap_allocator()); + map_init(&m->values, gb_heap_allocator()); + map_init(&m->members, gb_heap_allocator()); + map_init(&m->debug_info, gb_heap_allocator()); // Default states m->stmt_state_flags = 0; @@ -376,11 +426,20 @@ void ssa_init_module(ssaModule *m, Checker *c) { map_set(&m->members, hash_string(name), g); } } + + { + ssaDebugInfo *di = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_CompileUnit); + di->CompileUnit.file = m->info->files.entries[0].value; // Zeroth is the init file + di->CompileUnit.producer = make_string("odin"); + + map_set(&m->debug_info, hash_pointer(m), di); + } } void ssa_destroy_module(ssaModule *m) { map_destroy(&m->values); map_destroy(&m->members); + map_destroy(&m->debug_info); gb_arena_free(&m->arena); } @@ -445,6 +504,46 @@ Type *ssa_type(ssaValue *value) { return NULL; } +ssaDebugInfo *ssa_add_debug_info_file(ssaProcedure *proc, AstFile *file) { + GB_ASSERT(file != NULL); + ssaDebugInfo *di = ssa_alloc_debug_info(proc->module->allocator, ssaDebugInfo_File); + di->File.file = file; + + String filename = file->tokenizer.fullpath; + String directory = filename; + isize slash_index = 0; + for (isize i = filename.len-1; i >= 0; i--) { + if (filename.text[i] == '\\' || + filename.text[i] == '/') { + break; + } + slash_index = i; + } + directory.len = slash_index-1; + filename.text = filename.text + slash_index; + filename.len -= slash_index; + + + di->File.filename = filename; + di->File.directory = directory; + + map_set(&proc->module->debug_info, hash_pointer(file), di); + return di; +} + + +ssaDebugInfo *ssa_add_debug_info_proc(ssaProcedure *proc, Entity *entity, String name, ssaDebugInfo *file) { + GB_ASSERT(entity != NULL); + ssaDebugInfo *di = ssa_alloc_debug_info(proc->module->allocator, ssaDebugInfo_Proc); + di->Proc.entity = entity; + di->Proc.name = name; + di->Proc.file = file; + di->Proc.pos = entity->token.pos; + + map_set(&proc->module->debug_info, hash_pointer(entity), di); + return di; +} + @@ -674,9 +773,10 @@ ssaValue *ssa_make_const_bool(gbAllocator a, b32 b) { } -ssaValue *ssa_make_value_procedure(gbAllocator a, ssaModule *m, Type *type, AstNode *type_expr, AstNode *body, String name) { +ssaValue *ssa_make_value_procedure(gbAllocator a, ssaModule *m, Entity *entity, Type *type, AstNode *type_expr, AstNode *body, String name) { ssaValue *v = ssa_alloc_value(a, ssaValue_Proc); v->Proc.module = m; + v->Proc.entity = entity; v->Proc.type = type; v->Proc.type_expr = type_expr; v->Proc.body = body; @@ -1919,7 +2019,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue Type *type = type_of_expr(proc->module->info, expr); ssaValue *value = ssa_make_value_procedure(proc->module->allocator, - proc->module, type, pl->type, pl->body, name); + proc->module, NULL, type, pl->type, pl->body, name); value->Proc.tags = pl->tags; @@ -3053,7 +3153,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.string)); Entity *e = *found; ssaValue *value = ssa_make_value_procedure(proc->module->allocator, - proc->module, e->type, pd->type, pd->body, name); + proc->module, e, e->type, pd->type, pd->body, name); value->Proc.tags = pd->tags; @@ -3072,7 +3172,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { Entity *e = *map_get(&info->definitions, hash_pointer(pd->name)); Entity *f = *map_get(&info->foreign_procs, hash_string(name)); ssaValue *value = ssa_make_value_procedure(proc->module->allocator, - proc->module, e->type, pd->type, pd->body, name); + proc->module, e, e->type, pd->type, pd->body, name); value->Proc.tags = pd->tags; @@ -3594,6 +3694,28 @@ void ssa_build_proc(ssaValue *value, ssaProcedure *parent) { proc->parent = parent; + if (proc->entity != NULL) { + ssaModule *m = proc->module; + CheckerInfo *info = m->info; + Entity *e = proc->entity; + String filename = e->token.pos.file; + AstFile **found = map_get(&info->files, hash_string(filename)); + GB_ASSERT(found != NULL); + AstFile *f = *found; + ssaDebugInfo *di_file = NULL; + + + ssaDebugInfo **di_file_found = map_get(&m->debug_info, hash_pointer(f)); + if (di_file_found) { + di_file = *di_file_found; + GB_ASSERT(di_file->kind == ssaDebugInfo_File); + } else { + di_file = ssa_add_debug_info_file(proc, f); + } + + ssa_add_debug_info_proc(proc, e, proc->name, di_file); + } + if (proc->body != NULL) { u32 prev_stmt_state_flags = proc->module->stmt_state_flags; defer (proc->module->stmt_state_flags = prev_stmt_state_flags); |