aboutsummaryrefslogtreecommitdiff
path: root/src/ir_print.cpp
diff options
context:
space:
mode:
authorlachsinc <lachlansinclair@gmail.com>2018-09-05 21:11:51 +1000
committerlachsinc <lachlansinclair@gmail.com>2018-09-18 10:50:56 +1000
commit2f86f8f8e0618a88c2794362e5f99db29876ef9d (patch)
tree98b8d01fb4321f23421ee1cd05207c0d9e619d20 /src/ir_print.cpp
parent02f9a27f46de80f06d0e2b1409c223d39ae46bae (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.cpp144
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) {