Begin with on debugging symbol; fix version number 0.7.0

This commit is contained in:
gingerBill
2017-11-19 09:49:55 +00:00
parent 0c06a8d154
commit 2b0521347b
3 changed files with 203 additions and 102 deletions
+1 -1
View File
@@ -307,7 +307,7 @@ String get_fullpath_core(gbAllocator a, String path) {
} }
String const ODIN_VERSION = str_lit("0.6.2"); String const ODIN_VERSION = str_lit("0.7.0");
void init_build_context(void) { void init_build_context(void) {
BuildContext *bc = &build_context; BuildContext *bc = &build_context;
+74 -8
View File
@@ -11,7 +11,7 @@ struct irModule {
gbArena tmp_arena; gbArena tmp_arena;
gbAllocator allocator; gbAllocator allocator;
gbAllocator tmp_allocator; gbAllocator tmp_allocator;
// bool generate_debug_info; bool generate_debug_info;
u64 stmt_state_flags; u64 stmt_state_flags;
@@ -26,6 +26,9 @@ struct irModule {
Map<irDebugInfo *> debug_info; // Key: Unique pointer Map<irDebugInfo *> debug_info; // Key: Unique pointer
Map<irValue *> anonymous_proc_lits; // Key: AstNode * Map<irValue *> anonymous_proc_lits; // Key: AstNode *
irDebugInfo * debug_compile_unit;
i32 global_string_index; i32 global_string_index;
i32 global_array_index; // For ConstantSlice i32 global_array_index; // For ConstantSlice
i32 global_generated_index; i32 global_generated_index;
@@ -228,6 +231,7 @@ struct irProcedure {
irValue **args; \ irValue **args; \
isize arg_count; \ isize arg_count; \
irValue * context_ptr; \ irValue * context_ptr; \
irDebugInfo *debug_location; \
}) \ }) \
IR_INSTR_KIND(StartupRuntime, i32) \ IR_INSTR_KIND(StartupRuntime, i32) \
IR_INSTR_KIND(DebugDeclare, struct { \ IR_INSTR_KIND(DebugDeclare, struct { \
@@ -486,6 +490,8 @@ enum irDebugInfoKind {
irDebugInfo_Proc, irDebugInfo_Proc,
irDebugInfo_AllProcs, irDebugInfo_AllProcs,
irDebugInfo_Location,
irDebugInfo_BasicType, // basic types irDebugInfo_BasicType, // basic types
irDebugInfo_ProcType, irDebugInfo_ProcType,
irDebugInfo_DerivedType, // pointer, typedef irDebugInfo_DerivedType, // pointer, typedef
@@ -528,6 +534,10 @@ struct irDebugInfo {
struct { struct {
Array<irDebugInfo *> procs; Array<irDebugInfo *> procs;
} AllProcs; } AllProcs;
struct {
irDebugInfo *scope;
TokenPos pos;
} Location;
struct { struct {
@@ -1060,6 +1070,18 @@ irValue *ir_instr_call(irProcedure *p, irValue *value, irValue *return_ptr, irVa
v->Instr.Call.arg_count = arg_count; v->Instr.Call.arg_count = arg_count;
v->Instr.Call.type = result_type; v->Instr.Call.type = result_type;
v->Instr.Call.context_ptr = context_ptr; v->Instr.Call.context_ptr = context_ptr;
irDebugInfo **pp = map_get(&p->module->debug_info, hash_entity(p->entity));
if (pp != nullptr) {
GB_ASSERT_MSG(pp != nullptr, "%.*s %p", LIT(p->name), p->entity);
irDebugInfo *dl = ir_alloc_debug_info(p->module->allocator, irDebugInfo_Location);
dl->Location.scope = *pp;
dl->Location.pos = p->entity->token.pos;
map_set(&p->module->debug_info, hash_pointer(v), dl);
v->Instr.Call.debug_location = dl;
}
return v; return v;
} }
@@ -2483,6 +2505,49 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
#endif #endif
if (is_type_string(a)) {
char *runtime_proc = nullptr;
switch (op_kind) {
case Token_CmpEq: runtime_proc = "__string_eq"; break;
case Token_NotEq: runtime_proc = "__string_ne"; break;
case Token_Lt: runtime_proc = "__string_lt"; break;
case Token_Gt: runtime_proc = "__string_gt"; break;
case Token_LtEq: runtime_proc = "__string_le"; break;
case Token_GtEq: runtime_proc = "__string_gt"; break;
}
GB_ASSERT(runtime_proc != nullptr);
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 2);
args[0] = left;
args[1] = right;
return ir_emit_global_call(proc, runtime_proc, args, 2);
}
if (is_type_complex(a)) {
char *runtime_proc = "";
i64 sz = 8*type_size_of(proc->module->allocator, a);
switch (sz) {
case 64:
switch (op_kind) {
case Token_CmpEq: runtime_proc = "__complex64_eq"; break;
case Token_NotEq: runtime_proc = "__complex64_ne"; break;
}
break;
case 128:
switch (op_kind) {
case Token_CmpEq: runtime_proc = "__complex128_eq"; break;
case Token_NotEq: runtime_proc = "__complex128_ne"; break;
}
break;
}
GB_ASSERT(runtime_proc != nullptr);
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 2);
args[0] = left;
args[1] = right;
return ir_emit_global_call(proc, runtime_proc, args, 2);
}
return ir_emit(proc, ir_instr_binary_op(proc, op_kind, left, right, result)); return ir_emit(proc, ir_instr_binary_op(proc, op_kind, left, right, result));
} }
@@ -7600,6 +7665,8 @@ void ir_init_module(irModule *m, Checker *c) {
m->tmp_allocator = gb_arena_allocator(&m->tmp_arena); m->tmp_allocator = gb_arena_allocator(&m->tmp_arena);
m->info = &c->info; m->info = &c->info;
m->generate_debug_info = build_context.ODIN_OS == "windows" && build_context.word_size == 8;
map_init(&m->values, heap_allocator()); map_init(&m->values, heap_allocator());
map_init(&m->members, heap_allocator()); map_init(&m->members, heap_allocator());
map_init(&m->debug_info, heap_allocator()); map_init(&m->debug_info, heap_allocator());
@@ -7706,6 +7773,8 @@ void ir_init_module(irModule *m, Checker *c) {
di->CompileUnit.producer = str_lit("odin"); di->CompileUnit.producer = str_lit("odin");
map_set(&m->debug_info, hash_pointer(m), di); map_set(&m->debug_info, hash_pointer(m), di);
m->debug_compile_unit = di;
} }
} }
@@ -8466,9 +8535,7 @@ void ir_gen_tree(irGen *s) {
isize all_proc_max_count = 0; isize all_proc_max_count = 0;
for_array(i, m->debug_info.entries) { for_array(i, m->debug_info.entries) {
auto *entry = &m->debug_info.entries[i]; irDebugInfo *di = m->debug_info.entries[i].value;
irDebugInfo *di = entry->value;
di->id = cast(i32)i;
if (di->kind == irDebugInfo_Proc) { if (di->kind == irDebugInfo_Proc) {
all_proc_max_count++; all_proc_max_count++;
} }
@@ -8480,13 +8547,13 @@ void ir_gen_tree(irGen *s) {
for_array(i, m->debug_info.entries) { for_array(i, m->debug_info.entries) {
auto *entry = &m->debug_info.entries[i]; irDebugInfo *di = m->debug_info.entries[i].value;
irDebugInfo *di = entry->value;
if (di->kind == irDebugInfo_Proc) { if (di->kind == irDebugInfo_Proc) {
array_add(&all_procs->AllProcs.procs, di); array_add(&all_procs->AllProcs.procs, di);
} }
} }
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
if (build_context.is_dll && !has_dll_main) { if (build_context.is_dll && !has_dll_main) {
// DllMain :: proc(inst: rawptr, reason: u32, reserved: rawptr) -> i32 // DllMain :: proc(inst: rawptr, reason: u32, reserved: rawptr) -> i32
@@ -8754,11 +8821,10 @@ void ir_gen_tree(irGen *s) {
for_array(i, m->debug_info.entries) { for_array(i, m->debug_info.entries) {
auto *entry = &m->debug_info.entries[i]; auto *entry = &m->debug_info.entries[i];
irDebugInfo *di = entry->value; irDebugInfo *di = entry->value;
di->id = cast(i32)i; di->id = cast(i32)(i+1);
} }
// m->layout = str_lit("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"); // m->layout = str_lit("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");
} }
+128 -93
View File
@@ -139,6 +139,49 @@ void ir_print_escape_string(irFileBuffer *f, String name, bool print_quotes, boo
} }
void ir_print_escape_path(irFileBuffer *f, String path) {
isize extra = 0;
for (isize i = 0; i < path.len; i++) {
u8 c = path[i];
if (!ir_valid_char(c)) {
extra += 2;
}
}
if (extra == 0) {
ir_write_string(f, path);
return;
}
char hex_table[] = "0123456789ABCDEF";
isize buf_len = path.len + extra + 2 + 1;
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
u8 *buf = gb_alloc_array(string_buffer_allocator, u8, buf_len);
isize j = 0;
for (isize i = 0; i < path.len; i++) {
u8 c = path[i];
if (ir_valid_char(c) || c == ':') {
buf[j++] = c;
} else if (c == '\\') {
buf[j++] = '/';
} else {
buf[j] = '\\';
buf[j+1] = hex_table[c >> 4];
buf[j+2] = hex_table[c & 0x0f];
j += 3;
}
}
ir_file_write(f, buf, j);
gb_temp_arena_memory_end(tmp);
}
void ir_print_encoded_local(irFileBuffer *f, String name) { void ir_print_encoded_local(irFileBuffer *f, String name) {
ir_write_byte(f, '%'); ir_write_byte(f, '%');
@@ -1245,32 +1288,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
if (gb_is_between(bo->op, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) { if (gb_is_between(bo->op, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
if (is_type_string(elem_type)) { if (is_type_string(elem_type)) {
ir_write_string(f, "call "); GB_PANIC("Unhandled string type");
ir_print_calling_convention(f, m, ProcCC_Odin);
ir_print_type(f, m, t_bool);
char *runtime_proc = "";
switch (bo->op) {
case Token_CmpEq: runtime_proc = "__string_eq"; break;
case Token_NotEq: runtime_proc = "__string_ne"; break;
case Token_Lt: runtime_proc = "__string_lt"; break;
case Token_Gt: runtime_proc = "__string_gt"; break;
case Token_LtEq: runtime_proc = "__string_le"; break;
case Token_GtEq: runtime_proc = "__string_gt"; break;
}
ir_write_byte(f, ' ');
ir_print_encoded_global(f, make_string_c(runtime_proc), false);
ir_write_byte(f, '(');
ir_print_type(f, m, type);
ir_write_byte(f, ' ');
ir_print_value(f, m, bo->left, type);
ir_write_string(f, str_lit(", "));
ir_print_type(f, m, type);
ir_write_byte(f, ' ');
ir_print_value(f, m, bo->right, type);
ir_write_string(f, ")\n");
return;
} else if (is_type_float(elem_type)) { } else if (is_type_float(elem_type)) {
ir_write_string(f, "fcmp "); ir_write_string(f, "fcmp ");
switch (bo->op) { switch (bo->op) {
@@ -1282,37 +1300,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
case Token_GtEq: ir_write_string(f, "oge"); break; case Token_GtEq: ir_write_string(f, "oge"); break;
} }
} else if (is_type_complex(elem_type)) { } else if (is_type_complex(elem_type)) {
ir_write_string(f, "call "); GB_PANIC("Unhandled complex type");
ir_print_calling_convention(f, m, ProcCC_Odin);
ir_print_type(f, m, t_bool);
char *runtime_proc = "";
i64 sz = 8*type_size_of(m->allocator, elem_type);
switch (sz) {
case 64:
switch (bo->op) {
case Token_CmpEq: runtime_proc = "__complex64_eq"; break;
case Token_NotEq: runtime_proc = "__complex64_ne"; break;
}
break;
case 128:
switch (bo->op) {
case Token_CmpEq: runtime_proc = "__complex128_eq"; break;
case Token_NotEq: runtime_proc = "__complex128_ne"; break;
}
break;
}
ir_write_byte(f, ' ');
ir_print_encoded_global(f, make_string_c(runtime_proc), false);
ir_write_byte(f, '(');
ir_print_type(f, m, type);
ir_write_byte(f, ' ');
ir_print_value(f, m, bo->left, type);
ir_write_string(f, str_lit(", "));
ir_print_type(f, m, type);
ir_write_byte(f, ' ');
ir_print_value(f, m, bo->right, type);
ir_write_string(f, ")\n");
return; return;
} else { } else {
ir_write_string(f, "icmp "); ir_write_string(f, "icmp ");
@@ -1475,7 +1463,13 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
ir_write_string(f, " noalias nonnull "); ir_write_string(f, " noalias nonnull ");
ir_print_value(f, m, call->context_ptr, t_context_ptr); ir_print_value(f, m, call->context_ptr, t_context_ptr);
} }
ir_write_string(f, ")\n"); ir_write_string(f, ")");
if (m->generate_debug_info && call->debug_location) {
ir_fprintf(f, ", !dbg !%d", call->debug_location->id);
}
ir_write_string(f, "\n");
break; break;
} }
@@ -1644,8 +1638,11 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
Entity *e = dd->entity; Entity *e = dd->entity;
String name = e->token.string; String name = e->token.string;
TokenPos pos = e->token.pos; TokenPos pos = e->token.pos;
// gb_printf("debug_declare %.*s\n", LIT(dd->entity->token.string));
ir_write_string(f, "; ");
if (!m->generate_debug_info) {
ir_write_string(f, "; ");
}
ir_write_string(f, "call void @llvm.dbg.declare("); ir_write_string(f, "call void @llvm.dbg.declare(");
ir_write_string(f, "metadata "); ir_write_string(f, "metadata ");
ir_print_type(f, m, vt); ir_print_type(f, m, vt);
@@ -1752,11 +1749,16 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
ir_write_string(f, ") "); ir_write_string(f, ") ");
switch (proc->inlining) { switch (proc->inlining) {
default:
ir_fprintf(f, "#0 ");
break;
case ProcInlining_no_inline: case ProcInlining_no_inline:
ir_write_string(f, "noinline "); ir_write_string(f, "noinline ");
ir_fprintf(f, "#0 ");
break; break;
case ProcInlining_inline: case ProcInlining_inline:
ir_write_string(f, "alwaysinline "); ir_write_string(f, "alwaysinline ");
ir_fprintf(f, "#1 ");
break; break;
} }
@@ -1766,12 +1768,13 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
if (di_ != nullptr) { if (di_ != nullptr) {
irDebugInfo *di = *di_; irDebugInfo *di = *di_;
GB_ASSERT(di->kind == irDebugInfo_Proc); GB_ASSERT(di->kind == irDebugInfo_Proc);
// ir_fprintf(f, "!dbg !%d ", di->id); ir_fprintf(f, "!dbg !%d ", di->id);
} }
} }
} }
if (proc->body != nullptr) { if (proc->body != nullptr) {
// ir_fprintf(f, "nounwind uwtable {\n"); // ir_fprintf(f, "nounwind uwtable {\n");
@@ -1844,6 +1847,13 @@ void print_llvm_ir(irGen *ir) {
irFileBuffer buf = {}, *f = &buf; irFileBuffer buf = {}, *f = &buf;
ir_file_buffer_init(f, &ir->output_file); ir_file_buffer_init(f, &ir->output_file);
if (m->generate_debug_info) {
ir_write_string(f, "target datalayout = \"e-m:w-i64:64-f80:128-n8:16:32:64-S128\"\n");
ir_write_string(f, "target triple = \"x86_64-pc-windows-msvc19.11.25508\"\n\n");
}
ir_print_encoded_local(f, str_lit("..opaque")); ir_print_encoded_local(f, str_lit("..opaque"));
ir_write_string(f, str_lit(" = type {};\n")); ir_write_string(f, str_lit(" = type {};\n"));
ir_print_encoded_local(f, str_lit("..string")); ir_print_encoded_local(f, str_lit("..string"));
@@ -1970,23 +1980,28 @@ void print_llvm_ir(irGen *ir) {
} }
#if 0 if (m->generate_debug_info) {
// if (m->generate_debug_info) {
{
ir_write_byte(f, '\n'); ir_write_byte(f, '\n');
i32 diec = m->debug_info.entries.count; i32 diec = m->debug_info.entries.count;
ir_fprintf(f, "!llvm.dbg.cu = !{!0}\n"); i32 di_version = diec+1;
ir_fprintf(f, "!llvm.ident = !{!%d}\n", diec+3); i32 di_debug_info = diec+2;
ir_fprintf(f, "!%d = !{i32 2, !\"Dwarf Version\", i32 4}\n", diec+0); i32 di_code_view = diec+3;
ir_fprintf(f, "!%d = !{i32 2, !\"Debug Info Version\", i32 3}\n", diec+1); i32 di_wchar_size = diec+4;
ir_fprintf(f, "!%d = !{i32 1, !\"PIC Level\", i32 2}\n", diec+2);
ir_fprintf(f, "!%d = !{!\"clang version 3.9.0 (branches/release_39)\"}\n", diec+3); ir_fprintf(f, "attributes #0 = {nounwind noinline optnone uwtable}\n");
ir_fprintf(f, "attributes #1 = {nounwind alwaysinline uwtable}\n");
ir_fprintf(f, "!llvm.dbg.cu = !{!%d}\n", m->debug_compile_unit->id);
ir_fprintf(f, "!llvm.ident = !{!%d}\n", di_version);
ir_fprintf(f, "!llvm.module.flags = !{!%d, !%d, !%d}\n", di_debug_info, di_code_view, di_wchar_size);
ir_fprintf(f, "!0 = !{}\n");
for_array(di_index, m->debug_info.entries) { for_array(di_index, m->debug_info.entries) {
MapIrDebugInfoEntry *entry = &m->debug_info.entries[di_index]; irDebugInfo *di = m->debug_info.entries[di_index].value;
irDebugInfo *di = entry->value;
ir_fprintf(f, "!%d = ", di->id); ir_fprintf(f, "!%d = ", di->id);
switch (di->kind) { switch (di->kind) {
@@ -1994,38 +2009,42 @@ void print_llvm_ir(irGen *ir) {
irDebugInfo *file = *map_get(&m->debug_info, hash_pointer(di->CompileUnit.file)); irDebugInfo *file = *map_get(&m->debug_info, hash_pointer(di->CompileUnit.file));
ir_fprintf(f, ir_fprintf(f,
"distinct !DICompileUnit(" "distinct !DICompileUnit("
"language: DW_LANG_Go, " // Is this good enough? "language: DW_LANG_C_plus_plus" // Is this good enough?
"file: !%d, " ", file: !%d"
"producer: \"clang version 3.9.0 (branches/release_39)\", " ", producer: \"Odin %.*s\""
"flags: \"\", " ", flags: \"\""
"runtimeVersion: 0, " ", runtimeVersion: 0"
"isOptimized: false, " ", isOptimized: false"
"emissionKind: FullDebug" ", emissionKind: FullDebug"
")", ")",
file->id); file->id, LIT(build_context.ODIN_VERSION));
break; break;
} }
case irDebugInfo_File: case irDebugInfo_File:
ir_fprintf(f, "!DIFile(filename: \""); ir_fprintf(f, "!DIFile(filename: \"");
ir_print_escape_string(f, di->File.filename, false); ir_print_escape_path(f, di->File.filename);
ir_fprintf(f, "\", directory: \""); ir_fprintf(f, "\", directory: \"");
ir_print_escape_string(f, di->File.directory, false); ir_print_escape_path(f, di->File.directory);
ir_fprintf(f, "\")"); ir_fprintf(f, "\"");
ir_fprintf(f, ")");
break; break;
case irDebugInfo_Proc: case irDebugInfo_Proc:
ir_fprintf(f, "distinct !DISubprogram(" ir_fprintf(f, "distinct !DISubprogram("
"name: \"%.*s\", " "name: \"%.*s\""
// "linkageName: \"\", " ", linkageName: \"%.*s\""
"file: !%d, " ", file: !%d"
"line: %td, " ", line: %td"
"isDefinition: true, " ", isDefinition: true"
"isLocal: false, " ", isLocal: true"
"unit: !0" ", flags: DIFlagPrototyped"
", isOptimized: false"
", unit: !%d"
")", ")",
LIT(di->Proc.entity->token.string),
LIT(di->Proc.name), LIT(di->Proc.name),
di->Proc.file->id, di->Proc.file->id, di->Proc.pos.line,
di->Proc.pos.line); m->debug_compile_unit->id);
break; break;
case irDebugInfo_AllProcs: case irDebugInfo_AllProcs:
@@ -2037,11 +2056,27 @@ void print_llvm_ir(irGen *ir) {
} }
ir_write_byte(f, '}'); ir_write_byte(f, '}');
break; break;
case irDebugInfo_Location:
GB_ASSERT(di->Location.scope != nullptr);
ir_fprintf(f, "!DILocation(line: %td, column: %td, scope: !%d)",
di->Location.pos.line, di->Location.pos.column, di->Location.scope->id);
break;
default:
GB_PANIC("Unhandled irDebugInfo kind %d", di->kind);
break;
} }
ir_write_byte(f, '\n'); ir_write_byte(f, '\n');
} }
ir_fprintf(f, "!%d = !{!\"Odin version %.*s \"}\n", di_version, LIT(build_context.ODIN_VERSION));
ir_fprintf(f, "!%d = !{i32 2, !\"Debug Info Version\", i32 3}\n", di_debug_info);
ir_fprintf(f, "!%d = !{i32 2, !\"CodeView\", i32 1}\n", di_code_view);
ir_fprintf(f, "!%d = !{i32 1, !\"wchar_size\", i32 2}\n", di_wchar_size);
} }
#endif
ir_file_buffer_destroy(f); ir_file_buffer_destroy(f);
} }