diff options
| author | lachsinc <lachlansinclair@gmail.com> | 2018-09-05 21:11:51 +1000 |
|---|---|---|
| committer | lachsinc <lachlansinclair@gmail.com> | 2018-09-18 10:50:56 +1000 |
| commit | 2f86f8f8e0618a88c2794362e5f99db29876ef9d (patch) | |
| tree | 98b8d01fb4321f23421ee1cd05207c0d9e619d20 /src/ir_print.cpp | |
| parent | 02f9a27f46de80f06d0e2b1409c223d39ae46bae (diff) | |
Provide llvm ir with more debug info (for Visual Studio debugger support).
Diffstat (limited to 'src/ir_print.cpp')
| -rw-r--r-- | src/ir_print.cpp | 144 |
1 files changed, 134 insertions, 10 deletions
diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 5796845fb..d77657222 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -519,6 +519,36 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) { } } +void ir_print_debug_encoding(irFileBuffer *f, irDebugInfoKind kind, irDebugEncoding encoding) { + switch (kind) { + case irDebugInfo_BasicType: + switch (encoding) { + case irDebugBasicEncoding_address: ir_write_str_lit(f, "DW_ATE_address"); return; + case irDebugBasicEncoding_boolean: ir_write_str_lit(f, "DW_ATE_boolean"); return; + case irDebugBasicEncoding_float: ir_write_str_lit(f, "DW_ATE_float"); return; + case irDebugBasicEncoding_signed: ir_write_str_lit(f, "DW_ATE_signed"); return; + case irDebugBasicEncoding_signed_char: ir_write_str_lit(f, "DW_ATE_signed_char"); return; + case irDebugBasicEncoding_unsigned: ir_write_str_lit(f, "DW_ATE_unsigned"); return; + case irDebugBasicEncoding_unsigned_char: ir_write_str_lit(f, "DW_ATE_unsigned_char"); return; + } + case irDebugInfo_DerivedType: + switch (encoding) { + case irDebugBasicEncoding_member: ir_write_str_lit(f, "DW_TAG_member"); return; + case irDebugBasicEncoding_pointer_type: ir_write_str_lit(f, "DW_TAG_pointer_type"); return; + case irDebugBasicEncoding_typedef: ir_write_str_lit(f, "DW_TAG_typedef"); return; + } + case irDebugInfo_CompositeType: + switch (encoding) { + case irDebugBasicEncoding_array_type: ir_write_str_lit(f, "DW_TAG_array_type"); return; + case irDebugBasicEncoding_enumeration_type: ir_write_str_lit(f, "DW_TAG_enumeration_type"); return; + case irDebugBasicEncoding_structure_type: ir_write_str_lit(f, "DW_TAG_structure_type"); return; + case irDebugBasicEncoding_union_type: ir_write_str_lit(f, "DW_TAG_union_type"); return; + } + } + + GB_PANIC("Unreachable"); +} + void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type); void ir_print_compound_element(irFileBuffer *f, irModule *m, ExactValue v, Type *elem_type) { @@ -1518,16 +1548,17 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { String name = e->token.string; TokenPos pos = e->token.pos; + irDebugInfo **lookup_di = map_get(&m->debug_info, hash_entity(e)); + GB_ASSERT_NOT_NULL(*lookup_di); + irDebugInfo* local_var_di = *lookup_di; + ir_write_str_lit(f, "call void @llvm.dbg.declare("); ir_write_str_lit(f, "metadata "); ir_print_type(f, m, vt); ir_write_byte(f, ' '); ir_print_value(f, m, dd->value, vt); - ir_write_str_lit(f, ", metadata !DILocalVariable(name: \""); - ir_print_escape_string(f, name, false, false); - ir_fprintf(f, "\", scope: !%d, line: %td)", di->id, pos.line); - ir_write_str_lit(f, ", metadata !DIExpression()"); - ir_write_byte(f, ')'); + ir_fprintf(f, ", metadata !%d", local_var_di->id); + ir_write_str_lit(f, ", metadata !DIExpression())"); ir_fprintf(f, ", !dbg !DILocation(line: %td, column: %td, scope: !%d)", pos.line, pos.column, di->id); break; } @@ -1764,7 +1795,7 @@ void print_llvm_ir(irGen *ir) { ir_print_type(f, m, t_typeid); ir_write_str_lit(f, "} ; Basic_any\n"); - ir_write_str_lit(f, "declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone \n"); + ir_write_str_lit(f, "declare void @llvm.dbg.declare(metadata, metadata, metadata) #3 \n"); ir_write_byte(f, '\n'); @@ -1875,9 +1906,11 @@ void print_llvm_ir(irGen *ir) { ir_write_byte(f, '\n'); } + // TODO(lachsinc): Attribute map inside ir module? ir_fprintf(f, "attributes #0 = {nounwind uwtable}\n"); ir_fprintf(f, "attributes #1 = {nounwind alwaysinline uwtable}\n"); ir_fprintf(f, "attributes #2 = {nounwind noinline optnone uwtable}\n"); + ir_fprintf(f, "attributes #3 = {nounwind readnone}\n"); if (m->generate_debug_info) { ir_write_byte(f, '\n'); @@ -1909,7 +1942,7 @@ void print_llvm_ir(irGen *ir) { "language: DW_LANG_C_plus_plus" // Is this good enough? ", file: !%d" ", producer: \"Odin %.*s\"" - ", flags: \"\"" + // ", flags: \"\"" // TODO(lachsinc): Removed for now, check if correct ", runtimeVersion: 0" ", isOptimized: false" ", emissionKind: FullDebug" @@ -1938,13 +1971,104 @@ void print_llvm_ir(irGen *ir) { ", flags: DIFlagPrototyped" ", isOptimized: false" ", unit: !%d" - ")", + ", type: !DISubroutineType(types: !{", LIT(di->Proc.entity->token.string), LIT(di->Proc.name), - di->Proc.file->id, di->Proc.pos.line, + di->Proc.file->id, + di->Proc.pos.line, m->debug_compile_unit->id); + if (di->Proc.return_types.count == 0) { + ir_fprintf(f, "null})"); + } else { + for_array(return_type_index, di->Proc.return_types) { + ir_fprintf(f, "%s!%d", + return_type_index > 0 ? ", " : "", + di->Proc.return_types[return_type_index]->id); + } + ir_write_str_lit(f, "})"); + } + ir_write_byte(f, ')'); break; - + case irDebugInfo_LocalVariable: { + ir_fprintf(f, "!DILocalVariable(" + "name: \"%.*s\"" + ", scope: !%d" + ", file: !%d" + ", line: %d" + ", type: !%d", + LIT(di->LocalVariable.name), + di->LocalVariable.scope->id, + di->LocalVariable.file->id, + di->LocalVariable.pos.line, + di->LocalVariable.type->id); + if (di->LocalVariable.arg > 0) { + GB_ASSERT(false); // TODO(lachsinc): "Arg" debug info not implemented yet + ir_fprintf(f, ", arg: %d", di->LocalVariable.arg); + } + ir_write_byte(f, ')'); + break; + } + case irDebugInfo_BasicType: + ir_fprintf(f, "!DIBasicType(" + "name: \"%.*s\"" + ", size: %d" + ", encoding: ", + LIT(di->BasicType.name), + di->BasicType.size); + ir_print_debug_encoding(f, irDebugInfo_BasicType, di->BasicType.encoding); + ir_write_byte(f, ')'); + break; + case irDebugInfo_DerivedType: + GB_ASSERT(di->DerivedType.base_type); + ir_fprintf(f, "!DIDerivedType(" + "name: \"%.*s\"" + ", baseType: !%d" + ", size: %d" + ", align: %d" + ", tag: ", + LIT(di->DerivedType.name), + di->DerivedType.base_type->id, + di->DerivedType.size, + di->DerivedType.align); + ir_print_debug_encoding(f, irDebugInfo_DerivedType, di->DerivedType.tag); + if (di->DerivedType.offset > 0) { + ir_fprintf(f, ", offset: %d", + di->DerivedType.offset); + } + ir_write_byte(f, ')'); + break; + case irDebugInfo_CompositeType: { + ir_fprintf(f, "!DICompositeType(" + "name: \"%.*s\"" + ", scope: !%d" + ", file: !%d" + ", line: %td" + ", size: %d" + ", align: %d" + ", tag: ", + LIT(di->CompositeType.name), + di->CompositeType.scope->id, + di->CompositeType.file->id, + di->CompositeType.pos.line, + di->CompositeType.size, + di->CompositeType.align); + ir_print_debug_encoding(f, irDebugInfo_CompositeType, di->CompositeType.tag); + if (di->CompositeType.base_type) { + GB_ASSERT(di->CompositeType.tag == irDebugBasicEncoding_enumeration_type); + ir_fprintf(f, ", baseType: !%d", di->CompositeType.base_type->id); + } + if (di->CompositeType.elements.count > 0) { + ir_write_str_lit(f, ", elements: !{"); + for_array(element_index, di->CompositeType.elements) { + ir_fprintf(f, "%s!%d", + element_index > 0 ? ", " : "", + di->CompositeType.elements[element_index]->id); + } + ir_write_byte(f, '}'); + } + ir_write_byte(f, ')'); + break; + } case irDebugInfo_AllProcs: ir_fprintf(f, "!{"); for_array(proc_index, di->AllProcs.procs) { |