aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/codegen.cpp22
-rw-r--r--src/codegen/print_llvm.cpp104
-rw-r--r--src/codegen/ssa.cpp140
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);